osbot-utils 1.11.0__tar.gz → 1.13.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (265) hide show
  1. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/PKG-INFO +3 -4
  2. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/README.md +2 -2
  3. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Cursor.py +4 -1
  4. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Database.py +4 -1
  5. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Table.py +10 -0
  6. osbot_utils-1.13.0/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +45 -0
  7. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Local.py +2 -1
  8. osbot_utils-1.13.0/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +86 -0
  9. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_File.py +4 -4
  10. osbot_utils-1.13.0/osbot_utils/utils/Env.py +76 -0
  11. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Files.py +48 -3
  12. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Objects.py +0 -20
  13. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Str.py +8 -2
  14. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Zip.py +44 -1
  15. osbot_utils-1.13.0/osbot_utils/utils/__init__.py +0 -0
  16. osbot_utils-1.13.0/osbot_utils/version +1 -0
  17. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/pyproject.toml +1 -7
  18. osbot_utils-1.11.0/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Files.py +0 -23
  19. osbot_utils-1.11.0/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Files.py +0 -45
  20. osbot_utils-1.11.0/osbot_utils/utils/__init__.py +0 -16
  21. osbot_utils-1.11.0/osbot_utils/version +0 -1
  22. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/LICENSE +0 -0
  23. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/__init__.py +0 -0
  24. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/base_classes/Cache_Pickle.py +0 -0
  25. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/base_classes/Kwargs_To_Disk.py +0 -0
  26. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/base_classes/Kwargs_To_Self.py +0 -0
  27. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/base_classes/Type_Safe__List.py +0 -0
  28. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/base_classes/__init__.py +0 -0
  29. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/context_managers/__init__.py +0 -0
  30. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/context_managers/capture_duration.py +0 -0
  31. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/__init__.py +0 -0
  32. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/classes/__init__.py +0 -0
  33. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/classes/singleton.py +0 -0
  34. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/lists/__init__.py +0 -0
  35. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/lists/filter_list.py +0 -0
  36. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/lists/group_by.py +0 -0
  37. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/lists/index_by.py +0 -0
  38. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/__init__.py +0 -0
  39. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/cache.py +0 -0
  40. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/cache_on_function.py +0 -0
  41. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/cache_on_self.py +0 -0
  42. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/cache_on_tmp.py +0 -0
  43. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/capture_exception.py +0 -0
  44. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/capture_status.py +0 -0
  45. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/catch.py +0 -0
  46. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/context.py +0 -0
  47. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/depreciated.py +0 -0
  48. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/function_type_check.py +0 -0
  49. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/obj_as_context.py +0 -0
  50. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/remove_return_value.py +0 -0
  51. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/decorators/methods/required_fields.py +0 -0
  52. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/fluent/Fluent_Dict.py +0 -0
  53. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/fluent/Fluent_List.py +0 -0
  54. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/fluent/__init__.py +0 -0
  55. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/__init__.py +0 -0
  56. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/Mermaid.py +0 -0
  57. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/Mermaid__Edge.py +0 -0
  58. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/Mermaid__Graph.py +0 -0
  59. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/Mermaid__Node.py +0 -0
  60. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/Mermaid__Renderer.py +0 -0
  61. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Edge__Config.py +0 -0
  62. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Node__Config.py +0 -0
  63. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/configs/Mermaid__Render__Config.py +0 -0
  64. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/examples/Mermaid_Examples__FlowChart.py +0 -0
  65. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram_Direction.py +0 -0
  66. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/models/Mermaid__Diagram__Type.py +0 -0
  67. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mermaid/models/Mermaid__Node__Shape.py +0 -0
  68. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph.py +0 -0
  69. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Config.py +0 -0
  70. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Data.py +0 -0
  71. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Edge.py +0 -0
  72. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Node.py +0 -0
  73. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Random_Graphs.py +0 -0
  74. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraph__Serializer.py +0 -0
  75. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/MGraphs.py +0 -0
  76. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/graphs/mgraph/__init__.py +0 -0
  77. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/CPrint.py +0 -0
  78. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Dict_To_Attr.py +0 -0
  79. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Local_Cache.py +0 -0
  80. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Local_Caches.py +0 -0
  81. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Print_Table.py +0 -0
  82. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Python_Audit.py +0 -0
  83. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Random_Seed.py +0 -0
  84. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/SCP.py +0 -0
  85. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/SSH.py +0 -0
  86. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/Type_Registry.py +0 -0
  87. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/__init__.py +0 -0
  88. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast.py +0 -0
  89. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Base.py +0 -0
  90. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Data.py +0 -0
  91. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Load.py +0 -0
  92. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Merge.py +0 -0
  93. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Node.py +0 -0
  94. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Ast_Visit.py +0 -0
  95. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/Call_Tree.py +0 -0
  96. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/__init__.py +0 -0
  97. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Add.py +0 -0
  98. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Alias.py +0 -0
  99. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_And.py +0 -0
  100. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Argument.py +0 -0
  101. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Arguments.py +0 -0
  102. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Assert.py +0 -0
  103. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Assign.py +0 -0
  104. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Attribute.py +0 -0
  105. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Aug_Assign.py +0 -0
  106. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Bin_Op.py +0 -0
  107. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Bool_Op.py +0 -0
  108. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Break.py +0 -0
  109. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Call.py +0 -0
  110. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Class_Def.py +0 -0
  111. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Compare.py +0 -0
  112. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Comprehension.py +0 -0
  113. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Constant.py +0 -0
  114. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Continue.py +0 -0
  115. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Dict.py +0 -0
  116. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Eq.py +0 -0
  117. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Except_Handler.py +0 -0
  118. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Expr.py +0 -0
  119. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_For.py +0 -0
  120. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Function_Def.py +0 -0
  121. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Generator_Exp.py +0 -0
  122. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Gt.py +0 -0
  123. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_GtE.py +0 -0
  124. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_If.py +0 -0
  125. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_If_Exp.py +0 -0
  126. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Import.py +0 -0
  127. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Import_From.py +0 -0
  128. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_In.py +0 -0
  129. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Is.py +0 -0
  130. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Is_Not.py +0 -0
  131. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Keyword.py +0 -0
  132. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Lambda.py +0 -0
  133. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_List.py +0 -0
  134. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_List_Comp.py +0 -0
  135. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Load.py +0 -0
  136. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Lt.py +0 -0
  137. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_LtE.py +0 -0
  138. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Mod.py +0 -0
  139. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Module.py +0 -0
  140. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Mult.py +0 -0
  141. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Name.py +0 -0
  142. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Not.py +0 -0
  143. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Not_Eq.py +0 -0
  144. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Not_In.py +0 -0
  145. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Or.py +0 -0
  146. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Pass.py +0 -0
  147. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Pow.py +0 -0
  148. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Raise.py +0 -0
  149. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Return.py +0 -0
  150. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Set.py +0 -0
  151. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Slice.py +0 -0
  152. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Starred.py +0 -0
  153. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Store.py +0 -0
  154. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Sub.py +0 -0
  155. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Subscript.py +0 -0
  156. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Try.py +0 -0
  157. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Tuple.py +0 -0
  158. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Unary_Op.py +0 -0
  159. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_While.py +0 -0
  160. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_With.py +0 -0
  161. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_With_Item.py +0 -0
  162. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/Ast_Yield.py +0 -0
  163. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/ast/nodes/__init__.py +0 -0
  164. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Dict_To_Css.py +0 -0
  165. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Dict_To_Html.py +0 -0
  166. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Dict_To_Tags.py +0 -0
  167. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Html_To_Dict.py +0 -0
  168. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Html_To_Tag.py +0 -0
  169. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Base.py +0 -0
  170. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Body.py +0 -0
  171. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Div.py +0 -0
  172. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__H.py +0 -0
  173. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__HR.py +0 -0
  174. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Head.py +0 -0
  175. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Html.py +0 -0
  176. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Link.py +0 -0
  177. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/Tag__Style.py +0 -0
  178. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/html/__init__.py +0 -0
  179. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/Event__Queue.py +0 -0
  180. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/PubSub__Client.py +0 -0
  181. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/PubSub__Room.py +0 -0
  182. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/PubSub__Server.py +0 -0
  183. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/PubSub__Sqlite.py +0 -0
  184. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/__init__.py +0 -0
  185. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event.py +0 -0
  186. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Connect.py +0 -0
  187. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Disconnect.py +0 -0
  188. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Join_Room.py +0 -0
  189. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Leave_Room.py +0 -0
  190. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__Event__Message.py +0 -0
  191. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/Schema__PubSub__Client.py +0 -0
  192. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/pubsub/schemas/__init__.py +0 -0
  193. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Capture_Sqlite_Error.py +0 -0
  194. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Field.py +0 -0
  195. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Globals.py +0 -0
  196. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Sqlite__Table__Create.py +0 -0
  197. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Database__Disk.py +0 -0
  198. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/Temp_Sqlite__Table.py +0 -0
  199. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/__init__.py +0 -0
  200. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests.py +0 -0
  201. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__Cache__Requests__Patch.py +0 -0
  202. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Graph.py +0 -0
  203. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Json.py +0 -0
  204. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/Sqlite__DB__Requests.py +0 -0
  205. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/__init__.py +0 -0
  206. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/schemas/Schema__Table__Requests.py +0 -0
  207. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/domains/schemas/__init__.py +0 -0
  208. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/models/Sqlite__Field__Type.py +0 -0
  209. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/models/__init__.py +0 -0
  210. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/sample_data/Sqlite__Sample_Data__Chinook.py +0 -0
  211. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/sample_data/__init__.py +0 -0
  212. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder.py +0 -0
  213. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/sql_builder/SQL_Builder__Select.py +0 -0
  214. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/sql_builder/__init__.py +0 -0
  215. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Config.py +0 -0
  216. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Edges.py +0 -0
  217. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/tables/Sqlite__Table__Nodes.py +0 -0
  218. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/sqlite/tables/__init__.py +0 -0
  219. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call.py +0 -0
  220. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Config.py +0 -0
  221. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Graph.py +0 -0
  222. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Handler.py +0 -0
  223. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Print_Lines.py +0 -0
  224. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Print_Traces.py +0 -0
  225. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Stack.py +0 -0
  226. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Stack_Node.py +0 -0
  227. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__Stats.py +0 -0
  228. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Call__View_Model.py +0 -0
  229. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/Trace_Files.py +0 -0
  230. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/helpers/trace/__init__.py +0 -0
  231. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Catch.py +0 -0
  232. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Duration.py +0 -0
  233. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Hook_Method.py +0 -0
  234. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Log_To_Queue.py +0 -0
  235. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Log_To_String.py +0 -0
  236. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Logging.py +0 -0
  237. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Patch_Print.py +0 -0
  238. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Profiler.py +0 -0
  239. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Stderr.py +0 -0
  240. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Stdout.py +0 -0
  241. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_Folder.py +0 -0
  242. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_Sys_Path.py +0 -0
  243. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_Web_Server.py +0 -0
  244. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_Zip.py +0 -0
  245. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Temp_Zip_In_Memory.py +0 -0
  246. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Unit_Test.py +0 -0
  247. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/Unzip_File.py +0 -0
  248. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/testing/__init__.py +0 -0
  249. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Assert.py +0 -0
  250. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Call_Stack.py +0 -0
  251. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Csv.py +0 -0
  252. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Dev.py +0 -0
  253. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Exceptions.py +0 -0
  254. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Functions.py +0 -0
  255. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Http.py +0 -0
  256. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Int.py +0 -0
  257. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Json.py +0 -0
  258. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Json_Cache.py +0 -0
  259. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Lists.py +0 -0
  260. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Misc.py +0 -0
  261. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Png.py +0 -0
  262. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Process.py +0 -0
  263. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Python_Logger.py +0 -0
  264. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Status.py +0 -0
  265. {osbot_utils-1.11.0 → osbot_utils-1.13.0}/osbot_utils/utils/Version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: osbot_utils
3
- Version: 1.11.0
3
+ Version: 1.13.0
4
4
  Summary: OWASP Security Bot - Utils
5
5
  Home-page: https://github.com/owasp-sbot/OSBot-Utils
6
6
  License: MIT
@@ -11,7 +11,6 @@ Classifier: License :: OSI Approved :: MIT License
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
- Requires-Dist: python-dotenv
15
14
  Project-URL: Repository, https://github.com/owasp-sbot/OSBot-Utils
16
15
  Description-Content-Type: text/markdown
17
16
 
@@ -19,14 +18,14 @@ Description-Content-Type: text/markdown
19
18
 
20
19
  Powerful Python util methods and classes that simplify common apis and tasks.
21
20
 
22
- ![Current Release](https://img.shields.io/badge/release-v1.11.0-blue)
21
+ ![Current Release](https://img.shields.io/badge/release-v1.13.0-blue)
23
22
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
24
23
 
25
24
 
26
25
 
27
26
  ## Install - Release 1.x
28
27
 
29
- **for main branch**: add to requirements.txt
28
+ **for main branch**: just get it from pypi
30
29
 
31
30
  ```
32
31
  pip install osbot-utils
@@ -2,14 +2,14 @@
2
2
 
3
3
  Powerful Python util methods and classes that simplify common apis and tasks.
4
4
 
5
- ![Current Release](https://img.shields.io/badge/release-v1.11.0-blue)
5
+ ![Current Release](https://img.shields.io/badge/release-v1.13.0-blue)
6
6
  [![codecov](https://codecov.io/gh/owasp-sbot/OSBot-Utils/graph/badge.svg?token=GNVW0COX1N)](https://codecov.io/gh/owasp-sbot/OSBot-Utils)
7
7
 
8
8
 
9
9
 
10
10
  ## Install - Release 1.x
11
11
 
12
- **for main branch**: add to requirements.txt
12
+ **for main branch**: just get it from pypi
13
13
 
14
14
  ```
15
15
  pip install osbot-utils
@@ -84,4 +84,7 @@ class Sqlite__Cursor(Kwargs_To_Self):
84
84
  self.execute(sql_query)
85
85
  all_rows = self.cursor().fetchall()
86
86
  all_values = [cell.get(cell_name) for cell in all_rows]
87
- return all_values
87
+ return all_values
88
+
89
+ def vacuum(self):
90
+ return self.execute("VACUUM")
@@ -130,8 +130,11 @@ class Sqlite__Database(Kwargs_To_Self):
130
130
  table_names.append('sqlite_master')
131
131
  return table_names
132
132
 
133
+ def purge_database(self): # this fells like a better name than vacuum :)
134
+ return self.vacuum()
133
135
 
134
-
136
+ def vacuum(self):
137
+ return self.cursor().vacuum()
135
138
 
136
139
 
137
140
 
@@ -130,6 +130,7 @@ class Sqlite__Table(Kwargs_To_Self):
130
130
  rows = table_sqlite_master.cursor().execute__fetch_all(sql_query, params)
131
131
  return table_sqlite_master.list_of_field_name_from_rows(rows, field_name)
132
132
 
133
+
133
134
  def new_row_obj(self, row_data=None):
134
135
  if self.row_schema:
135
136
  new_obj = self.row_schema()
@@ -154,6 +155,7 @@ class Sqlite__Table(Kwargs_To_Self):
154
155
  picked_row_data[field_name] = field_value
155
156
  return picked_row_data
156
157
  return row_data
158
+
157
159
  def parse_row(self, row):
158
160
  if row and self.auto_pickle_blob:
159
161
  fields = self.fields__cached()
@@ -169,6 +171,14 @@ class Sqlite__Table(Kwargs_To_Self):
169
171
  def print(self, **kwargs):
170
172
  return Print_Table(**kwargs).print(self.rows())
171
173
 
174
+ def row(self, where, fields=None):
175
+ if fields is None:
176
+ return self.select_row_where(**where)
177
+
178
+ sql_query, params = self.sql_builder(limit=1).query_select_fields_with_conditions(fields, where)
179
+ row = self.cursor().execute__fetch_one(sql_query, params)
180
+ return self.parse_row(row)
181
+
172
182
  def row_add(self, row_obj=None):
173
183
  invalid_reason = self.sql_builder().validate_row_obj(row_obj)
174
184
  if invalid_reason:
@@ -0,0 +1,45 @@
1
+ from osbot_utils.decorators.lists.index_by import index_by
2
+ from osbot_utils.decorators.methods.cache_on_self import cache_on_self
3
+ from osbot_utils.helpers.sqlite.domains.Sqlite__DB__Local import Sqlite__DB__Local
4
+ from osbot_utils.helpers.sqlite.tables.Sqlite__Table__Files import Sqlite__Table__Files
5
+
6
+
7
+ class Sqlite__DB__Files(Sqlite__DB__Local):
8
+
9
+ def __init__(self, db_path=None, db_name=None):
10
+ super().__init__(db_path=db_path, db_name=db_name)
11
+
12
+ def add_file(self, path, contents=None, metadata=None):
13
+ return self.table_files().add_file(path, contents, metadata)
14
+
15
+ def clear_table(self):
16
+ self.table_files().clear()
17
+
18
+ def delete_file(self, path):
19
+ return self.table_files().delete_file(path)
20
+
21
+ def file(self, path, include_contents=False):
22
+ return self.table_files().file(path, include_contents=include_contents)
23
+
24
+ def file_exists(self, path):
25
+ return self.table_files().file_exists(path)
26
+
27
+ def file_names(self):
28
+ return self.table_files().select_field_values('path')
29
+ @cache_on_self
30
+ def table_files(self):
31
+ return Sqlite__Table__Files(database=self).setup()
32
+
33
+ @index_by
34
+ def files(self,include_contents=False):
35
+ return self.table_files().files(include_contents=include_contents)
36
+
37
+ def files__with_content(self):
38
+ return self.files(include_contents=True)
39
+
40
+ def files__by_path(self):
41
+ return self.files(index_by='path')
42
+
43
+ def setup(self):
44
+ self.table_files()
45
+ return self
@@ -10,7 +10,8 @@ class Sqlite__DB__Local(Sqlite__Database):
10
10
  db_name: str
11
11
 
12
12
  def __init__(self, db_path=None, db_name=None):
13
- self.db_name = db_name or random_text('db_local') + '.sqlite'
13
+ if hasattr(self, 'db_name') is False:
14
+ self.db_name = db_name or random_text('db_local') + '.sqlite'
14
15
  super().__init__(db_path=db_path or self.path_local_db())
15
16
 
16
17
  def path_db_folder(self):
@@ -0,0 +1,86 @@
1
+ from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
2
+ from osbot_utils.helpers.sqlite.Sqlite__Table import Sqlite__Table
3
+ from osbot_utils.utils.Misc import timestamp_utc_now, bytes_sha256, str_sha256
4
+ from osbot_utils.utils.Status import status_warning, status_ok
5
+
6
+ SQLITE__TABLE_NAME__FILES = 'files'
7
+
8
+ class Schema__Table__Files(Kwargs_To_Self):
9
+ path : str
10
+ contents : bytes
11
+ metadata : bytes
12
+ timestamp: int
13
+
14
+
15
+ class Sqlite__Table__Files(Sqlite__Table):
16
+ auto_pickle_blob : bool = True
17
+ set_timestamp : bool = True
18
+
19
+ def __init__(self, **kwargs):
20
+ self.table_name = SQLITE__TABLE_NAME__FILES
21
+ self.row_schema = Schema__Table__Files
22
+ super().__init__(**kwargs)
23
+
24
+ def add_file(self, path, contents=None, metadata= None):
25
+ if self.contains(path=path): # don't allow multiple entries for the same file path (until we add versioning support)
26
+ return status_warning(f"File not added, since file with path '{path}' already exists in the database")
27
+ if metadata is None:
28
+ metadata = {}
29
+ metadata.update(self.create_contents_metadata(contents))
30
+ row_data = self.create_node_data(path, contents, metadata)
31
+ new_row_obj = self.add_row_and_commit(**row_data)
32
+ return status_ok(message='file added', data= new_row_obj)
33
+
34
+ def create_contents_metadata(self, contents):
35
+ file_size = len(contents)
36
+ file_is_binary = type(contents) is bytes
37
+ if file_is_binary:
38
+ file_hash = bytes_sha256(contents)
39
+ else:
40
+ file_hash = str_sha256(str(contents))
41
+ return dict(file_contents=dict(hash = file_hash ,
42
+ is_binary = file_is_binary ,
43
+ size = file_size ))
44
+
45
+ def delete_file(self, path):
46
+ if self.not_contains(path=path): # don't allow multiple entries for the same file path (until we add versioning support)
47
+ return status_warning(f"File not deleted, since file with path '{path}' did not exist in the database")
48
+
49
+ self.rows_delete_where(path=path)
50
+ return status_ok(message='file deleted')
51
+
52
+ def create_node_data(self, path, contents=None, metadata= None):
53
+ node_data = {'path' : path ,
54
+ 'contents': contents ,
55
+ 'metadata': metadata }
56
+ if self.set_timestamp:
57
+ node_data['timestamp'] = timestamp_utc_now()
58
+ return node_data
59
+
60
+ def field_names_without_content(self): # todo: refactor to get this directly from the schema
61
+ return ['id', 'path', 'metadata', 'timestamp'] # and so that these values are not hard-coded here
62
+
63
+ def file(self, path, include_contents=True):
64
+ if include_contents:
65
+ fields = ['*']
66
+ else:
67
+ fields = self.field_names_without_content()
68
+ return self.row(where=dict(path=path), fields = fields)
69
+
70
+ def file_without_contents(self, path):
71
+ return self.file(path, include_contents=False)
72
+
73
+ def file_exists(self, path):
74
+ return self.contains(path=path)
75
+
76
+ def files(self, include_contents=False):
77
+ if include_contents:
78
+ return self.rows()
79
+ fields_names = self.field_names_without_content()
80
+ return self.rows(fields_names)
81
+
82
+ def setup(self):
83
+ if self.exists() is False:
84
+ self.create()
85
+ self.index_create('path')
86
+ return self
@@ -1,11 +1,11 @@
1
- from osbot_utils.utils.Files import Files, file_delete, folder_delete_all, files_list, file_create, file_name, \
1
+ from osbot_utils.utils.Files import Files, file_delete, folder_delete_all, files_list, file_create, \
2
2
  parent_folder, file_exists, file_contents
3
3
  from osbot_utils.utils.Misc import random_filename
4
4
 
5
5
 
6
6
  class Temp_File:
7
- def __init__(self, contents='...', extension='tmp'):
8
- self.tmp_file = random_filename(extension)
7
+ def __init__(self, contents='...', extension='tmp',file_name=None, ):
8
+ self.tmp_file = file_name or random_filename(extension)
9
9
  self.tmp_folder = None
10
10
  self.file_path = None
11
11
  self.original_contents = contents
@@ -30,7 +30,7 @@ class Temp_File:
30
30
  return file_exists(self.file_path)
31
31
 
32
32
  def file_name(self):
33
- return file_name(self.path())
33
+ return Files.file_name(self.path())
34
34
 
35
35
  def files_in_folder(self):
36
36
  return files_list(self.tmp_folder)
@@ -0,0 +1,76 @@
1
+ # In Misc.py
2
+ import os
3
+
4
+ from osbot_utils.utils.Files import all_parent_folders
5
+ from osbot_utils.utils.Misc import list_set
6
+ from osbot_utils.utils.Str import strip_quotes
7
+
8
+
9
+ def env_value(var_name):
10
+ return env_vars().get(var_name, None)
11
+
12
+ def env_vars_list():
13
+ return list_set(env_vars())
14
+
15
+ def env_vars(reload_vars=False):
16
+ """
17
+ if reload_vars reload data from .env file
18
+ then return dictionary with current environment variables
19
+ """
20
+ if reload_vars:
21
+ load_dotenv()
22
+ vars = os.environ
23
+ data = {}
24
+ for key in vars:
25
+ data[key] = vars[key]
26
+ return data
27
+
28
+ def env_load_from_file(path, override=False):
29
+ if os.path.exists(path):
30
+ with open(path) as f:
31
+ for line in f:
32
+ line = line.strip()
33
+ if not line or line.startswith('#'): # Strip whitespace and ignore comments
34
+ continue
35
+ key, value = line.split(sep='=', maxsplit=1) # Split the line into key and value
36
+ value = strip_quotes(value.strip()) # Handle case when the value is in quotes
37
+ if override or key.strip() not in os.environ: # Set the environment variable
38
+ os.environ[key.strip()] = value.strip()
39
+
40
+ def env_unload_from_file(path):
41
+ if os.path.exists(path):
42
+ with open(path) as f:
43
+ for line in f:
44
+ line = line.strip()
45
+ if not line or line.startswith('#'): # Strip whitespace and ignore comments
46
+ continue
47
+ key, _ = line.split(sep='=', maxsplit=1) # Split the line into key and value
48
+ key = key.strip()
49
+ if key in os.environ: # Remove the environment variable if it exists
50
+ del os.environ[key]
51
+
52
+ def load_dotenv(dotenv_path=None, override=False):
53
+ if dotenv_path: # If a specific dotenv path is provided, load from it
54
+ env_load_from_file(dotenv_path, override)
55
+ else:
56
+ directories = all_parent_folders(include_path=True) # Define the possible directories to search for the .env file (which is this and all parent folders)
57
+ for directory in directories: # Iterate through the directories and load the .env file if found
58
+ env_path = os.path.join(directory, '.env') # Define the path to the .env file
59
+ if os.path.exists(env_path): # If we found one
60
+ env_load_from_file(env_path, override) # Process it
61
+ break # Stop after loading the first .env file # Stop after loading the first .env file
62
+
63
+
64
+ def unload_dotenv(dotenv_path=None):
65
+ if dotenv_path: # If a specific dotenv path is provided, unload from it
66
+ env_unload_from_file(dotenv_path)
67
+ else:
68
+ directories = all_parent_folders(include_path=True) # Define the possible directories to search for the .env file (which is this and all parent folders)
69
+ for directory in directories: # Iterate through the directories and unload the .env file if found
70
+ env_path = os.path.join(directory, '.env') # Define the path to the .env file
71
+ if os.path.exists(env_path): # If we found one
72
+ env_unload_from_file(env_path) # Process it
73
+ break # Stop after unloading the first .env file
74
+
75
+
76
+ env_load = load_dotenv
@@ -21,7 +21,7 @@ class Files:
21
21
  def copy(source:str, destination:str) -> str:
22
22
  if file_exists(source): # make sure source file exists
23
23
  destination_parent_folder = parent_folder(destination) # get target parent folder
24
- folder_create(destination_parent_folder) # ensure targer folder exists # todo: check if this is still needed (we should be using a copy method that creates the required fodlers)
24
+ folder_create(destination_parent_folder) # ensure target folder exists # todo: check if this is still needed (we should be using a copy method that creates the required fodlers)
25
25
  return shutil.copy(source, destination) # copy file and returns file destination
26
26
 
27
27
  @staticmethod
@@ -308,7 +308,11 @@ class Files:
308
308
  @staticmethod
309
309
  def path_combine(path1, path2):
310
310
  if type(path1) in [str, Path] and type(path2) in [str, Path]:
311
- return abspath(join(str(path1), str(path2)))
311
+ parent_path = str(path1)
312
+ sub_path = str(path2)
313
+ if sub_path.startswith('/'):
314
+ sub_path = sub_path[1:]
315
+ return abspath(join(parent_path,sub_path))
312
316
 
313
317
  @staticmethod
314
318
  def parent_folder(path):
@@ -424,13 +428,53 @@ class Files:
424
428
  file.write(contents)
425
429
  return path
426
430
 
427
- # todo: refactor the methods above into static methods
431
+ # todo: refactor the methods above into static methods (as bellow)
428
432
 
433
+ def all_parent_folders(path=None, include_path=False):
434
+ if path is None:
435
+ path = os.getcwd()
436
+ parent_directories = []
429
437
 
438
+ # Optionally include the starting path
439
+ if include_path:
440
+ parent_directories.append(path)
441
+
442
+ while True: # Split the path into parts
443
+ path, tail = os.path.split(path)
444
+ if tail:
445
+ parent_directories.append(path)
446
+ else:
447
+ if path and path not in parent_directories: # to handle the root path case
448
+ parent_directories.append(path)
449
+ break
450
+
451
+ return parent_directories
452
+ def file_move(source_file, target_file):
453
+ if file_exists(source_file):
454
+ file_copy(source_file, target_file)
455
+ if file_exists(target_file):
456
+ if file_delete(source_file):
457
+ return True
458
+ return False
459
+
460
+ def folders_names_in_folder(target):
461
+ folders = folders_in_folder(target)
462
+ return folders_names(folders)
463
+
464
+ def stream_to_bytes(stream):
465
+ return stream.read()
466
+
467
+ def stream_to_file(stream, path=None):
468
+ if path is None: # if path is not defined
469
+ path = Files.temp_file() # save it to a temp file
470
+ with open(path, 'wb') as file: # Write the content to the file
471
+ file.write(stream.read())
472
+ return path
430
473
 
431
474
  # helper methods
432
475
  # todo: all all methods above (including the duplicated mappings at the top)
433
476
 
477
+ bytes_to_file = Files.write_bytes
434
478
  create_folder = Files.folder_create
435
479
  create_folder_in_parent = Files.folder_create_in_parent
436
480
  create_temp_file = Files.write
@@ -465,6 +509,7 @@ file_open_gz = Files.open_gz
465
509
  file_open_bytes = Files.open_bytes
466
510
  file_to_base64 = Files.file_to_base64
467
511
  file_from_base64 = Files.file_from_base64
512
+ file_from_bytes = Files.write_bytes
468
513
  file_save = Files.save
469
514
  file_sha256 = Files.contents_sha256
470
515
  file_size = Files.file_size
@@ -7,8 +7,6 @@ import pickle
7
7
  import types
8
8
  from typing import get_origin, Union, get_args
9
9
 
10
- from dotenv import load_dotenv
11
-
12
10
  from osbot_utils.utils.Misc import list_set
13
11
  from osbot_utils.utils.Str import str_unicode_escape, str_max_width
14
12
 
@@ -88,24 +86,6 @@ def enum_from_value(enum_type, value):
88
86
  except KeyError:
89
87
  raise ValueError(f"Value '{value}' is not a valid member of {enum_type.__name__}.") # Handle the case where the value does not match any Enum member
90
88
 
91
- def env_value(var_name):
92
- return env_vars().get(var_name, None)
93
-
94
- def env_vars_list():
95
- return list_set(env_vars())
96
-
97
- def env_vars(reload_vars=False):
98
- """
99
- if reload_vars reload data from .env file
100
- then return dictionary with current environment variables
101
- """
102
- if reload_vars:
103
- load_dotenv()
104
- vars = os.environ
105
- data = {}
106
- for key in vars:
107
- data[key] = vars[key]
108
- return data
109
89
 
110
90
  def get_field(target, field, default=None):
111
91
  if target is not None:
@@ -3,13 +3,19 @@ from html import escape, unescape
3
3
 
4
4
  from osbot_utils.utils.Files import safe_file_name
5
5
 
6
+ # todo: refactor this this class all str related methods (mainly from the Misc class)
6
7
 
7
- def html_escape(value):
8
+ def html_escape(value: str):
8
9
  return escape(value)
9
10
 
10
- def html_unescape(value):
11
+ def html_unescape(value: str):
11
12
  return unescape(value)
12
13
 
14
+ def strip_quotes(value: str): # Remove surrounding quotes (single or double)
15
+ if (value.startswith("'") and value.endswith("'")) or (value.startswith('"') and value.endswith('"')):
16
+ return value[1:-1]
17
+ return value
18
+
13
19
  def str_dedent(value, strip=True):
14
20
  result = textwrap.dedent(value)
15
21
  if strip:
@@ -1,11 +1,41 @@
1
+ import gzip
1
2
  import io
2
3
  import os
3
4
  import shutil
5
+ import tarfile
4
6
  import zipfile
5
7
  from os.path import abspath
6
8
 
7
- from osbot_utils.utils.Files import temp_folder, folder_files, temp_file, is_file
9
+ from osbot_utils.utils.Files import temp_folder, folder_files, temp_file, is_file, file_copy, file_move
10
+
11
+
12
+ def gz_tar_bytes_file_list(gz_bytes):
13
+ gz_buffer_from_bytes = io.BytesIO(gz_bytes)
14
+ with gzip.GzipFile(fileobj=gz_buffer_from_bytes, mode='rb') as gz:
15
+ decompressed_data = gz.read()
16
+ tar_buffer_from_bytes = io.BytesIO(decompressed_data) # Assuming the decompressed data is a tag file, process it
17
+ with tarfile.open(fileobj=tar_buffer_from_bytes, mode='r:') as tar:
18
+ return sorted(tar.getnames())
19
+
20
+ def gz_tar_bytes_get_file(gz_bytes, tar_file_path):
21
+ gz_buffer_from_bytes = io.BytesIO(gz_bytes)
22
+ with gzip.GzipFile(fileobj=gz_buffer_from_bytes, mode='rb') as gz:
23
+ decompressed_data = gz.read()
24
+ tar_buffer_from_bytes = io.BytesIO(decompressed_data)
25
+ with tarfile.open(fileobj=tar_buffer_from_bytes, mode='r:') as tar:
26
+ extracted_file = tar.extractfile(tar_file_path)
27
+ if extracted_file:
28
+ return extracted_file.read()
29
+ else:
30
+ raise FileNotFoundError(f"The file {tar_file_path} was not found in the tar archive.")
8
31
 
32
+ def gz_zip_bytes_file_list(gz_bytes):
33
+ gz_buffer_from_bytes = io.BytesIO(gz_bytes)
34
+ with gzip.GzipFile(fileobj=gz_buffer_from_bytes, mode='rb') as gz:
35
+ decompressed_data = gz.read()
36
+ zip_buffer_from_bytes = io.BytesIO(decompressed_data) # Assuming the decompressed data is a zip file, process it
37
+ with zipfile.ZipFile(zip_buffer_from_bytes, 'r') as zf:
38
+ return sorted(zf.namelist())
9
39
 
10
40
  def unzip_file(zip_file, target_folder=None, format='zip'):
11
41
  target_folder = target_folder or temp_folder()
@@ -28,6 +58,14 @@ def zip_bytes_get_file(zip_bytes, zip_file_path):
28
58
  with zipfile.ZipFile(zip_buffer, 'r') as zf:
29
59
  return zf.read(zip_file_path)
30
60
 
61
+ def zip_bytes_extract_to_folder(zip_bytes, target_folder=None):
62
+ target_folder = target_folder or temp_folder() # Use the provided target folder or create a temporary one
63
+ zip_buffer = io.BytesIO(zip_bytes) # Create a BytesIO buffer from the zip bytes
64
+ with zipfile.ZipFile(zip_buffer, 'r') as zf: # Open the zip file from the buffer
65
+ zf.extractall(target_folder) # Extract all files to the target folder
66
+ return target_folder # Return the path of the target folder
67
+
68
+
31
69
  def zip_bytes_file_list(zip_bytes):
32
70
  zip_buffer_from_bytes = io.BytesIO(zip_bytes)
33
71
  with zipfile.ZipFile(zip_buffer_from_bytes, 'r') as zf:
@@ -61,6 +99,11 @@ def zip_files_to_bytes(target_files, root_folder=None):
61
99
  def zip_folder(root_dir, format='zip'):
62
100
  return shutil.make_archive(base_name=root_dir, format=format, root_dir=root_dir)
63
101
 
102
+ def zip_folder_to_file (root_dir, target_file):
103
+ zip_file = zip_folder(root_dir)
104
+ return file_move(zip_file, target_file)
105
+
106
+
64
107
  def zip_folder_to_bytes(root_dir): # todo add unit test
65
108
  zip_buffer = io.BytesIO() # Create a BytesIO buffer to hold the zipped file
66
109
  with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zf: # Create a ZipFile object with the buffer as the target
File without changes
@@ -0,0 +1 @@
1
+ v1.13.0
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "osbot_utils"
3
- version = "v1.11.0"
3
+ version = "v1.13.0"
4
4
  description = "OWASP Security Bot - Utils"
5
5
  authors = ["Dinis Cruz <dinis.cruz@owasp.org>"]
6
6
  license = "MIT"
@@ -10,12 +10,6 @@ repository = "https://github.com/owasp-sbot/OSBot-Utils"
10
10
 
11
11
  [tool.poetry.dependencies]
12
12
  python = "^3.11"
13
- python-dotenv = "*"
14
-
15
- #[tool.poetry.group.test.dependencies]
16
- #pytest = "*"
17
- #pytest-cov = "*"
18
- #coveralls = "*"
19
13
 
20
14
 
21
15
  [build-system]
@@ -1,23 +0,0 @@
1
- from osbot_utils.decorators.methods.cache_on_self import cache_on_self
2
- from osbot_utils.helpers.sqlite.domains.Sqlite__DB__Local import Sqlite__DB__Local
3
- from osbot_utils.helpers.sqlite.tables.Sqlite__Table__Files import Sqlite__Table__Files
4
-
5
-
6
- class Sqlite__DB__Files(Sqlite__DB__Local):
7
-
8
- def __init__(self, db_path=None, db_name=None):
9
- super().__init__(db_path=db_path, db_name=db_name)
10
-
11
- def add_file(self, path, contents=None, metadata=None):
12
- return self.table_files().add_file(path, contents, metadata)
13
-
14
- @cache_on_self
15
- def table_files(self):
16
- return Sqlite__Table__Files(database=self).setup()
17
-
18
- def files(self):
19
- return self.table_files().files()
20
-
21
- def setup(self):
22
- self.table_files()
23
- return self
@@ -1,45 +0,0 @@
1
- from osbot_utils.base_classes.Kwargs_To_Self import Kwargs_To_Self
2
- from osbot_utils.helpers.sqlite.Sqlite__Table import Sqlite__Table
3
- from osbot_utils.utils.Misc import timestamp_utc_now
4
-
5
- SQLITE__TABLE_NAME__FILES = 'files'
6
-
7
- class Schema__Table__Files(Kwargs_To_Self):
8
- path : str
9
- contents : bytes
10
- metadata : bytes
11
- timestamp: int
12
-
13
-
14
- class Sqlite__Table__Files(Sqlite__Table):
15
- auto_pickle_blob : bool = True
16
- set_timestamp : bool = True
17
-
18
- def __init__(self, **kwargs):
19
- self.table_name = SQLITE__TABLE_NAME__FILES
20
- self.row_schema = Schema__Table__Files
21
- super().__init__(**kwargs)
22
-
23
- def add_file(self, path, contents=None, metadata= None):
24
- if self.contains(path=path): # don't allow multiple entries for the same file path (until we add versioning support)
25
- return None
26
- row_data = self.create_node_data(path, contents, metadata)
27
- return self.add_row_and_commit(**row_data)
28
-
29
- def create_node_data(self, path, contents=None, metadata= None):
30
- node_data = {'path' : path ,
31
- 'contents': contents ,
32
- 'metadata': metadata }
33
- if self.set_timestamp:
34
- node_data['timestamp'] = timestamp_utc_now()
35
- return node_data
36
-
37
-
38
- def files(self):
39
- return self.rows()
40
-
41
- def setup(self):
42
- if self.exists() is False:
43
- self.create()
44
- self.index_create('path')
45
- return self