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.
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/PKG-INFO +2 -2
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/README.md +1 -1
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe.py +20 -7
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid.py +7 -7
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Zip_Bytes.py +2 -2
- osbot_utils-1.91.0/osbot_utils/helpers/python_compatibility/python_3_8.py +8 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Handler.py +21 -21
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/Type_Safe__Validator.py +14 -0
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Max.py +28 -0
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Min.py +38 -0
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__One_Of.py +18 -0
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/Validator__Regex.py +26 -0
- osbot_utils-1.91.0/osbot_utils/helpers/type_safe/validators/__init__.py +0 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__Attribute.py +7 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__Element.py +15 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File.py +9 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__Load.py +88 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__To_Dict.py +41 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/Xml__File__To_Xml.py +72 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/__init__.py +0 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Channel.py +17 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Enclosure.py +7 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Feed.py +11 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py +93 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Image.py +8 -0
- osbot_utils-1.91.0/osbot_utils/helpers/xml/rss/RSS__Item.py +17 -0
- osbot_utils-1.91.0/osbot_utils/testing/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Objects.py +46 -10
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Regex.py +1 -1
- osbot_utils-1.91.0/osbot_utils/utils/__init__.py +0 -0
- osbot_utils-1.91.0/osbot_utils/version +1 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/pyproject.toml +1 -1
- osbot_utils-1.89.0/osbot_utils/helpers/Xml_To_Dict.py +0 -87
- osbot_utils-1.89.0/osbot_utils/version +0 -1
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/LICENSE +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Cache_Pickle.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Kwargs_To_Disk.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Kwargs_To_Self.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__Base.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__Dict.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/Type_Safe__List.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/base_classes/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/async_invoke.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/capture_duration.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/disable_root_loggers.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/context_managers/print_duration.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/classes/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/classes/singleton.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/filter_list.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/group_by.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/lists/index_by.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_function.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_self.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/cache_on_tmp.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/capture_exception.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/capture_status.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/catch.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/context.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/depreciated.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/function_type_check.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/obj_as_context.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/remove_return_value.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/required_fields.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/decorators/methods/type_safe.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/Fluent_Dict.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/Fluent_List.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/fluent/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Edge.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Graph.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Node.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/Mermaid__Renderer.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Edge__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Node__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Render__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/examples/Mermaid_Examples__FlowChart.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram_Direction.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram__Type.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mermaid/models/Mermaid__Node__Shape.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Data.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Edge.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Node.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraph__Serializer.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/MGraphs.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/graphs/mgraph/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/CFormat.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/CPrint.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Dependency_Manager.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Dict_To_Attr.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Guid.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Hashicorp_Secrets.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Local_Cache.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Local_Caches.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Print_Table.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Python_Audit.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Guid.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Guid_Short.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Random_Seed.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Safe_Id.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Str_ASCII.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Timestamp_Now.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Type_Registry.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/Type_Safe_Method.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Base.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Data.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Load.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Merge.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Node.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Ast_Visit.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/Call_Tree.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Add.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Alias.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_And.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Argument.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Arguments.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Assert.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Assign.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Attribute.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Aug_Assign.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Bin_Op.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Bool_Op.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Break.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Call.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Class_Def.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Compare.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Comprehension.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Constant.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Continue.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Dict.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Eq.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Except_Handler.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Expr.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_For.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Function_Def.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Generator_Exp.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Gt.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_GtE.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_If.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_If_Exp.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Import.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Import_From.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_In.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Is.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Is_Not.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Keyword.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Lambda.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_List.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_List_Comp.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Load.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Lt.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_LtE.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Mod.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Module.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Mult.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Name.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not_Eq.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Not_In.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Or.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Pass.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Pow.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Raise.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Return.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Set.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Slice.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Starred.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Store.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Sub.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Subscript.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Try.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Tuple.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Unary_Op.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_While.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_With.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_With_Item.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/Ast_Yield.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ast/nodes/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Actions.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Data.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Invoke.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Row.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Table.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/cache_requests/flows/flow__Cache__Requests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Flow.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Flow__Events.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/Task.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/flow.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/decorators/task.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Data.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Type.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/flows/models/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Generator_Context_Manager.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Generator_Manager.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Model__Generator_State.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/Model__Generator_Target.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/generators/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Css.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Html.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Dict_To_Tags.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Html_To_Dict.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Html_To_Tag.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Base.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Body.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Div.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__H.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__HR.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Head.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Html.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Link.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/Tag__Style.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/html/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/Event__Queue.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Client.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Room.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Server.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/PubSub__Sqlite.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Connect.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Disconnect.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Execute_Method.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Join_Room.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Leave_Room.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Message.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/Schema__PubSub__Client.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/pubsub/schemas/__init__.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/helpers/sqlite → osbot_utils-1.91.0/osbot_utils/helpers/python_compatibility}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Capture_Sqlite_Error.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Cursor.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Database.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Field.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Globals.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Table.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Sqlite__Table__Create.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/cache → osbot_utils-1.91.0/osbot_utils/helpers/sqlite}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Schema__Table__Requests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Patch.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Sqlite.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Table.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/Sqlite__DB__Requests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/cache/TestCase__Sqlite__Cache__Requests.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/helpers/sqlite/domains → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/cache}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +0 -0
- {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
- {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
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py +0 -0
- {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
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sample_data/Sqlite__Sample_Data__Chinook.py +0 -0
- {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
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder__Select.py +0 -0
- {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
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/helpers/ssh → osbot_utils-1.91.0/osbot_utils/helpers/sqlite/tables}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SCP.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Cache__Requests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Execute.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Health_Check.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Linux.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Linux__Amazon.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/SSH__Python.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/ssh/TestCase__SSH.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/helpers/trace → osbot_utils-1.91.0/osbot_utils/helpers/ssh}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Config.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Graph.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Print_Traces.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stack.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stack_Node.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__Stats.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Call__View_Model.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/helpers/trace/Trace_Files.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/testing → osbot_utils-1.91.0/osbot_utils/helpers/trace}/__init__.py +0 -0
- {osbot_utils-1.89.0/osbot_utils/utils → osbot_utils-1.91.0/osbot_utils/helpers/type_safe}/__init__.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Catch.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Custom_Handler_For_Http_Tests.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Duration.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Hook_Method.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Log_To_Queue.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Log_To_String.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Logging.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Patch_Print.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Profiler.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Pytest.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Stderr.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Stdout.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Env_Vars.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_File.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Folder.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Sys_Path.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Web_Server.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Zip.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Temp_Zip_In_Memory.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Unit_Test.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/testing/Unzip_File.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Assert.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Call_Stack.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Csv.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Dev.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Env.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Exceptions.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Files.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Functions.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Http.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Int.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Json.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Json_Cache.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Lists.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Misc.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Png.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Process.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Python_Logger.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Status.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Str.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Threads.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Toml.py +0 -0
- {osbot_utils-1.89.0 → osbot_utils-1.91.0}/osbot_utils/utils/Version.py +0 -0
- {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.
|
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
|
-

|
27
27
|
[](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
|
-

|
6
6
|
[](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
|
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
|
69
|
-
from osbot_utils.utils.Objects
|
70
|
-
from osbot_utils.utils.Objects
|
71
|
-
from osbot_utils.utils.Objects
|
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 =
|
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
|
2
|
-
from osbot_utils.graphs.mermaid.Mermaid__Edge
|
3
|
-
from osbot_utils.graphs.mermaid.Mermaid__Graph
|
4
|
-
from osbot_utils.graphs.mermaid.models.Mermaid__Diagram_Direction
|
5
|
-
from osbot_utils.graphs.mermaid.models.Mermaid__Diagram__Type
|
6
|
-
from osbot_utils.utils.Python_Logger
|
7
|
-
from osbot_utils.base_classes.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
|
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,
|
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):
|
@@ -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'
|
12
|
-
'
|
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'
|
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'
|
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
|
File without changes
|
@@ -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,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]
|