osbot-utils 2.63.0__tar.gz → 2.65.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-2.63.0 → osbot_utils-2.65.0}/PKG-INFO +2 -2
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/README.md +1 -1
- osbot_utils-2.65.0/osbot_utils/decorators/methods/cache_on_self.py +51 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/Cache_Controller.py +28 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/Cache_Key_Generator.py +113 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/Cache_Metrics.py +31 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/Cache_On_Self.py +124 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/Cache_Storage.py +33 -0
- osbot_utils-2.65.0/osbot_utils/helpers/cache_on_self/__init__.py +145 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Method.py +23 -12
- osbot_utils-2.65.0/osbot_utils/type_safe/decorators/type_safe.py +20 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Raise_Exception.py +2 -2
- osbot_utils-2.65.0/osbot_utils/version +1 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/pyproject.toml +1 -1
- osbot_utils-2.63.0/osbot_utils/decorators/methods/cache_on_self.py +0 -80
- osbot_utils-2.63.0/osbot_utils/type_safe/decorators/type_safe.py +0 -12
- osbot_utils-2.63.0/osbot_utils/version +0 -1
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/LICENSE +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/base_classes/Cache_Pickle.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/base_classes/Kwargs_To_Disk.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/base_classes/Kwargs_To_Self.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/base_classes/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/context_managers/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/context_managers/async_invoke.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/context_managers/disable_root_loggers.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/classes/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/classes/singleton.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/lists/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/lists/filter_list.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/lists/group_by.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/lists/index_by.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/cache_on_function.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/cache_on_tmp.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/capture_exception.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/capture_status.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/catch.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/context.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/depreciated.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/function_type_check.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/obj_as_context.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/remove_return_value.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/decorators/methods/required_fields.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/fluent/Fluent_Dict.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/fluent/Fluent_List.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/fluent/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/CFormat.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/CPrint.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Dependency_Manager.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Dict_To_Attr.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Guid.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Hashicorp_Secrets.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Local_Cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Local_Caches.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Obj_Id.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Print_Table.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Python_Audit.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Random_Guid.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Random_Guid_Short.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Random_Seed.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Safe_Id.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Str_ASCII.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Timestamp_Now.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Type_Registry.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/Zip_Bytes.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Base.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Load.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Merge.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Node.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Ast_Visit.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/Call_Tree.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Add.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Alias.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_And.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Argument.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Arguments.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Assert.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Assign.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Attribute.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Aug_Assign.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Bin_Op.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Bool_Op.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Break.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Call.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Class_Def.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Compare.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Comprehension.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Constant.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Continue.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Dict.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Eq.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Except_Handler.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Expr.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_For.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Function_Def.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Generator_Exp.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Gt.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_GtE.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_If.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_If_Exp.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Import.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Import_From.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_In.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Is.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Is_Not.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Keyword.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Lambda.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_List.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_List_Comp.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Load.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Lt.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_LtE.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Mod.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Module.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Mult.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Name.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Not.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Not_Eq.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Not_In.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Or.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Pass.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Pow.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Raise.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Return.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Set.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Slice.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Starred.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Store.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Sub.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Subscript.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Try.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Tuple.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Unary_Op.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_While.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_With.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_With_Item.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/Ast_Yield.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ast/nodes/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Actions.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Config.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Invoke.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Row.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/Cache__Requests__Table.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/cache_requests/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/Duration.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/decorators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/decorators/capture_duration.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/decorators/duration.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/decorators/print_duration.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/schemas/Schema__Duration.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/duration/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/Flow.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/Task.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/actions/Flow__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/actions/Flow__Events.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/actions/Flow__Stats__Collector.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/actions/Task__Stats__Collector.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/actions/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/decorators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/decorators/flow.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/decorators/task.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Flow_Run__Config.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Flow_Run__Event.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Flow_Run__Event_Type.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Schema__Flow__Artifact.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/Schema__Flow__Result.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/models/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Event.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Event__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Log.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Stats.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Status.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Flow__Task__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/Schema__Task__Stats.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/flows/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/generators/Generator_Context_Manager.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/generators/Generator_Manager.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/generators/Model__Generator_State.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/generators/Model__Generator_Target.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/generators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/CSS_Dict__To__Css.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html_Dict__To__Html.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html_Dict__To__Html_Document.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html_Dict__To__Html_Tags.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html__To__Html_Dict.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html__To__Html_Document.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Html__To__Html_Tag.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Base.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Body.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Div.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__H.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__HR.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Head.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Html.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Link.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Style.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/Tag__Text.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/schemas/Schema__Html_Document.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/schemas/Schema__Html_Node.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/schemas/Schema__Html_Node__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/schemas/Schema__Html_Node__Data__Type.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/html/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/actions/LLM_Request__Execute.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/actions/Type_Safe__Schema_For__LLMs.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/actions/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/builders/LLM_Request__Builder.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/builders/LLM_Request__Builder__Open_AI.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/builders/LLM_Request__Factory.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/builders/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/LLM_Cache__Path_Generator.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/LLM_Request__Cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/LLM_Request__Cache__File_System.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/LLM_Request__Cache__Storage.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/Virtual_Storage__Local__Folder.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/Virtual_Storage__Sqlite.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/cache/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/platforms/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/platforms/open_ai/API__LLM__Open_AI.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/platforms/open_ai/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Cache__Index.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Request.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Data.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Function_Call.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Message__Content.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Request__Message__Role.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Response.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/Schema__LLM_Response__Cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/llms/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/Event__Queue.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/PubSub__Client.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/PubSub__Room.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/PubSub__Server.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/PubSub__Sqlite.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Connect.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Disconnect.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Execute_Method.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Join_Room.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Leave_Room.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Message.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/Schema__PubSub__Client.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/pubsub/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/python_compatibility/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/python_compatibility/python_3_8.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_float/Safe_Float.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_float/Safe_Float__Engineering.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_float/Safe_Float__Money.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_float/Safe_Float__Percentage_Exact.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_float/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_Int.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_UInt.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_UInt__Byte.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_UInt__FileSize.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_UInt__Percentage.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/Safe_UInt__Port.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_int/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__File__Name.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__File__Path.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__Hash.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__Text.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__Text__Dangerous.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/Safe_Str__Url.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/Safe_Str__Html.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/Safe_Str__Http__Content_Type.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/Safe_Str__Http__ETag.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/Safe_Str__Http__Last_Modified.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/Safe_Str__Http__Text.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/safe_str/http/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Capture_Sqlite_Error.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Cursor.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Database.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Field.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Globals.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Table.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Sqlite__Table__Create.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Schema__Table__Requests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Patch.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Sqlite.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Sqlite__Cache__Requests__Table.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/Sqlite__DB__Requests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/TestCase__Sqlite__Cache__Requests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/cache/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/domains/schemas/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/models/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/sample_data/Sqlite__Sample_Data__Chinook.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/sample_data/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder__Select.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/sql_builder/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Config.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/sqlite/tables/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SCP.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Cache__Requests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Execute.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Health_Check.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Linux.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Linux__Amazon.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/SSH__Python.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/TestCase__SSH.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/ssh/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Config.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Handler.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Print_Traces.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Stack.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Stack_Node.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__Stats.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Call__View_Model.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/Trace_Files.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/trace/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__Attribute.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__Element.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__File.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__File__Load.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__File__To_Dict.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/Xml__File__To_Xml.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Channel.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Enclosure.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Feed.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Feed__Parser.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Image.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/helpers/xml/rss/RSS__Item.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Catch.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Custom_Handler_For_Http_Tests.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Hook_Method.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Log_To_Queue.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Log_To_String.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Logging.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Patch_Print.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Profiler.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Pytest.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Stderr.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Stdout.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Env_Vars.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_File.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Folder.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Sys_Path.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Web_Server.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Zip.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Temp_Zip_In_Memory.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Unit_Test.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/Unzip_File.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/performance/Performance_Measure__Session.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/performance/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/performance/models/Model__Performance_Measure__Measurement.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/performance/models/Model__Performance_Measure__Result.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/testing/performance/models/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Base.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Dict.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__List.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Primitive.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Set.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/Type_Safe__Tuple.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/decorators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/methods/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/methods/type_safe_property.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Annotations.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Convert.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Json_Compressor.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Json_Compressor__Type_Registry.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Not_Cached.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Shared__Variables.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/Type_Safe__Validation.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/shared/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__Class_Kwargs.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__Default_Kwargs.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__Default_Value.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__From_Json.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__Init.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/Type_Safe__Step__Set_Attr.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/steps/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/Type_Safe__Validator.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/Validator__Max.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/Validator__Min.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/Validator__One_Of.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/Validator__Regex.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/type_safe/validators/__init__.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Assert.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Call_Stack.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Csv.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Dev.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Env.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Exceptions.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Files.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Functions.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Http.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Int.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Json.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Json_Cache.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Lists.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Misc.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Objects.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Png.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Process.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Python_Logger.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Regex.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Status.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Str.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Threads.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Toml.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Version.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/Zip.py +0 -0
- {osbot_utils-2.63.0 → osbot_utils-2.65.0}/osbot_utils/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: osbot_utils
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.65.0
|
4
4
|
Summary: OWASP Security Bot - Utils
|
5
5
|
License: MIT
|
6
6
|
Author: Dinis Cruz
|
@@ -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
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import inspect
|
2
|
+
from functools import wraps
|
3
|
+
from typing import Any, Callable, TypeVar, Dict
|
4
|
+
from weakref import WeakKeyDictionary
|
5
|
+
|
6
|
+
from osbot_utils.helpers.cache_on_self.Cache_On_Self import Cache_On_Self
|
7
|
+
|
8
|
+
|
9
|
+
T = TypeVar('T', bound=Callable[..., Any])
|
10
|
+
|
11
|
+
# Global registry of cache managers per instance per method
|
12
|
+
# Structure: {instance: {method_name: Cache_On_Self}}
|
13
|
+
_cache_managers_registry: WeakKeyDictionary[Any, Dict[str, Cache_On_Self]] = WeakKeyDictionary()
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
def cache_on_self(function: T) -> T:
|
18
|
+
"""
|
19
|
+
Decorator to cache method results on the instance.
|
20
|
+
|
21
|
+
Use this for cases where we want the cache to be tied to the
|
22
|
+
Class instance (i.e. not global for all executions)
|
23
|
+
"""
|
24
|
+
function_name = function.__name__
|
25
|
+
|
26
|
+
@wraps(function)
|
27
|
+
def wrapper(*args, **kwargs):
|
28
|
+
# Extract self from args
|
29
|
+
if not args:
|
30
|
+
raise ValueError("cache_on_self could not find self - no arguments provided")
|
31
|
+
|
32
|
+
self = args[0]
|
33
|
+
|
34
|
+
# Get or create cache manager for this instance/method combination
|
35
|
+
if self not in _cache_managers_registry:
|
36
|
+
_cache_managers_registry[self] = {}
|
37
|
+
|
38
|
+
if function_name not in _cache_managers_registry[self]:
|
39
|
+
# Create new cache manager for this instance/method
|
40
|
+
_cache_managers_registry[self][function_name] = Cache_On_Self(function=function)
|
41
|
+
|
42
|
+
cache_manager = _cache_managers_registry[self][function_name]
|
43
|
+
|
44
|
+
# Handle special __return__ parameter
|
45
|
+
if kwargs.get('__return__') == 'cache_on_self':
|
46
|
+
return cache_manager
|
47
|
+
|
48
|
+
# Normal call
|
49
|
+
return cache_manager.handle_call(args, kwargs)
|
50
|
+
|
51
|
+
return wrapper
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import inspect
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
|
5
|
+
class Cache_Controller: # Controls cache behavior and reload logic
|
6
|
+
|
7
|
+
def extract_clean_kwargs(self, kwargs: Dict[str, Any]) -> Dict[str, Any]: # Remove special parameters from kwargs
|
8
|
+
return {k: v for k, v in kwargs.items()
|
9
|
+
if k not in ['reload_cache', '__return__']}
|
10
|
+
|
11
|
+
def should_reload(self, kwargs : Dict[str, Any] ,
|
12
|
+
reload_next_flag: bool ) -> bool: # Determine if cache should be reloaded
|
13
|
+
if reload_next_flag:
|
14
|
+
return True
|
15
|
+
return kwargs.get('reload_cache', False) is True
|
16
|
+
|
17
|
+
def should_return_cache_manager(self, kwargs: Dict[str, Any]) -> bool: # Check if should return cache manager
|
18
|
+
return kwargs.get('__return__') == 'cache_on_self'
|
19
|
+
|
20
|
+
def extract_self_from_args(self, args: tuple) -> Any: # Validate and extract self from args
|
21
|
+
if len(args) == 0:
|
22
|
+
raise ValueError("cache_on_self could not find self - no arguments provided")
|
23
|
+
|
24
|
+
potential_self = args[0]
|
25
|
+
if not inspect.isclass(type(potential_self)):
|
26
|
+
raise ValueError("cache_on_self could not find self - first argument is not an instance")
|
27
|
+
|
28
|
+
return potential_self
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import json
|
2
|
+
from typing import Callable, Dict, List, Tuple, Any, Set, FrozenSet
|
3
|
+
from osbot_utils.utils.Misc import str_md5
|
4
|
+
|
5
|
+
|
6
|
+
CACHE_ON_SELF_TYPES = [int, float, bytearray, bytes, bool, complex, str]
|
7
|
+
CACHE_ON_SELF_KEY_PREFIX = '__cache_on_self__'
|
8
|
+
|
9
|
+
|
10
|
+
class Cache_Key_Generator: # Handles all cache key generation logic
|
11
|
+
|
12
|
+
def __init__(self, supported_types: List[type] = None):
|
13
|
+
self.supported_types = supported_types or CACHE_ON_SELF_TYPES
|
14
|
+
|
15
|
+
def generate_key(self, function : Callable ,
|
16
|
+
args : Tuple [Any, ...],
|
17
|
+
kwargs : Dict [str, Any]
|
18
|
+
) -> str: # Generate cache key from function name and arguments
|
19
|
+
key_name = function.__name__
|
20
|
+
args_hash = self.get_args_hash(args)
|
21
|
+
kwargs_hash = self.get_kwargs_hash(kwargs)
|
22
|
+
return f'{CACHE_ON_SELF_KEY_PREFIX}_{key_name}_{args_hash}_{kwargs_hash}'
|
23
|
+
|
24
|
+
def get_args_hash(self, args: Tuple[Any, ...]) -> str: # Get hash for args or empty string if no hashable args
|
25
|
+
args_str = self.args_to_str(args)
|
26
|
+
if args_str:
|
27
|
+
return self.compute_hash(args_str)
|
28
|
+
return ''
|
29
|
+
|
30
|
+
def get_kwargs_hash(self, kwargs: Dict[str, Any]) -> str: # Get hash for kwargs or empty string if no hashable kwargs
|
31
|
+
kwargs_str = self.kwargs_to_str(kwargs)
|
32
|
+
if kwargs_str:
|
33
|
+
return self.compute_hash(kwargs_str)
|
34
|
+
return ''
|
35
|
+
|
36
|
+
def args_to_str(self, args: Tuple[Any, ...]) -> str: # Convert supported args to string representation
|
37
|
+
if not args:
|
38
|
+
return ''
|
39
|
+
|
40
|
+
parts = []
|
41
|
+
for i, arg in enumerate(args):
|
42
|
+
arg_str = self.value_to_cache_str(arg)
|
43
|
+
if arg_str:
|
44
|
+
# Include index to avoid collisions like (1, 23) vs (12, 3)
|
45
|
+
parts.append(f"[{i}]:{arg_str}")
|
46
|
+
return '|'.join(parts)
|
47
|
+
|
48
|
+
def kwargs_to_str(self, kwargs: Dict[str, Any]) -> str: # Convert supported kwargs to string representation
|
49
|
+
if not kwargs:
|
50
|
+
return ''
|
51
|
+
|
52
|
+
parts = []
|
53
|
+
for key, value in sorted(kwargs.items()): # Sort for consistent ordering
|
54
|
+
value_str = self.value_to_cache_str(value)
|
55
|
+
if value_str:
|
56
|
+
parts.append(f'{key}:{value_str}')
|
57
|
+
return '|'.join(parts)
|
58
|
+
|
59
|
+
def value_to_cache_str(self, value: Any) -> str: # Convert a value to a cacheable string representation
|
60
|
+
"""Convert any value to a string suitable for cache key generation.
|
61
|
+
|
62
|
+
Returns a type-prefixed string for all supported types.
|
63
|
+
Returns empty string ONLY for unsupported types.
|
64
|
+
"""
|
65
|
+
if value is None:
|
66
|
+
return '<none>'
|
67
|
+
|
68
|
+
# Handle primitive types with type prefix to avoid any collision
|
69
|
+
value_type = type(value)
|
70
|
+
if value_type in self.supported_types:
|
71
|
+
type_name = value_type.__name__
|
72
|
+
return f"<{type_name}>:{value}"
|
73
|
+
|
74
|
+
# Handle mutable types by converting to a stable string representation
|
75
|
+
try:
|
76
|
+
if isinstance(value, dict):
|
77
|
+
# Sort dict by keys for consistent ordering
|
78
|
+
sorted_items = sorted(value.items())
|
79
|
+
return f"<dict>:{json.dumps(sorted_items, sort_keys=True, separators=(',', ':'))}"
|
80
|
+
|
81
|
+
elif isinstance(value, list):
|
82
|
+
return f"<list>:{json.dumps(value, separators=(',', ':'))}"
|
83
|
+
|
84
|
+
elif isinstance(value, tuple):
|
85
|
+
return f"<tuple>:{json.dumps(value, separators=(',', ':'))}"
|
86
|
+
|
87
|
+
elif isinstance(value, set):
|
88
|
+
# Convert to sorted list for consistent ordering
|
89
|
+
return f"<set>:{json.dumps(sorted(list(value)), separators=(',', ':'))}"
|
90
|
+
|
91
|
+
elif isinstance(value, frozenset):
|
92
|
+
return f"<frozenset>:{json.dumps(sorted(list(value)), separators=(',', ':'))}"
|
93
|
+
|
94
|
+
else:
|
95
|
+
# For other types, try to use repr if it's likely to be stable
|
96
|
+
# This is a fallback - specific types should be handled above
|
97
|
+
if hasattr(value, '__dict__'):
|
98
|
+
# For objects, we could hash their dict representation
|
99
|
+
# But this is risky, so we'll skip for now
|
100
|
+
return ''
|
101
|
+
else:
|
102
|
+
# For other immutable types, try repr
|
103
|
+
try:
|
104
|
+
return f"other:{repr(value)}"
|
105
|
+
except:
|
106
|
+
return ''
|
107
|
+
|
108
|
+
except (TypeError, ValueError, RecursionError):
|
109
|
+
# If we can't serialize the value, skip it
|
110
|
+
return ''
|
111
|
+
|
112
|
+
def compute_hash(self, value: str) -> str: # Compute hash of string value
|
113
|
+
return str_md5(value)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Cache_Metrics: # Track cache performance metrics
|
2
|
+
|
3
|
+
def __init__(self):
|
4
|
+
self.hits = 0
|
5
|
+
self.misses = 0
|
6
|
+
self.reloads = 0
|
7
|
+
self.key_generation_time = 0.0
|
8
|
+
self.cache_lookup_time = 0.0
|
9
|
+
self.function_execution_time = 0.0
|
10
|
+
|
11
|
+
@property
|
12
|
+
def hit_rate(self) -> float: # Calculate cache hit rate
|
13
|
+
total = self.hits + self.misses
|
14
|
+
return self.hits / total if total > 0 else 0.0
|
15
|
+
|
16
|
+
def record_hit(self) -> None: # Record cache hit
|
17
|
+
self.hits += 1
|
18
|
+
|
19
|
+
def record_miss(self) -> None: # Record cache miss
|
20
|
+
self.misses += 1
|
21
|
+
|
22
|
+
def record_reload(self) -> None: # Record cache reload
|
23
|
+
self.reloads += 1
|
24
|
+
|
25
|
+
def reset(self) -> None: # Reset all metrics
|
26
|
+
self.hits = 0
|
27
|
+
self.misses = 0
|
28
|
+
self.reloads = 0
|
29
|
+
self.key_generation_time = 0.0
|
30
|
+
self.cache_lookup_time = 0.0
|
31
|
+
self.function_execution_time = 0.0
|
@@ -0,0 +1,124 @@
|
|
1
|
+
from typing import Any, Callable, Dict, List
|
2
|
+
from osbot_utils.type_safe.Type_Safe import Type_Safe
|
3
|
+
from osbot_utils.helpers.cache_on_self.Cache_Controller import Cache_Controller
|
4
|
+
from osbot_utils.helpers.cache_on_self.Cache_Key_Generator import Cache_Key_Generator, CACHE_ON_SELF_KEY_PREFIX
|
5
|
+
from osbot_utils.helpers.cache_on_self.Cache_Metrics import Cache_Metrics
|
6
|
+
from osbot_utils.helpers.cache_on_self.Cache_Storage import Cache_Storage
|
7
|
+
|
8
|
+
|
9
|
+
class Cache_On_Self(Type_Safe):
|
10
|
+
cache_storage : Cache_Storage # Storage handler instance
|
11
|
+
controller : Cache_Controller # Controller instance
|
12
|
+
key_generator : Cache_Key_Generator # Key generator instance
|
13
|
+
metrics : Cache_Metrics # Metrics tracking
|
14
|
+
function : Callable # The wrapped function
|
15
|
+
function_name : str # Cached function name
|
16
|
+
no_args_key : str # Pre-computed key for no args
|
17
|
+
target_self : Any = None # The instance being cached on
|
18
|
+
current_cache_key : str = '' # Current cache key
|
19
|
+
current_cache_value : Any = None # Current cached value
|
20
|
+
reload_next : bool = False # Force reload on next call
|
21
|
+
disabled : bool = False # cache disable status
|
22
|
+
|
23
|
+
def __init__(self, function : Callable = None ,
|
24
|
+
supported_types: List[type] = None ):
|
25
|
+
super().__init__()
|
26
|
+
self.function = function
|
27
|
+
self.function_name = function.__name__ if function else ''
|
28
|
+
self.no_args_key = f'{CACHE_ON_SELF_KEY_PREFIX}_{self.function_name}__' # Pre-compute for performance
|
29
|
+
self.cache_storage = Cache_Storage()
|
30
|
+
self.controller = Cache_Controller()
|
31
|
+
self.key_generator = Cache_Key_Generator(supported_types)
|
32
|
+
self.metrics = Cache_Metrics()
|
33
|
+
|
34
|
+
def handle_call(self, args: tuple, kwargs: dict) -> Any: # Main entry point for cached calls
|
35
|
+
# Check if caching is disabled
|
36
|
+
if self.disabled:
|
37
|
+
return self.execute(args, kwargs)
|
38
|
+
|
39
|
+
if not kwargs and len(args) == 1: # Fast path for common case: no kwargs, single arg (self)
|
40
|
+
target_self = args[0]
|
41
|
+
cache_key = self.no_args_key
|
42
|
+
|
43
|
+
if self.cache_storage.has_cached_value(target_self, cache_key): # Use cache_storage
|
44
|
+
self.metrics.hits += 1 # Increment cache Hit
|
45
|
+
return self.cache_storage.get_cached_value(target_self, cache_key) # Use cache_storage
|
46
|
+
|
47
|
+
self.metrics.misses += 1 # Increment cache miss - execute and store (Direct increment)
|
48
|
+
result = self.function(*args)
|
49
|
+
self.cache_storage.set_cached_value(target_self, cache_key, result) # Use cache_storage instead of setattr
|
50
|
+
return result
|
51
|
+
|
52
|
+
return self.handle_call_full(args, kwargs)
|
53
|
+
|
54
|
+
def handle_call_full(self, args : tuple,
|
55
|
+
kwargs: dict
|
56
|
+
) -> Any: # Full logic for complex cases
|
57
|
+
# Check if caching is disabled
|
58
|
+
if self.disabled:
|
59
|
+
clean_kwargs = self.controller.extract_clean_kwargs(kwargs)
|
60
|
+
return self.execute(args, clean_kwargs)
|
61
|
+
|
62
|
+
# Extract values - don't store as instance variables to avoid recursion issues
|
63
|
+
target_self = self.controller.extract_self_from_args(args)
|
64
|
+
clean_kwargs = self.controller.extract_clean_kwargs(kwargs)
|
65
|
+
should_reload = self.controller.should_reload(kwargs, self.reload_next)
|
66
|
+
cache_key = self.key_generator.generate_key(self.function, args, clean_kwargs)
|
67
|
+
|
68
|
+
if should_reload:
|
69
|
+
self.reload_next = False # Reset reload flag
|
70
|
+
|
71
|
+
cached_exists = self.cache_storage.has_cached_value(target_self, cache_key)
|
72
|
+
|
73
|
+
if should_reload or not cached_exists:
|
74
|
+
# Execute and cache, passing the cache key directly
|
75
|
+
result = self.execute_and_cache(args, clean_kwargs, target_self, cache_key, should_reload)
|
76
|
+
else:
|
77
|
+
self.metrics.record_hit()
|
78
|
+
result = self.cache_storage.get_cached_value(target_self, cache_key)
|
79
|
+
|
80
|
+
# Update instance state only for external inspection
|
81
|
+
self.target_self = target_self
|
82
|
+
self.current_cache_key = cache_key
|
83
|
+
self.current_cache_value = result
|
84
|
+
|
85
|
+
return result
|
86
|
+
|
87
|
+
def execute(self, args : tuple,
|
88
|
+
kwargs : dict ,
|
89
|
+
) -> Any: # Execute function
|
90
|
+
return self.function(*args, **kwargs)
|
91
|
+
|
92
|
+
def execute_and_cache(self, args : tuple,
|
93
|
+
clean_kwargs : dict,
|
94
|
+
target_self : Any,
|
95
|
+
cache_key : str,
|
96
|
+
should_reload: bool) -> Any: # Execute function and store result
|
97
|
+
if should_reload:
|
98
|
+
self.metrics.record_reload()
|
99
|
+
else:
|
100
|
+
self.metrics.record_miss()
|
101
|
+
|
102
|
+
result = self.execute(args=args, kwargs=clean_kwargs)
|
103
|
+
self.cache_storage.set_cached_value(target_self, cache_key, result)
|
104
|
+
return result
|
105
|
+
|
106
|
+
def clear(self) -> None: # Clear current cache entry
|
107
|
+
if self.target_self and self.current_cache_key:
|
108
|
+
self.cache_storage.clear_key(self.target_self, self.current_cache_key)
|
109
|
+
|
110
|
+
def clear_all(self) -> None: # Clear all cache for current instance
|
111
|
+
if self.target_self:
|
112
|
+
self.cache_storage.clear_all(self.target_self)
|
113
|
+
|
114
|
+
def get_all_keys(self) -> List[str]: # Get all cache keys for current instance
|
115
|
+
if self.target_self:
|
116
|
+
return self.cache_storage.get_all_cache_keys(self.target_self)
|
117
|
+
return []
|
118
|
+
|
119
|
+
def stats(self) -> Dict[str, Any]: # Get cache statistics
|
120
|
+
return { 'hits' : self.metrics.hits ,
|
121
|
+
'misses' : self.metrics.misses ,
|
122
|
+
'reloads' : self.metrics.reloads ,
|
123
|
+
'hit_rate' : self.metrics.hit_rate ,
|
124
|
+
'cache_key' : self.current_cache_key }
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from weakref import WeakKeyDictionary
|
2
|
+
from typing import Any, Dict, List
|
3
|
+
|
4
|
+
class Cache_Storage: # Handles all cache storage without polluting instance attributes
|
5
|
+
|
6
|
+
def __init__(self):
|
7
|
+
self.cache_data: WeakKeyDictionary = WeakKeyDictionary() # Use WeakKeyDictionary so cache is automatically cleaned up when instances are garbage collected , instance -> {cache_key: value}
|
8
|
+
|
9
|
+
def has_cached_value(self, instance: Any, cache_key: str) -> bool:
|
10
|
+
if instance in self.cache_data:
|
11
|
+
return cache_key in self.cache_data[instance]
|
12
|
+
return False
|
13
|
+
|
14
|
+
def get_cached_value(self, instance: Any, cache_key: str) -> Any:
|
15
|
+
return self.cache_data[instance][cache_key]
|
16
|
+
|
17
|
+
def set_cached_value(self, instance: Any, cache_key: str, value: Any) -> None:
|
18
|
+
if instance not in self.cache_data:
|
19
|
+
self.cache_data[instance] = {}
|
20
|
+
self.cache_data[instance][cache_key] = value
|
21
|
+
|
22
|
+
def get_all_cache_keys(self, instance: Any) -> List[str]:
|
23
|
+
if instance in self.cache_data:
|
24
|
+
return list(self.cache_data[instance].keys())
|
25
|
+
return []
|
26
|
+
|
27
|
+
def clear_key(self, instance: Any, cache_key: str) -> None:
|
28
|
+
if instance in self.cache_data:
|
29
|
+
self.cache_data[instance].pop(cache_key, None)
|
30
|
+
|
31
|
+
def clear_all(self, instance: Any) -> None:
|
32
|
+
if instance in self.cache_data:
|
33
|
+
del self.cache_data[instance]
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# note 1: this __init__.py file needs to be here (vs inside the /utils/ast/nodes folder)
|
2
|
+
# so that the methods registration happens as soon as somebody uses a method from the /utils/ast folder/package
|
3
|
+
# note 2: this is needed due to the circular dependencyes between the Ast_Node and the
|
4
|
+
# clases that use it as a base class
|
5
|
+
|
6
|
+
import ast
|
7
|
+
from osbot_utils.helpers.Type_Registry import type_registry
|
8
|
+
from osbot_utils.helpers.ast.nodes.Ast_Add import Ast_Add
|
9
|
+
from osbot_utils.helpers.ast.nodes.Ast_Alias import Ast_Alias
|
10
|
+
from osbot_utils.helpers.ast.nodes.Ast_And import Ast_And
|
11
|
+
from osbot_utils.helpers.ast.nodes.Ast_Argument import Ast_Argument
|
12
|
+
from osbot_utils.helpers.ast.nodes.Ast_Arguments import Ast_Arguments
|
13
|
+
from osbot_utils.helpers.ast.nodes.Ast_Assert import Ast_Assert
|
14
|
+
from osbot_utils.helpers.ast.nodes.Ast_Assign import Ast_Assign
|
15
|
+
from osbot_utils.helpers.ast.nodes.Ast_Attribute import Ast_Attribute
|
16
|
+
from osbot_utils.helpers.ast.nodes.Ast_Aug_Assign import Ast_Aug_Assign
|
17
|
+
from osbot_utils.helpers.ast.nodes.Ast_Bin_Op import Ast_Bin_Op
|
18
|
+
from osbot_utils.helpers.ast.nodes.Ast_Bool_Op import Ast_Bool_Op
|
19
|
+
from osbot_utils.helpers.ast.nodes.Ast_Break import Ast_Break
|
20
|
+
from osbot_utils.helpers.ast.nodes.Ast_Call import Ast_Call
|
21
|
+
from osbot_utils.helpers.ast.nodes.Ast_Class_Def import Ast_Class_Def
|
22
|
+
from osbot_utils.helpers.ast.nodes.Ast_Compare import Ast_Compare
|
23
|
+
from osbot_utils.helpers.ast.nodes.Ast_Comprehension import Ast_Comprehension
|
24
|
+
from osbot_utils.helpers.ast.nodes.Ast_Constant import Ast_Constant
|
25
|
+
from osbot_utils.helpers.ast.nodes.Ast_Continue import Ast_Continue
|
26
|
+
from osbot_utils.helpers.ast.nodes.Ast_Dict import Ast_Dict
|
27
|
+
from osbot_utils.helpers.ast.nodes.Ast_Eq import Ast_Eq
|
28
|
+
from osbot_utils.helpers.ast.nodes.Ast_Except_Handler import Ast_Except_Handler
|
29
|
+
from osbot_utils.helpers.ast.nodes.Ast_Expr import Ast_Expr
|
30
|
+
from osbot_utils.helpers.ast.nodes.Ast_For import Ast_For
|
31
|
+
from osbot_utils.helpers.ast.nodes.Ast_Function_Def import Ast_Function_Def
|
32
|
+
from osbot_utils.helpers.ast.nodes.Ast_Generator_Exp import Ast_Generator_Exp
|
33
|
+
from osbot_utils.helpers.ast.nodes.Ast_Gt import Ast_Gt
|
34
|
+
from osbot_utils.helpers.ast.nodes.Ast_GtE import Ast_GtE
|
35
|
+
from osbot_utils.helpers.ast.nodes.Ast_If import Ast_If
|
36
|
+
from osbot_utils.helpers.ast.nodes.Ast_If_Exp import Ast_If_Exp
|
37
|
+
from osbot_utils.helpers.ast.nodes.Ast_Import import Ast_Import
|
38
|
+
from osbot_utils.helpers.ast.nodes.Ast_Import_From import Ast_Import_From
|
39
|
+
from osbot_utils.helpers.ast.nodes.Ast_In import Ast_In
|
40
|
+
from osbot_utils.helpers.ast.nodes.Ast_Is import Ast_Is
|
41
|
+
from osbot_utils.helpers.ast.nodes.Ast_Is_Not import Ast_Is_Not
|
42
|
+
from osbot_utils.helpers.ast.nodes.Ast_Keyword import Ast_Keyword
|
43
|
+
from osbot_utils.helpers.ast.nodes.Ast_Lambda import Ast_Lambda
|
44
|
+
from osbot_utils.helpers.ast.nodes.Ast_List import Ast_List
|
45
|
+
from osbot_utils.helpers.ast.nodes.Ast_List_Comp import Ast_List_Comp
|
46
|
+
from osbot_utils.helpers.ast.nodes.Ast_Load import Ast_Load
|
47
|
+
from osbot_utils.helpers.ast.nodes.Ast_Lt import Ast_Lt
|
48
|
+
from osbot_utils.helpers.ast.nodes.Ast_LtE import Ast_LtE
|
49
|
+
from osbot_utils.helpers.ast.nodes.Ast_Mod import Ast_Mod
|
50
|
+
from osbot_utils.helpers.ast.nodes.Ast_Module import Ast_Module
|
51
|
+
from osbot_utils.helpers.ast.nodes.Ast_Mult import Ast_Mult
|
52
|
+
from osbot_utils.helpers.ast.nodes.Ast_Name import Ast_Name
|
53
|
+
from osbot_utils.helpers.ast.nodes.Ast_Not import Ast_Not
|
54
|
+
from osbot_utils.helpers.ast.nodes.Ast_Not_Eq import Ast_Not_Eq
|
55
|
+
from osbot_utils.helpers.ast.nodes.Ast_Not_In import Ast_Not_In
|
56
|
+
from osbot_utils.helpers.ast.nodes.Ast_Or import Ast_Or
|
57
|
+
from osbot_utils.helpers.ast.nodes.Ast_Pass import Ast_Pass
|
58
|
+
from osbot_utils.helpers.ast.nodes.Ast_Pow import Ast_Pow
|
59
|
+
from osbot_utils.helpers.ast.nodes.Ast_Raise import Ast_Raise
|
60
|
+
from osbot_utils.helpers.ast.nodes.Ast_Return import Ast_Return
|
61
|
+
from osbot_utils.helpers.ast.nodes.Ast_Set import Ast_Set
|
62
|
+
from osbot_utils.helpers.ast.nodes.Ast_Slice import Ast_Slice
|
63
|
+
from osbot_utils.helpers.ast.nodes.Ast_Starred import Ast_Starred
|
64
|
+
from osbot_utils.helpers.ast.nodes.Ast_Store import Ast_Store
|
65
|
+
from osbot_utils.helpers.ast.nodes.Ast_Sub import Ast_Sub
|
66
|
+
from osbot_utils.helpers.ast.nodes.Ast_Subscript import Ast_Subscript
|
67
|
+
from osbot_utils.helpers.ast.nodes.Ast_Try import Ast_Try
|
68
|
+
from osbot_utils.helpers.ast.nodes.Ast_Tuple import Ast_Tuple
|
69
|
+
from osbot_utils.helpers.ast.nodes.Ast_Unary_Op import Ast_Unary_Op
|
70
|
+
from osbot_utils.helpers.ast.nodes.Ast_While import Ast_While
|
71
|
+
from osbot_utils.helpers.ast.nodes.Ast_With import Ast_With
|
72
|
+
from osbot_utils.helpers.ast.nodes.Ast_With_Item import Ast_With_Item
|
73
|
+
from osbot_utils.helpers.ast.nodes.Ast_Yield import Ast_Yield
|
74
|
+
|
75
|
+
ast_types = {
|
76
|
+
ast.Add : Ast_Add ,
|
77
|
+
ast.alias : Ast_Alias ,
|
78
|
+
ast.And : Ast_And ,
|
79
|
+
ast.Assert : Ast_Assert ,
|
80
|
+
ast.Assign : Ast_Assign ,
|
81
|
+
ast.Attribute : Ast_Attribute ,
|
82
|
+
ast.arg : Ast_Argument ,
|
83
|
+
ast.arguments : Ast_Arguments ,
|
84
|
+
ast.AugAssign : Ast_Aug_Assign ,
|
85
|
+
ast.BinOp : Ast_Bin_Op ,
|
86
|
+
ast.BoolOp : Ast_Bool_Op ,
|
87
|
+
ast.Break : Ast_Break ,
|
88
|
+
ast.Call : Ast_Call ,
|
89
|
+
ast.ClassDef : Ast_Class_Def ,
|
90
|
+
ast.Compare : Ast_Compare ,
|
91
|
+
ast.Constant : Ast_Constant ,
|
92
|
+
ast.Continue : Ast_Continue ,
|
93
|
+
ast.comprehension : Ast_Comprehension ,
|
94
|
+
ast.Dict : Ast_Dict ,
|
95
|
+
ast.ExceptHandler : Ast_Except_Handler,
|
96
|
+
ast.Expr : Ast_Expr ,
|
97
|
+
ast.Eq : Ast_Eq ,
|
98
|
+
ast.Gt : Ast_Gt ,
|
99
|
+
ast.GtE : Ast_GtE ,
|
100
|
+
ast.Import : Ast_Import ,
|
101
|
+
ast.ImportFrom : Ast_Import_From ,
|
102
|
+
ast.In : Ast_In ,
|
103
|
+
ast.For : Ast_For ,
|
104
|
+
ast.FunctionDef : Ast_Function_Def ,
|
105
|
+
ast.GeneratorExp : Ast_Generator_Exp ,
|
106
|
+
ast.If : Ast_If ,
|
107
|
+
ast.IfExp : Ast_If_Exp ,
|
108
|
+
ast.Is : Ast_Is ,
|
109
|
+
ast.IsNot : Ast_Is_Not ,
|
110
|
+
ast.keyword : Ast_Keyword ,
|
111
|
+
ast.Lambda : Ast_Lambda ,
|
112
|
+
ast.List : Ast_List ,
|
113
|
+
ast.ListComp : Ast_List_Comp ,
|
114
|
+
ast.Lt : Ast_Lt ,
|
115
|
+
ast.LtE : Ast_LtE ,
|
116
|
+
ast.Load : Ast_Load ,
|
117
|
+
ast.Mod : Ast_Mod ,
|
118
|
+
ast.Module : Ast_Module ,
|
119
|
+
ast.Mult : Ast_Mult ,
|
120
|
+
ast.Name : Ast_Name ,
|
121
|
+
ast.Not : Ast_Not ,
|
122
|
+
ast.NotEq : Ast_Not_Eq ,
|
123
|
+
ast.NotIn : Ast_Not_In ,
|
124
|
+
ast.Or : Ast_Or ,
|
125
|
+
ast.Pass : Ast_Pass ,
|
126
|
+
ast.Pow : Ast_Pow ,
|
127
|
+
ast.Raise : Ast_Raise ,
|
128
|
+
ast.Return : Ast_Return ,
|
129
|
+
ast.Slice : Ast_Slice ,
|
130
|
+
ast.Starred : Ast_Starred ,
|
131
|
+
ast.Store : Ast_Store ,
|
132
|
+
ast.Set : Ast_Set ,
|
133
|
+
ast.Sub : Ast_Sub ,
|
134
|
+
ast.Subscript : Ast_Subscript ,
|
135
|
+
ast.Try : Ast_Try ,
|
136
|
+
ast.Tuple : Ast_Tuple ,
|
137
|
+
ast.UnaryOp : Ast_Unary_Op ,
|
138
|
+
ast.While : Ast_While ,
|
139
|
+
ast.With : Ast_With ,
|
140
|
+
ast.withitem : Ast_With_Item ,
|
141
|
+
ast.Yield : Ast_Yield ,
|
142
|
+
}
|
143
|
+
|
144
|
+
for key, value in ast_types.items():
|
145
|
+
type_registry.register(key, value)
|
@@ -10,12 +10,13 @@ class Type_Safe__Method:
|
|
10
10
|
self.func = func # Store original function
|
11
11
|
self.sig = inspect.signature(func) # Get function signature
|
12
12
|
self.annotations = func.__annotations__ # Get function annotations
|
13
|
+
self.params = list(self.sig.parameters.keys())
|
13
14
|
|
14
15
|
def check_for_any_use(self):
|
15
16
|
for param_name, type_hint in self.annotations.items():
|
16
17
|
if type_hint is any: # Detect incorrect usage of lowercase any
|
17
18
|
raise ValueError(f"Parameter '{param_name}' uses lowercase 'any' instead of 'Any' from typing module. "
|
18
|
-
|
19
|
+
f"Please use 'from typing import Any' and annotate as '{param_name}: Any'")
|
19
20
|
|
20
21
|
def handle_type_safety(self, args: tuple, kwargs: dict): # Main method to handle type safety
|
21
22
|
self.check_for_any_use()
|
@@ -80,10 +81,6 @@ class Type_Safe__Method:
|
|
80
81
|
self.validate_union_type(param_name, param_value, expected_type) # Validate union
|
81
82
|
return # Exit early
|
82
83
|
|
83
|
-
# if self.try_basic_type_conversion(param_value, expected_type, param_name, # Try basic type conversion
|
84
|
-
# bound_args): # Pass bound args
|
85
|
-
# return # Exit if conversion successful
|
86
|
-
|
87
84
|
self.validate_direct_type(param_name, param_value, expected_type) # Direct type validation
|
88
85
|
|
89
86
|
def is_optional_type(self, type_hint: Any) -> bool: # Check if type is Optional
|
@@ -108,9 +105,13 @@ class Type_Safe__Method:
|
|
108
105
|
if not isinstance(param_value, list): # Check if value is a list
|
109
106
|
raise ValueError(f"Parameter '{param_name}' expected a list but got {type(param_value)}") # Raise error if not list
|
110
107
|
|
111
|
-
item_type = get_args(expected_type)[0]
|
112
|
-
|
113
|
-
|
108
|
+
item_type = get_args(expected_type)[0] # Get list item type
|
109
|
+
if get_origin(item_type) is not None: # Handle the case when item_type is a subscripted type (which is not supported at the moment)
|
110
|
+
raise NotImplementedError(f"Validation for list items with subscripted type"
|
111
|
+
f" '{item_type}' is not yet supported "
|
112
|
+
f"in parameter '{param_name}'.") # todo: add support for checking for subscripted types
|
113
|
+
for i, item in enumerate(param_value): # Check each list item
|
114
|
+
if not isinstance(item, item_type): # Validate item type
|
114
115
|
raise ValueError(f"List item at index {i} expected type {item_type}, but got {type(item)}") # Raise error for invalid item
|
115
116
|
|
116
117
|
def validate_type_parameter(self, param_name: str, param_value: Any, expected_type: Any): # Validate a Type[T] parameter
|
@@ -163,6 +164,7 @@ class Type_Safe__Method:
|
|
163
164
|
is_optional = self.is_optional_type(expected_type) # Check if type is optional
|
164
165
|
has_default = self.has_default_value(param_name) # Check if has default value
|
165
166
|
self.validate_none_value(param_name, is_optional, has_default) # Validate None value
|
167
|
+
return True
|
166
168
|
|
167
169
|
origin = get_origin(expected_type)
|
168
170
|
|
@@ -174,11 +176,20 @@ class Type_Safe__Method:
|
|
174
176
|
if not isinstance(param_value, dict):
|
175
177
|
raise ValueError(f"Parameter '{param_name}' expected dict but got {type(param_value)}")
|
176
178
|
key_type, value_type = get_args(expected_type)
|
179
|
+
if value_type is Any: # if value type is Any, we don't need to do any checks since they will all match
|
180
|
+
return True
|
177
181
|
for k, v in param_value.items():
|
178
|
-
if
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
+
if get_origin(key_type) is None:
|
183
|
+
if not isinstance(k, key_type):
|
184
|
+
raise ValueError(f"Dict key '{k}' expected type {key_type}, but got {type(k)}")
|
185
|
+
else:
|
186
|
+
raise NotImplementedError(f"Validation for subscripted key type '{key_type}' not yet supported in parameter '{param_name}'")
|
187
|
+
|
188
|
+
if get_origin(value_type) is None:
|
189
|
+
if not isinstance(v, value_type):
|
190
|
+
raise ValueError(f"Dict value for key '{k}' expected type {value_type}, but got {type(v)}")
|
191
|
+
elif value_type is not Any:
|
192
|
+
raise NotImplementedError(f"Validation for subscripted value type '{value_type}' not yet supported in parameter '{param_name}'")
|
182
193
|
return True
|
183
194
|
base_type = origin
|
184
195
|
else:
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import functools # For wrapping functions
|
2
|
+
from osbot_utils.type_safe.Type_Safe__Method import Type_Safe__Method
|
3
|
+
|
4
|
+
def type_safe(func): # Main decorator function
|
5
|
+
type_checker = Type_Safe__Method(func) # Create type checker instance
|
6
|
+
|
7
|
+
has_only_self = len(type_checker.params) == 1 and type_checker.params[0] == 'self' # Check if method has only 'self' parameter or no parameters
|
8
|
+
has_no_params = len(type_checker.params) == 0
|
9
|
+
direct_execution = has_no_params or has_only_self # these are major performance optimisation where this @type_safe had an overhead of 250x (even on methods with no params) to now having an over head of ~5x
|
10
|
+
|
11
|
+
@functools.wraps(func) # Preserve function metadata
|
12
|
+
def wrapper(*args, **kwargs): # Wrapper function
|
13
|
+
if direct_execution:
|
14
|
+
return func(*args, **kwargs)
|
15
|
+
else:
|
16
|
+
bound_args = type_checker.handle_type_safety(args, kwargs) # Validate type safety
|
17
|
+
return func(**bound_args.arguments) # Call original function
|
18
|
+
|
19
|
+
return wrapper # Return wrapped function
|
20
|
+
|