danielutils 0.9.84__tar.gz → 0.9.91__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 (239) hide show
  1. {danielutils-0.9.84/danielutils.egg-info → danielutils-0.9.91}/PKG-INFO +1 -1
  2. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/__init__.py +2 -1
  3. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/multiprogramming/worker.py +2 -1
  4. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/aliases.py +6 -7
  5. danielutils-0.9.91/danielutils/context_managers/__init__.py +5 -0
  6. danielutils-0.9.91/danielutils/context_managers/optional_context.py +18 -0
  7. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/context_managers/temporary_file.py +11 -11
  8. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/custom_types.py +6 -1
  9. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/__init__.py +1 -0
  10. danielutils-0.9.91/danielutils/data_structures/algorithms.py +44 -0
  11. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/decorate_conditionally.py +1 -1
  12. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/memo.py +21 -2
  13. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/overload.py +2 -2
  14. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/processify.py +3 -1
  15. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/file_specifications/__init__.py +4 -3
  16. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/__init__.py +2 -0
  17. danielutils-0.9.91/danielutils/functions/factorial.py +5 -0
  18. danielutils-0.9.91/danielutils/functions/partition.py +37 -0
  19. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/generators/join_generators.py +1 -1
  20. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/progress_bar/ascii_progress_bar.py +26 -15
  21. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/progress_bar/progress_bar.py +7 -2
  22. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/callstack.py +4 -2
  23. danielutils-0.9.91/danielutils/retry_executor/__init__.py +3 -0
  24. danielutils-0.9.91/danielutils/retry_executor/backoff_strategies/__init__.py +3 -0
  25. danielutils-0.9.91/danielutils/retry_executor/backoff_strategies/constant_backoff.py +19 -0
  26. danielutils-0.9.91/danielutils/retry_executor/backoff_strategies/exponential_backoff.py +21 -0
  27. danielutils-0.9.91/danielutils/retry_executor/backoff_strategies/no_backoff.py +12 -0
  28. danielutils-0.9.91/danielutils/retry_executor/backoff_strategy.py +22 -0
  29. danielutils-0.9.91/danielutils/retry_executor/retry_executor.py +37 -0
  30. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/layered_command.py +3 -3
  31. danielutils-0.9.91/danielutils/testing/__init__.py +1 -0
  32. danielutils-0.9.91/danielutils/testing/unittest_/__init__.py +2 -0
  33. danielutils-0.9.91/danielutils/testing/unittest_/always_teardown_testcase.py +37 -0
  34. danielutils-0.9.91/danielutils/testing/unittest_/auto_cwd_testcase.py +49 -0
  35. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/computability_and_complexity/__init__.py +1 -0
  36. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/computability_and_complexity/discreate_finite_automaton.py +21 -0
  37. danielutils-0.9.91/danielutils/university/computability_and_complexity/languages/language.py +17 -0
  38. danielutils-0.9.91/danielutils/university/computability_and_complexity/languages/sat.py +69 -0
  39. danielutils-0.9.91/danielutils/university/computability_and_complexity/turing_machine.py +47 -0
  40. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/databases/all.py +2 -2
  41. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossless/run_length.py +3 -2
  42. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/linear_algebra/matrix.py +5 -5
  43. danielutils-0.9.91/danielutils/university/probability/conditional_variable/continuous/__init__.py +0 -0
  44. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/funcs/expected_value.py +1 -1
  45. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/transformation.py +2 -2
  46. {danielutils-0.9.84 → danielutils-0.9.91/danielutils.egg-info}/PKG-INFO +1 -1
  47. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils.egg-info/SOURCES.txt +19 -0
  48. {danielutils-0.9.84 → danielutils-0.9.91}/pyproject.toml +1 -1
  49. danielutils-0.9.84/danielutils/context_managers/__init__.py +0 -3
  50. {danielutils-0.9.84 → danielutils-0.9.91}/LICENSE +0 -0
  51. {danielutils-0.9.84 → danielutils-0.9.91}/MANIFEST.in +0 -0
  52. {danielutils-0.9.84 → danielutils-0.9.91}/README.md +0 -0
  53. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/__init__.py +0 -0
  54. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/database/__init__.py +0 -0
  55. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/database/cached_database.py +0 -0
  56. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/database/database.py +0 -0
  57. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/database/redis_database.py +0 -0
  58. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/multiprogramming/__init__.py +0 -0
  59. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/multiprogramming/multi_id.py +0 -0
  60. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/multiprogramming/worker_pool.py +0 -0
  61. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/abstractions/repl.py +0 -0
  62. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/__init__.py +0 -0
  63. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/counter.py +0 -0
  64. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/frange.py +0 -0
  65. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/__init__.py +0 -0
  66. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/factory.py +0 -0
  67. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/tdict.py +0 -0
  68. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/tlist.py +0 -0
  69. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/tset.py +0 -0
  70. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/better_builtins/typed_builtins/ttuple.py +0 -0
  71. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/colors.py +0 -0
  72. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/context_managers/attr_context.py +0 -0
  73. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/context_managers/multi_context.py +0 -0
  74. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/context_managers/state_context.py +0 -0
  75. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/convenience.py +0 -0
  76. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/conversions/__init__.py +0 -0
  77. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/conversions/main_conversions.py +0 -0
  78. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/conversions/specialized_conversions/__init__.py +0 -0
  79. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/conversions/specialized_conversions/to_hex.py +0 -0
  80. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/conversions/specialized_conversions/to_int.py +0 -0
  81. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/comparer.py +0 -0
  82. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/default_dict.py +0 -0
  83. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/functions.py +0 -0
  84. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/graph/__init__.py +0 -0
  85. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/graph/binary_node.py +0 -0
  86. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/graph/graph.py +0 -0
  87. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/graph/multinode.py +0 -0
  88. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/graph/node.py +0 -0
  89. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/heap/__init__.py +0 -0
  90. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/heap/heap.py +0 -0
  91. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/heap/max_heap.py +0 -0
  92. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/heap/min_heap.py +0 -0
  93. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/queue/__init__.py +0 -0
  94. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/queue/atomic_queue.py +0 -0
  95. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/queue/priority_queue.py +0 -0
  96. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/queue/queue.py +0 -0
  97. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/stack.py +0 -0
  98. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/trees/__init__.py +0 -0
  99. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/trees/binary_syntax_tree.py +0 -0
  100. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/data_structures/trees/binary_tree.py +0 -0
  101. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/date.py +0 -0
  102. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/date_time.py +0 -0
  103. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/__init__.py +0 -0
  104. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/atomic.py +0 -0
  105. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/attach.py +0 -0
  106. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/chain_decorators.py +0 -0
  107. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/delay_call.py +0 -0
  108. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/deprecate.py +0 -0
  109. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/final.py +0 -0
  110. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/limit_recursion.py +0 -0
  111. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/partially_implemented.py +0 -0
  112. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/property.py +0 -0
  113. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/singleton.py +0 -0
  114. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/threadify.py +0 -0
  115. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/timeout.py +0 -0
  116. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/total_ordering.py +0 -0
  117. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/decorators/validate.py +0 -0
  118. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/exceptions.py +0 -0
  119. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/areoneof.py +0 -0
  120. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/check_foreach.py +0 -0
  121. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/flatten.py +0 -0
  122. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/foreach.py +0 -0
  123. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/isoftype.py +0 -0
  124. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/isoneof.py +0 -0
  125. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/multiloop.py +0 -0
  126. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/parallel_for.py +0 -0
  127. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/powerset.py +0 -0
  128. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/subseteq.py +0 -0
  129. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/functions/types_subseteq.py +0 -0
  130. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/generators/__init__.py +0 -0
  131. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/generators/conditional_generator.py +0 -0
  132. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/generators/generator_from_stream.py +0 -0
  133. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/internet.py +0 -0
  134. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/io_.py +0 -0
  135. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/math_/__init__.py +0 -0
  136. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/math_/constants.py +0 -0
  137. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/math_/functions.py +0 -0
  138. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/math_/math_print.py +0 -0
  139. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/math_/math_symbols.py +0 -0
  140. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/__init__.py +0 -0
  141. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/atomic_class_meta.py +0 -0
  142. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/implicit_data_deleter_meta.py +0 -0
  143. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/instance_cache_meta.py +0 -0
  144. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/interface.py +0 -0
  145. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/metaclasses/overload_meta.py +0 -0
  146. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/mock_/__init__.py +0 -0
  147. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/mock_/mock_database.py +0 -0
  148. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/mock_/mock_module.py +0 -0
  149. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/path.py +0 -0
  150. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/print_.py +0 -0
  151. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/progress_bar/__init__.py +0 -0
  152. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/progress_bar/progress_bar_pool.py +0 -0
  153. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/protocols/__init__.py +0 -0
  154. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/protocols/dictable.py +0 -0
  155. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/protocols/evaluable.py +0 -0
  156. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/protocols/serializable.py +0 -0
  157. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/py.typed +0 -0
  158. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/__init__.py +0 -0
  159. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/class_/__init__.py +0 -0
  160. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/class_/class_reflection.py +0 -0
  161. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/file/__init__.py +0 -0
  162. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/file/file_reflection.py +0 -0
  163. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/function/__init__.py +0 -0
  164. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/function/function_reflections.py +0 -0
  165. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/__init__.py +0 -0
  166. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/get_traceback.py +0 -0
  167. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/os_.py +0 -0
  168. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/packages.py +0 -0
  169. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/python_version.py +0 -0
  170. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/signals.py +0 -0
  171. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/interpreter/tracer.py +0 -0
  172. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/module/__init__.py +0 -0
  173. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/module/module_reflections.py +0 -0
  174. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/reflection/module/package_reflection.py +0 -0
  175. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/snippets/__init__.py +0 -0
  176. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/snippets/try_get.py +0 -0
  177. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/__init__.py +0 -0
  178. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/independent.py +0 -0
  179. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/windows/__init__.py +0 -0
  180. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/windows/utils/__init__.py +0 -0
  181. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/windows/utils/filetime.py +0 -0
  182. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/windows/win32_ctime.py +0 -0
  183. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/system/windows/windows.py +0 -0
  184. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/text.py +0 -0
  185. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/time.py +0 -0
  186. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/__init__.py +0 -0
  187. {danielutils-0.9.84/danielutils/university/image_proccesing/tansformations → danielutils-0.9.91/danielutils/university/computability_and_complexity/languages}/__init__.py +0 -0
  188. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/databases/__init__.py +0 -0
  189. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/__init__.py +0 -0
  190. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/__init__.py +0 -0
  191. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/encoding.py +0 -0
  192. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossless/__init__.py +0 -0
  193. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossless/huffman.py +0 -0
  194. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossless/lossless_encoding.py +0 -0
  195. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossless/lzw.py +0 -0
  196. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossy/__init__.py +0 -0
  197. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/encoding/lossy/lossy_encoding.py +0 -0
  198. {danielutils-0.9.84/danielutils/university/machine_learning → danielutils-0.9.91/danielutils/university/image_proccesing/tansformations}/__init__.py +0 -0
  199. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/tansformations/gaussian.py +0 -0
  200. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/tansformations/gradient.py +0 -0
  201. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/tansformations/hough.py +0 -0
  202. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/tansformations/laplacian.py +0 -0
  203. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/image_proccesing/tansformations/transformation.py +0 -0
  204. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/linear_algebra/__init__.py +0 -0
  205. {danielutils-0.9.84/danielutils/university/probability/conditional_variable/continuous → danielutils-0.9.91/danielutils/university/machine_learning}/__init__.py +0 -0
  206. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/machine_learning/activation_functions/__init__.py +0 -0
  207. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/machine_learning/activation_functions/activation_function.py +0 -0
  208. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/machine_learning/activation_functions/relu.py +0 -0
  209. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/machine_learning/neuron.py +0 -0
  210. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/oop/__init__.py +0 -0
  211. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/oop/observer.py +0 -0
  212. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/oop/strategy.py +0 -0
  213. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/__init__.py +0 -0
  214. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/__init__.py +0 -0
  215. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/conditional_variable.py +0 -0
  216. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/__init__.py +0 -0
  217. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/bernoulli.py +0 -0
  218. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/binomial.py +0 -0
  219. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/conditional_from_discrete_probability_func.py +0 -0
  220. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/discrete.py +0 -0
  221. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/geometric.py +0 -0
  222. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/poisson.py +0 -0
  223. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/conditional_variable/discrete/uniform.py +0 -0
  224. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/distributions.py +0 -0
  225. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/expressions/__init__.py +0 -0
  226. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/expressions/accumulation_expression.py +0 -0
  227. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/expressions/probability_expression.py +0 -0
  228. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/funcs/__init__.py +0 -0
  229. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/funcs/covariance.py +0 -0
  230. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/funcs/probability_function.py +0 -0
  231. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/funcs/variance.py +0 -0
  232. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/operator.py +0 -0
  233. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/protocols.py +0 -0
  234. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/university/probability/supp.py +0 -0
  235. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils/versioned_imports.py +0 -0
  236. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils.egg-info/dependency_links.txt +0 -0
  237. {danielutils-0.9.84 → danielutils-0.9.91}/danielutils.egg-info/top_level.txt +0 -0
  238. {danielutils-0.9.84 → danielutils-0.9.91}/setup.cfg +0 -0
  239. {danielutils-0.9.84 → danielutils-0.9.91}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: danielutils
3
- Version: 0.9.84
3
+ Version: 0.9.91
4
4
  Summary: A python utils library for things I find useful
5
5
  Author-email: danielnachumdev <danielnachumdev@gmail.com>
6
6
  License: MIT License
@@ -40,4 +40,5 @@ from .generators import *
40
40
  from .university import *
41
41
  from .mock_ import *
42
42
  from .context_managers import *
43
- from .file_specifications import *
43
+ from .file_specifications import *
44
+ from .testing import *
@@ -12,7 +12,7 @@ class Worker(ABC):
12
12
  """A Worker Interface
13
13
  """
14
14
 
15
- def __init__(self, id: int, pool: "danielutils.Threading.worker_pool.WorkerPool") -> None: # pylint: disable=redefined-builtin #noqa
15
+ def __init__(self, id: int, pool: "danielutils.abstractions.multiprogramming.worker_pool.WorkerPool") -> None: # pylint: disable=redefined-builtin #noqa
16
16
  self.id = id
17
17
  self.pool = pool
18
18
  self.thread: Thread = Thread(target=self._loop)
@@ -57,6 +57,7 @@ class Worker(ABC):
57
57
  to signal actions if needed
58
58
  will call 'notification_function'
59
59
  """
60
+ # TODO
60
61
  self.pool._notify_subscribers() # pylint: disable=protected-access
61
62
 
62
63
  def acquire(self) -> Optional[Tuple[Any]]:
@@ -150,16 +150,15 @@ T = TypeVar("T")
150
150
 
151
151
  Supplier = Callable[[], T]
152
152
  Runnable = Supplier[None]
153
-
153
+ Consumer = Callable[[T], None]
154
154
  UnaryFunction = Callable[[U], T]
155
- UnaryOperator = UnaryFunction[T, T]
156
- Predicate = UnaryFunction[T, bool]
157
- Consumer = UnaryFunction[T, None]
155
+ UnaryOperator = Callable[[T], T]
156
+ Predicate = Callable[[T], bool]
158
157
 
159
158
  BinaryFunction = Callable[[A, B], T]
160
- BinaryOperator = BinaryFunction[T, T, T]
161
- Comparator = BinaryFunction[A, B, int]
162
- BinaryConsumer = BinaryFunction[T, T, None]
159
+ BinaryOperator = Callable[[T, T], T]
160
+ Comparator = Callable[[A, B], int]
161
+ BinaryConsumer = Callable[[T, T], None]
163
162
 
164
163
  __all__ = [
165
164
  "UnaryFunction",
@@ -0,0 +1,5 @@
1
+ from .attr_context import *
2
+ from .multi_context import *
3
+ from .optional_context import *
4
+ from .state_context import *
5
+ from .temporary_file import *
@@ -0,0 +1,18 @@
1
+ from typing import ContextManager
2
+ class OptionalContext(ContextManager):
3
+ def __init__(self, predicate: bool, context: ContextManager):
4
+ self.predicate = predicate
5
+ self.context = context
6
+
7
+ def __enter__(self):
8
+ if self.predicate:
9
+ self.context.__enter__()
10
+
11
+ def __exit__(self, __exc_type, __exc_value, __traceback):
12
+ if self.predicate:
13
+ self.context.__exit__(__exc_type, __exc_value, __traceback)
14
+
15
+
16
+ __all__=[
17
+ "OptionalContext"
18
+ ]
@@ -1,10 +1,10 @@
1
- from typing import ContextManager
2
- from ..io_ import file_exists, delete_file
3
1
  import atexit
2
+ from typing import ContextManager, Set, List
3
+ from ..io_ import file_exists, delete_file
4
4
 
5
5
 
6
6
  class TemporaryFile(ContextManager):
7
- _instances: set['TemporaryFile'] = set()
7
+ _instances: Set['TemporaryFile'] = set()
8
8
 
9
9
  def __init__(self, path: str):
10
10
  if file_exists(path):
@@ -18,22 +18,16 @@ class TemporaryFile(ContextManager):
18
18
  def __exit__(self, exc_type, exc_val, exc_tb):
19
19
  self.close()
20
20
 
21
- @atexit.register
22
- @staticmethod
23
- def _global_close():
24
- for inst in TemporaryFile._instances:
25
- inst.close()
26
-
27
21
  def close(self) -> None:
28
22
  delete_file(self.path)
29
23
 
30
- def read(self) -> list[str]:
24
+ def read(self) -> List[str]:
31
25
  if not file_exists(self.path):
32
26
  return []
33
27
  with open(self.path, 'r') as f:
34
28
  return f.readlines()
35
29
 
36
- def write(self, lines: list[str]) -> None:
30
+ def write(self, lines: List[str]) -> None:
37
31
  with open(self.path, 'a') as f:
38
32
  f.writelines(lines)
39
33
 
@@ -42,6 +36,12 @@ class TemporaryFile(ContextManager):
42
36
  pass
43
37
 
44
38
 
39
+ @atexit.register
40
+ def __close_all():
41
+ for inst in TemporaryFile._instances: # type:ignore #pylint: disable=all
42
+ inst.close()
43
+
44
+
45
45
  __all__ = [
46
46
  'TemporaryFile'
47
47
  ]
@@ -1,4 +1,9 @@
1
- from typing import TypeAlias, Callable, TypeVar, Generic
1
+ from typing import Callable, TypeVar, Generic
2
+
3
+ try:
4
+ from typing import TypeAlias
5
+ except ImportError:
6
+ from typing_extensions import TypeAlias
2
7
 
3
8
  T = TypeVar('T')
4
9
  U = TypeVar('U')
@@ -5,3 +5,4 @@ from .graph import *
5
5
  from .stack import *
6
6
  from .default_dict import *
7
7
  from .trees import *
8
+ from .algorithms import *
@@ -0,0 +1,44 @@
1
+ from collections import defaultdict
2
+ from typing import TypeVar, List, Callable, Dict
3
+ from itertools import product
4
+ from copy import deepcopy
5
+
6
+ NodeT = TypeVar("NodeT")
7
+
8
+ DistanceMatrix = Dict[NodeT, Dict[NodeT, float]]
9
+
10
+
11
+ def bellman_ford(nodes: List[NodeT], weight_func: Callable[[NodeT, NodeT], float],
12
+ iteration_callback: Callable[[DistanceMatrix], None],
13
+ poisoned_reverse: bool = False) -> DistanceMatrix:
14
+ dist: Dict[NodeT, Dict[NodeT, float]] = defaultdict(defaultdict)
15
+ prev: Dict[NodeT, Dict[NodeT, NodeT]] = defaultdict(defaultdict)
16
+
17
+ for u, v in product(nodes, nodes):
18
+ dist[u][v] = weight_func(u, v)
19
+
20
+ iteration_callback(dist)
21
+
22
+ for _ in range(len(nodes) - 1):
23
+ tmp = deepcopy(dist)
24
+ for u, v in product(nodes, nodes):
25
+ if u == v:
26
+ continue
27
+
28
+ for mid in nodes:
29
+ if mid == u or mid == v:
30
+ continue
31
+
32
+ if dist[u][v] > dist[u][mid] + dist[mid][v]:
33
+ tmp[u][v] = dist[u][mid] + dist[mid][v]
34
+ prev[u][v] = mid
35
+
36
+ dist = tmp
37
+ iteration_callback(dist)
38
+
39
+ iteration_callback(prev)
40
+
41
+
42
+ __all__ = [
43
+ "bellman_ford"
44
+ ]
@@ -3,7 +3,7 @@ from typing import Callable, Optional, Union
3
3
  from .validate import validate
4
4
 
5
5
 
6
- @validate # type:ignore(strict=False)
6
+ @validate(strict=False) # type:ignore
7
7
  def decorate_conditionally(decorator: Callable, predicate: Union[bool, Callable[[], bool]], *,
8
8
  decorator_args: Optional[list] = None, decorator_kwargs: Optional[dict] = None):
9
9
  """will decorate a function iff the predicate is True or returns True
@@ -1,5 +1,5 @@
1
1
  import functools
2
- from typing import Callable, Any, TypeVar, Dict
2
+ from typing import Callable, Any, TypeVar, Dict, Generator, List, Set, Optional
3
3
  from copy import deepcopy
4
4
  from .validate import validate
5
5
  from ..versioned_imports import ParamSpec
@@ -27,6 +27,25 @@ def memo(func: FuncT) -> FuncT:
27
27
  return wrapper
28
28
 
29
29
 
30
+ def memo_generator(func: Callable[P, Generator]) -> Callable[P, Generator]:
31
+ cache: Dict[tuple, Any] = {}
32
+
33
+ @functools.wraps(func)
34
+ def wrapper(*args: P.args, **kwargs: P.kwargs) -> Generator:
35
+ args = tuple(args)
36
+ if (args, *kwargs.items()) not in cache:
37
+ lst = []
38
+ for v in func(*args, **kwargs):
39
+ lst.append(v)
40
+ yield v
41
+ cache[(args, *kwargs.items())] = lst
42
+ else:
43
+ yield from cache[(args, *kwargs.items())]
44
+
45
+ return wrapper
46
+
47
+
30
48
  __all__ = [
31
- "memo"
49
+ "memo",
50
+ "memo_generator"
32
51
  ]
@@ -1,4 +1,4 @@
1
- from typing import Callable, cast, Any, TypeVar, Dict
1
+ from typing import Callable, cast, Any, TypeVar, Dict, List
2
2
  import inspect
3
3
  import functools
4
4
  from ..reflection import is_function_annotated_properly
@@ -122,7 +122,7 @@ class overload:
122
122
  overload._validate(func)
123
123
  self._qualname = func.__qualname__
124
124
  self._moudle = func.__module__
125
- self._functions: Dict[int, Dict[Callable]] = {}
125
+ self._functions: Dict[int, List[Callable]] = {}
126
126
  self._functions[overload._get_key(func)] = [func]
127
127
  functools.wraps(func)(self)
128
128
 
@@ -35,12 +35,14 @@ def processify(func):
35
35
  return wrapper
36
36
 
37
37
 
38
-
39
38
  def _run_func(main_pid: int, dct: dict, func_name: str, args, kwargs) -> None:
40
39
  return dct[func_name](*args, __main_pid=main_pid, **kwargs)
41
40
 
41
+
42
42
  def debug_info(include_builtins: bool = False) -> dict:
43
43
  f = get_prev_frame(2)
44
+ if f is None:
45
+ raise RuntimeError("Failed to get frame")
44
46
  g = {k: v for k, v in f.f_globals.items() if k != "__builtins__"} if not include_builtins else dict(f.f_globals)
45
47
  return {
46
48
  "file": f.f_code.co_filename,
@@ -1,5 +1,5 @@
1
1
  from dataclasses import dataclass
2
- from typing import Optional
2
+ from typing import Optional, List
3
3
  from enum import Enum
4
4
 
5
5
 
@@ -29,12 +29,13 @@ class Field:
29
29
  class Section:
30
30
  name: str
31
31
  prefix: bytes
32
- fields: Optional[list[Field]]
32
+ fields: Optional[List[Field]]
33
33
  is_optional: bool = False
34
34
 
35
35
 
36
36
  class FileSpecification:
37
- def __init__(self, long_name: str, short_name: str, extension: str, specification: str, sections: list[Section]):
37
+ def __init__(self, long_name: str, short_name: str, extension: str, specification: str,
38
+ sections: List[Section]) -> None:
38
39
  """
39
40
 
40
41
  Args:
@@ -9,3 +9,5 @@ from .flatten import *
9
9
  from .subseteq import *
10
10
  from .parallel_for import *
11
11
  from .foreach import *
12
+ from .factorial import *
13
+ from .partition import *
@@ -0,0 +1,5 @@
1
+ def factorial(n: int) -> int:
2
+ res = 1
3
+ for i in range(2, n + 1):
4
+ res *= i
5
+ return res
@@ -0,0 +1,37 @@
1
+ from typing import List, Generator, Tuple, Union
2
+
3
+
4
+ def partitions(n: int, k: int) -> Generator[List[int], None, None]:
5
+ from ..decorators import memo_generator
6
+
7
+ @memo_generator()
8
+ def helper(n: int, target_sum: int, current_sum: int, topLevel: int, arr: Union[List[int], Tuple[int]]) -> \
9
+ Generator[List[int], None, None]:
10
+ arr = list(arr)
11
+ if n == 1:
12
+ if current_sum <= target_sum:
13
+ if topLevel == 1 or (target_sum - current_sum >= arr[-2]):
14
+ arr[-1] = target_sum - current_sum
15
+ yield tuple(arr)
16
+ return
17
+
18
+ start = 0
19
+ if n != topLevel:
20
+ start = arr[-1 * n - 1]
21
+
22
+ for i in range(start, target_sum + 1):
23
+ arr[-1 * n] = i
24
+ yield from helper(n - 1, target_sum, current_sum + i, topLevel, tuple(arr))
25
+
26
+ arr: List[int] = [0] * k
27
+ yield from helper(k, n, 0, k, tuple(arr))
28
+
29
+
30
+ def num_partitions(n: int, k: int) -> int:
31
+ return len(list(partitions(n, k)))
32
+
33
+
34
+ __all__ = [
35
+ "partitions",
36
+ "num_partitions"
37
+ ]
@@ -44,7 +44,7 @@ def join_generators(*generators) -> Generator[Tuple[int, Any], None, None]:
44
44
  Yields:
45
45
  Generator[Any, None, None]: one generator that combines all of the given ones
46
46
  """
47
- queue = Queue()
47
+ queue: Queue = Queue()
48
48
  edit_queue_semaphore = Semaphore(1)
49
49
  queue_status_semaphore = Semaphore(0)
50
50
  finished_threads_counter = AtomicCounter()
@@ -1,5 +1,5 @@
1
1
  import time
2
- from typing import Optional, Iterable, Sized
2
+ from typing import Optional, Iterable, Sized, Iterator
3
3
 
4
4
  from .progress_bar import ProgressBar
5
5
  from .progress_bar_pool import ProgressBarPool
@@ -10,7 +10,7 @@ class AsciiProgressBar(ProgressBar):
10
10
 
11
11
  def __init__(
12
12
  self,
13
- iterable: Iterable,
13
+ iterator: Iterator,
14
14
  position: int,
15
15
  *,
16
16
  total: Optional[float] = None,
@@ -18,20 +18,19 @@ class AsciiProgressBar(ProgressBar):
18
18
  leave: bool = True,
19
19
  num_bars: int = 1,
20
20
  ncols: int = 50,
21
- pool: Optional = None,
21
+ pool: Optional[ProgressBarPool] = None,
22
22
  **kwargs
23
23
  ):
24
24
  total_ = 1
25
- if isinstance(iterable, Sized):
26
- total_ = len(iterable)
25
+ if isinstance(iterator, Sized):
26
+ total_ = len(iterator)
27
27
  if total is not None:
28
28
  total_ = total
29
- ProgressBar.__init__(self, total_, position)
30
- self.iterable: Iterable = iterable
29
+ ProgressBar.__init__(self, total_, position, desc=desc)
30
+ self.iterator: Iterator = iterator
31
31
  self.pool: ProgressBarPool = pool
32
32
  self.num_bars: int = num_bars
33
33
  self.leave: bool = leave
34
- self.desc: str = desc
35
34
  self.initial_value: float = 0
36
35
  self.current_value: float = 0
37
36
  self.ncols: int = ncols
@@ -47,16 +46,18 @@ class AsciiProgressBar(ProgressBar):
47
46
 
48
47
  def __iter__(self):
49
48
  self.bprint_row_index = bprint.current_row
50
- for v in self.iterable:
49
+ for v in self.iterator:
51
50
  self.update(0)
52
51
  yield v
53
52
  bprint.move_up()
54
53
  bprint.clear_line()
55
- bprint.rows.pop()
54
+ if len(bprint.rows) > 0:
55
+ bprint.rows.pop()
56
56
  self.update(1)
57
57
  bprint.move_up()
58
58
  bprint.clear_line()
59
- bprint.rows.pop()
59
+ if len(bprint.rows) > 0:
60
+ bprint.rows.pop()
60
61
  if self.position > 0:
61
62
  self.reset()
62
63
  else:
@@ -79,11 +80,21 @@ class AsciiProgressBar(ProgressBar):
79
80
  unit=self.unit
80
81
  )
81
82
  if refresh and self.pool is not None and len(self.pool.bars) > 1:
82
- for w in self.writes:
83
- bprint(w, end="")
84
- bprint(to_print)
83
+ i = bprint.rows.index(f"{self.prev_print}\n")
84
+ rows = [to_print]
85
+ for j, row in enumerate(bprint.rows[i + 1:]):
86
+ rows.append(row)
87
+ for row in rows:
88
+ bprint.move_up(1)
89
+ bprint.clear_line()
90
+ bprint.rows.pop()
91
+ for row in rows:
92
+ bprint(row)
93
+ else:
94
+ bprint(to_print)
95
+ self.prev_print = to_print
85
96
 
86
- def update(self, amount: float = 1, refresh: bool = False):
97
+ def update(self, amount: float = 1, refresh: bool = False): # type:ignore
87
98
  self.prev_value = self.current_value
88
99
  self.current_value = min(
89
100
  self.current_value + amount, self.total) # type:ignore
@@ -20,7 +20,9 @@ class ProgressBar(ABC):
20
20
  DEFAULT_BAR_FORMAT = "{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}"
21
21
 
22
22
  @abstractmethod
23
- def __init__(self, total, position: int, unit="it", bar_format: str = DEFAULT_BAR_FORMAT, **kwargs) -> None:
23
+ def __init__(self, total, position: int, unit="it", bar_format: str = DEFAULT_BAR_FORMAT, *, desc: str,
24
+ **kwargs) -> None:
25
+ self.desc: str = desc
24
26
  self.total = total
25
27
  self.position = position
26
28
  self.unit = unit
@@ -32,7 +34,7 @@ class ProgressBar(ABC):
32
34
  return len(self.writes)
33
35
 
34
36
  @abstractmethod
35
- def update(self, amount: float = 1) -> None:
37
+ def update(self, amount: float = 1, **kwargs) -> None:
36
38
  """A function to update the progress-bar's value by a positive relative amount
37
39
  """
38
40
 
@@ -51,6 +53,9 @@ class ProgressBar(ABC):
51
53
  """A function to reset the progress-bar's progress
52
54
  """
53
55
 
56
+ @abstractmethod
57
+ def __iter__(self): ...
58
+
54
59
 
55
60
  try:
56
61
  from tqdm import tqdm
@@ -25,8 +25,10 @@ def get_prev_frame(n_steps: int = 1) -> Optional[FrameType]:
25
25
 
26
26
  def get_prev_line_of_code(n_steps: int = 1) -> Optional[str]:
27
27
  frame = get_prev_frame(n_steps + 1)
28
- file = frame.f_back.f_code.co_filename
29
- line_number = frame.f_back.f_lineno - 1
28
+ if frame is None:
29
+ return None
30
+ file = frame.f_back.f_code.co_filename # type:ignore
31
+ line_number = frame.f_back.f_lineno - 1 # type:ignore
30
32
  with open(file, "r", encoding="utf-8") as f:
31
33
  lines = f.readlines()
32
34
  line = lines[line_number]
@@ -0,0 +1,3 @@
1
+ from .backoff_strategies import *
2
+ from .backoff_strategy import *
3
+ from .retry_executor import *
@@ -0,0 +1,3 @@
1
+ from .no_backoff import *
2
+ from .constant_backoff import *
3
+ from .exponential_backoff import *
@@ -0,0 +1,19 @@
1
+ from ..backoff_strategy import BackOffStrategy
2
+
3
+
4
+ class ConstantBackOffStrategy(BackOffStrategy):
5
+ """
6
+ will always back off exactly the same amount of time
7
+
8
+ :param delay: The amount of milliseconds to sleep
9
+ """
10
+
11
+ def __init__(self, delay: int) -> None:
12
+ if not delay >= 0:
13
+ raise ValueError("delay must be positive")
14
+ super().__init__(lambda: delay)
15
+
16
+
17
+ __all__ = [
18
+ "ConstantBackOffStrategy"
19
+ ]
@@ -0,0 +1,21 @@
1
+ from ..backoff_strategy import BackOffStrategy
2
+
3
+
4
+ class ExponentialBackOffStrategy(BackOffStrategy):
5
+ def __init__(self, initial: int, multiplier: float) -> None:
6
+ if not initial >= 0:
7
+ raise ValueError("initial must be positive")
8
+ if not multiplier >= 0:
9
+ raise ValueError("multiplier must be positive")
10
+ prev: float = 1.0
11
+
12
+ def inner() -> int:
13
+ nonlocal prev
14
+ return initial ** (prev := prev * multiplier)
15
+
16
+ super().__init__(inner)
17
+
18
+
19
+ __all__ = [
20
+ "ExponentialBackOffStrategy"
21
+ ]
@@ -0,0 +1,12 @@
1
+ from ..backoff_strategy import BackOffStrategy
2
+
3
+
4
+ class NoBackOffStrategy(BackOffStrategy):
5
+
6
+ def __init__(self) -> None:
7
+ super().__init__(lambda: 0)
8
+
9
+
10
+ __all__ = [
11
+ 'NoBackOffStrategy',
12
+ ]
@@ -0,0 +1,22 @@
1
+ from danielutils import Supplier
2
+
3
+
4
+ class BackOffStrategy:
5
+ """
6
+ A class to create a common abstraction for backoff strategies
7
+ """
8
+
9
+ def __init__(self, supp: Supplier[int]) -> None:
10
+ self._supp = supp
11
+
12
+ def get_backoff(self) -> int:
13
+ """
14
+
15
+ :return: amount of milliseconds to sleep
16
+ """
17
+ return self._supp()
18
+
19
+
20
+ __all__ = [
21
+ "BackOffStrategy"
22
+ ]
@@ -0,0 +1,37 @@
1
+ import time
2
+ from typing import Generic, TypeVar, Optional
3
+
4
+ from danielutils import Supplier, Consumer
5
+ from .backoff_strategies import ConstantBackOffStrategy
6
+
7
+ from .backoff_strategy import BackOffStrategy
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ class RetryExecutor(Generic[T]):
13
+ def __init__(self, backoff_strategy: BackOffStrategy = ConstantBackOffStrategy(200)) -> None:
14
+ self._backoff_strategy = backoff_strategy
15
+
16
+ def execute(self, supp: Supplier[T], max_retries: int = 5,
17
+ exception_callback: Optional[Consumer[Exception]] = None) -> Optional[T]:
18
+
19
+ for i in range(max_retries):
20
+
21
+ try:
22
+ return supp()
23
+ except Exception as e:
24
+ if exception_callback:
25
+ exception_callback(e)
26
+
27
+ if i != max_retries - 1:
28
+ self._sleep()
29
+ return None
30
+
31
+ def _sleep(self) -> None:
32
+ time.sleep(self._backoff_strategy.get_backoff())
33
+
34
+
35
+ __all__ = [
36
+ "RetryExecutor",
37
+ ]
@@ -1,5 +1,5 @@
1
1
  import sys, os
2
- from typing import Optional
2
+ from typing import Optional, Tuple, List
3
3
  from ..context_managers import TemporaryFile
4
4
  import random
5
5
 
@@ -79,7 +79,7 @@ class LayeredCommand:
79
79
  command_flush_stderr: Optional[bool] = None,
80
80
  command_raise_on_fail: Optional[bool] = None,
81
81
  command_verbose: Optional[bool] = None
82
- ) -> tuple[int, list[str], list[str]]:
82
+ ) -> Tuple[int, List[str], List[str]]:
83
83
  if not self._has_entered:
84
84
  raise RuntimeError(
85
85
  "LayeredCommand must be used with a context manager. Use as: `with LayeredCommand(...) as l1:`")
@@ -109,7 +109,7 @@ class LayeredCommand:
109
109
  self._error(raise_on_fail and code != 0, command, code, command_verbose)
110
110
  return code, stdout.read(), stderr.read()
111
111
 
112
- def __call__(self, *args, **kwargs) -> tuple[int, list[str], list[str]]:
112
+ def __call__(self, *args, **kwargs) -> Tuple[int, List[str], List[str]]:
113
113
  return self.execute(*args, **kwargs)
114
114
 
115
115
 
@@ -0,0 +1 @@
1
+ from .unittest_ import *
@@ -0,0 +1,2 @@
1
+ from .always_teardown_testcase import *
2
+ from .auto_cwd_testcase import *