danielutils 1.1.28__py3-none-any.whl

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 (287) hide show
  1. danielutils/__init__.py +50 -0
  2. danielutils/abstractions/__init__.py +3 -0
  3. danielutils/abstractions/db/__init__.py +10 -0
  4. danielutils/abstractions/db/database.py +206 -0
  5. danielutils/abstractions/db/database_definitions.py +219 -0
  6. danielutils/abstractions/db/database_exceptions.py +34 -0
  7. danielutils/abstractions/db/database_factory.py +70 -0
  8. danielutils/abstractions/db/database_initializer.py +261 -0
  9. danielutils/abstractions/db/database_models.py +213 -0
  10. danielutils/abstractions/db/dependencies.py +6 -0
  11. danielutils/abstractions/db/implementations/__init__.py +4 -0
  12. danielutils/abstractions/db/implementations/in_memory_database.py +365 -0
  13. danielutils/abstractions/db/implementations/persistent_in_memory_database.py +174 -0
  14. danielutils/abstractions/db/implementations/redis_database.py +403 -0
  15. danielutils/abstractions/db/implementations/sqlite_database.py +491 -0
  16. danielutils/abstractions/multiprogramming/__init__.py +3 -0
  17. danielutils/abstractions/multiprogramming/multi_id.py +26 -0
  18. danielutils/abstractions/multiprogramming/worker.py +104 -0
  19. danielutils/abstractions/multiprogramming/worker_pool.py +98 -0
  20. danielutils/abstractions/repl.py +125 -0
  21. danielutils/aliases.py +174 -0
  22. danielutils/async_/__init__.py +7 -0
  23. danielutils/async_/async_cmd.py +28 -0
  24. danielutils/async_/async_command.py +879 -0
  25. danielutils/async_/async_layered_command.py +125 -0
  26. danielutils/async_/async_retry_executor.py +86 -0
  27. danielutils/async_/async_worker_pool.py +110 -0
  28. danielutils/async_/time_strategy.py +73 -0
  29. danielutils/async_/utils.py +57 -0
  30. danielutils/better_builtins/__init__.py +3 -0
  31. danielutils/better_builtins/counter.py +48 -0
  32. danielutils/better_builtins/frange.py +266 -0
  33. danielutils/better_builtins/typed_builtins/__init__.py +4 -0
  34. danielutils/better_builtins/typed_builtins/factory.py +126 -0
  35. danielutils/better_builtins/typed_builtins/tdict.py +36 -0
  36. danielutils/better_builtins/typed_builtins/tlist.py +223 -0
  37. danielutils/better_builtins/typed_builtins/tset.py +67 -0
  38. danielutils/better_builtins/typed_builtins/ttuple.py +15 -0
  39. danielutils/colors.py +203 -0
  40. danielutils/context_managers/__init__.py +5 -0
  41. danielutils/context_managers/attr_context.py +40 -0
  42. danielutils/context_managers/multi_context.py +34 -0
  43. danielutils/context_managers/optional_context.py +33 -0
  44. danielutils/context_managers/state_context.py +25 -0
  45. danielutils/context_managers/temporary_file.py +108 -0
  46. danielutils/convenience.py +12 -0
  47. danielutils/conversions/__init__.py +2 -0
  48. danielutils/conversions/main_conversions.py +131 -0
  49. danielutils/conversions/specialized_conversions/__init__.py +2 -0
  50. danielutils/conversions/specialized_conversions/to_hex.py +25 -0
  51. danielutils/conversions/specialized_conversions/to_int.py +19 -0
  52. danielutils/custom_types.py +18 -0
  53. danielutils/data_structures/__init__.py +8 -0
  54. danielutils/data_structures/algorithms.py +52 -0
  55. danielutils/data_structures/comparer.py +47 -0
  56. danielutils/data_structures/default_dict.py +23 -0
  57. danielutils/data_structures/functions.py +35 -0
  58. danielutils/data_structures/graph/__init__.py +4 -0
  59. danielutils/data_structures/graph/binary_node.py +71 -0
  60. danielutils/data_structures/graph/graph.py +208 -0
  61. danielutils/data_structures/graph/multinode.py +101 -0
  62. danielutils/data_structures/graph/node.py +60 -0
  63. danielutils/data_structures/heap/__init__.py +3 -0
  64. danielutils/data_structures/heap/heap.py +119 -0
  65. danielutils/data_structures/heap/max_heap.py +18 -0
  66. danielutils/data_structures/heap/min_heap.py +18 -0
  67. danielutils/data_structures/queue/__init__.py +3 -0
  68. danielutils/data_structures/queue/atomic_queue.py +15 -0
  69. danielutils/data_structures/queue/priority_queue.py +110 -0
  70. danielutils/data_structures/queue/queue.py +92 -0
  71. danielutils/data_structures/stack.py +102 -0
  72. danielutils/data_structures/trees/__init__.py +2 -0
  73. danielutils/data_structures/trees/binary_syntax_tree.py +84 -0
  74. danielutils/data_structures/trees/binary_tree.py +63 -0
  75. danielutils/date.py +43 -0
  76. danielutils/date_time.py +23 -0
  77. danielutils/decorators/__init__.py +18 -0
  78. danielutils/decorators/atomic.py +45 -0
  79. danielutils/decorators/attach.py +61 -0
  80. danielutils/decorators/chain_decorators.py +39 -0
  81. danielutils/decorators/decorate_conditionally.py +32 -0
  82. danielutils/decorators/delay_call.py +47 -0
  83. danielutils/decorators/deprecate.py +46 -0
  84. danielutils/decorators/final.py +39 -0
  85. danielutils/decorators/limit_recursion.py +63 -0
  86. danielutils/decorators/memo.py +68 -0
  87. danielutils/decorators/normalize_decorator.py +55 -0
  88. danielutils/decorators/overload.py +204 -0
  89. danielutils/decorators/partially_implemented.py +32 -0
  90. danielutils/decorators/processify.py +74 -0
  91. danielutils/decorators/property.py +42 -0
  92. danielutils/decorators/singleton.py +59 -0
  93. danielutils/decorators/threadify.py +40 -0
  94. danielutils/decorators/timeout.py +82 -0
  95. danielutils/decorators/total_ordering.py +82 -0
  96. danielutils/decorators/validate.py +227 -0
  97. danielutils/exceptions.py +90 -0
  98. danielutils/functions/__init__.py +13 -0
  99. danielutils/functions/areoneof.py +47 -0
  100. danielutils/functions/check_foreach.py +39 -0
  101. danielutils/functions/factorial.py +24 -0
  102. danielutils/functions/flatten.py +33 -0
  103. danielutils/functions/foreach.py +20 -0
  104. danielutils/functions/isoftype.py +475 -0
  105. danielutils/functions/isoneof.py +71 -0
  106. danielutils/functions/multiloop.py +51 -0
  107. danielutils/functions/parallel_for.py +47 -0
  108. danielutils/functions/partition.py +45 -0
  109. danielutils/functions/powerset.py +31 -0
  110. danielutils/functions/subseteq.py +25 -0
  111. danielutils/functions/types_subseteq.py +51 -0
  112. danielutils/generators/__init__.py +3 -0
  113. danielutils/generators/conditional_generator.py +59 -0
  114. danielutils/generators/generator_from_stream.py +31 -0
  115. danielutils/generators/join_generators.py +109 -0
  116. danielutils/internet.py +92 -0
  117. danielutils/io_.py +451 -0
  118. danielutils/java/__init__.py +18 -0
  119. danielutils/java/interfaces/__init__.py +1 -0
  120. danielutils/java/interfaces/comparable.py +31 -0
  121. danielutils/java/java_interface.py +59 -0
  122. danielutils/logging_/__init__.py +2 -0
  123. danielutils/logging_/_impl/__init__.py +4 -0
  124. danielutils/logging_/_impl/builtin_impls/__init__.py +2 -0
  125. danielutils/logging_/_impl/builtin_impls/file_logger.py +35 -0
  126. danielutils/logging_/_impl/builtin_impls/print_logger.py +21 -0
  127. danielutils/logging_/_impl/log_level.py +13 -0
  128. danielutils/logging_/_impl/logger.py +109 -0
  129. danielutils/logging_/_impl/logger_strategy_impl_base.py +37 -0
  130. danielutils/logging_/utils.py +199 -0
  131. danielutils/lombok/__init__.py +1 -0
  132. danielutils/lombok/builder.py +68 -0
  133. danielutils/math_/__init__.py +2 -0
  134. danielutils/math_/constants.py +103 -0
  135. danielutils/math_/functions.py +34 -0
  136. danielutils/math_/math_print.py +52 -0
  137. danielutils/math_/math_symbols.py +125 -0
  138. danielutils/metaclasses/__init__.py +5 -0
  139. danielutils/metaclasses/atomic_class_meta.py +36 -0
  140. danielutils/metaclasses/implicit_data_deleter_meta.py +87 -0
  141. danielutils/metaclasses/instance_cache_meta.py +66 -0
  142. danielutils/metaclasses/interface.py +328 -0
  143. danielutils/metaclasses/overload_meta.py +48 -0
  144. danielutils/mock_/__init__.py +1 -0
  145. danielutils/mock_/mock_module.py +27 -0
  146. danielutils/path.py +55 -0
  147. danielutils/print_.py +123 -0
  148. danielutils/progress_bar/__init__.py +3 -0
  149. danielutils/progress_bar/ascii_progress_bar.py +161 -0
  150. danielutils/progress_bar/progress_bar.py +75 -0
  151. danielutils/progress_bar/progress_bar_pool.py +72 -0
  152. danielutils/protocols/__init__.py +3 -0
  153. danielutils/protocols/dictable.py +38 -0
  154. danielutils/protocols/evaluable.py +26 -0
  155. danielutils/protocols/serializable.py +51 -0
  156. danielutils/py.typed +0 -0
  157. danielutils/random_.py +47 -0
  158. danielutils/reflection/__init__.py +6 -0
  159. danielutils/reflection/declarations.py +288 -0
  160. danielutils/reflection/file/__init__.py +1 -0
  161. danielutils/reflection/file/file_reflection.py +85 -0
  162. danielutils/reflection/function/__init__.py +1 -0
  163. danielutils/reflection/function/function_reflections.py +152 -0
  164. danielutils/reflection/info_classes/__init__.py +6 -0
  165. danielutils/reflection/info_classes/argument_info.py +278 -0
  166. danielutils/reflection/info_classes/class_info.py +204 -0
  167. danielutils/reflection/info_classes/decorator_info.py +54 -0
  168. danielutils/reflection/info_classes/file_info.py +1180 -0
  169. danielutils/reflection/info_classes/folder_info.py +592 -0
  170. danielutils/reflection/info_classes/function_info.py +551 -0
  171. danielutils/reflection/info_classes/import_info.py +207 -0
  172. danielutils/reflection/interpreter/__init__.py +9 -0
  173. danielutils/reflection/interpreter/callstack.py +57 -0
  174. danielutils/reflection/interpreter/get_traceback.py +27 -0
  175. danielutils/reflection/interpreter/interpreter.py +41 -0
  176. danielutils/reflection/interpreter/is_debugging.py +13 -0
  177. danielutils/reflection/interpreter/os_.py +33 -0
  178. danielutils/reflection/interpreter/packages.py +33 -0
  179. danielutils/reflection/interpreter/python_version.py +33 -0
  180. danielutils/reflection/interpreter/signals.py +18 -0
  181. danielutils/reflection/interpreter/tracer.py +175 -0
  182. danielutils/reflection/module/__init__.py +3 -0
  183. danielutils/reflection/module/lazy_module.py +104 -0
  184. danielutils/reflection/module/module_reflections.py +34 -0
  185. danielutils/reflection/module/package_reflection.py +161 -0
  186. danielutils/retry_executor/__init__.py +3 -0
  187. danielutils/retry_executor/backoff_strategies/__init__.py +6 -0
  188. danielutils/retry_executor/backoff_strategies/constant_backoff.py +25 -0
  189. danielutils/retry_executor/backoff_strategies/exponential_backoff.py +26 -0
  190. danielutils/retry_executor/backoff_strategies/functional_backoff.py +29 -0
  191. danielutils/retry_executor/backoff_strategies/linear_backoff.py +23 -0
  192. danielutils/retry_executor/backoff_strategies/multiplicative_backoff.py +23 -0
  193. danielutils/retry_executor/backoff_strategies/no_backoff.py +17 -0
  194. danielutils/retry_executor/backoff_strategy.py +28 -0
  195. danielutils/retry_executor/retry_executor.py +55 -0
  196. danielutils/snippets/__init__.py +1 -0
  197. danielutils/snippets/try_get.py +28 -0
  198. danielutils/system/__init__.py +3 -0
  199. danielutils/system/independent.py +197 -0
  200. danielutils/system/layered_command.py +130 -0
  201. danielutils/system/windows/__init__.py +2 -0
  202. danielutils/system/windows/utils/__init__.py +1 -0
  203. danielutils/system/windows/utils/filetime.py +19 -0
  204. danielutils/system/windows/win32_ctime.py +183 -0
  205. danielutils/system/windows/windows.py +78 -0
  206. danielutils/testing/__init__.py +1 -0
  207. danielutils/testing/unittest_/__init__.py +2 -0
  208. danielutils/testing/unittest_/always_teardown_testcase.py +75 -0
  209. danielutils/testing/unittest_/auto_cwd_testcase.py +114 -0
  210. danielutils/text.py +169 -0
  211. danielutils/time.py +64 -0
  212. danielutils/tools/__init__.py +1 -0
  213. danielutils/tools/unittest_test_runner/__init__.py +9 -0
  214. danielutils/tools/unittest_test_runner/cli.py +70 -0
  215. danielutils/tools/unittest_test_runner/core/__init__.py +17 -0
  216. danielutils/tools/unittest_test_runner/core/discovery.py +322 -0
  217. danielutils/tools/unittest_test_runner/core/execution.py +244 -0
  218. danielutils/tools/unittest_test_runner/core/parser.py +163 -0
  219. danielutils/tools/unittest_test_runner/core/runner.py +561 -0
  220. danielutils/tools/unittest_test_runner/models.py +82 -0
  221. danielutils/university/__init__.py +7 -0
  222. danielutils/university/computability_and_complexity/__init__.py +2 -0
  223. danielutils/university/computability_and_complexity/discreate_finite_automaton.py +89 -0
  224. danielutils/university/computability_and_complexity/languages/__init__.py +0 -0
  225. danielutils/university/computability_and_complexity/languages/language.py +17 -0
  226. danielutils/university/computability_and_complexity/languages/sat.py +71 -0
  227. danielutils/university/computability_and_complexity/turing_machine.py +47 -0
  228. danielutils/university/databases/__init__.py +1 -0
  229. danielutils/university/databases/all.py +756 -0
  230. danielutils/university/image_proccesing/__init__.py +1 -0
  231. danielutils/university/image_proccesing/encoding/__init__.py +3 -0
  232. danielutils/university/image_proccesing/encoding/encoding.py +35 -0
  233. danielutils/university/image_proccesing/encoding/lossless/__init__.py +4 -0
  234. danielutils/university/image_proccesing/encoding/lossless/huffman.py +0 -0
  235. danielutils/university/image_proccesing/encoding/lossless/lossless_encoding.py +10 -0
  236. danielutils/university/image_proccesing/encoding/lossless/lzw.py +0 -0
  237. danielutils/university/image_proccesing/encoding/lossless/run_length.py +22 -0
  238. danielutils/university/image_proccesing/encoding/lossy/__init__.py +1 -0
  239. danielutils/university/image_proccesing/encoding/lossy/lossy_encoding.py +10 -0
  240. danielutils/university/image_proccesing/tansformations/__init__.py +0 -0
  241. danielutils/university/image_proccesing/tansformations/gaussian.py +0 -0
  242. danielutils/university/image_proccesing/tansformations/gradient.py +0 -0
  243. danielutils/university/image_proccesing/tansformations/hough.py +0 -0
  244. danielutils/university/image_proccesing/tansformations/laplacian.py +0 -0
  245. danielutils/university/image_proccesing/tansformations/transformation.py +11 -0
  246. danielutils/university/linear_algebra/__init__.py +1 -0
  247. danielutils/university/linear_algebra/matrix.py +404 -0
  248. danielutils/university/machine_learning/__init__.py +0 -0
  249. danielutils/university/machine_learning/activation_functions/__init__.py +2 -0
  250. danielutils/university/machine_learning/activation_functions/activation_function.py +11 -0
  251. danielutils/university/machine_learning/activation_functions/relu.py +11 -0
  252. danielutils/university/machine_learning/neuron.py +15 -0
  253. danielutils/university/oop/__init__.py +1 -0
  254. danielutils/university/oop/observer.py +31 -0
  255. danielutils/university/oop/strategy.py +9 -0
  256. danielutils/university/probability/__init__.py +7 -0
  257. danielutils/university/probability/conditional_variable/__init__.py +3 -0
  258. danielutils/university/probability/conditional_variable/conditional_variable.py +138 -0
  259. danielutils/university/probability/conditional_variable/continuous/__init__.py +0 -0
  260. danielutils/university/probability/conditional_variable/discrete/__init__.py +8 -0
  261. danielutils/university/probability/conditional_variable/discrete/bernoulli.py +38 -0
  262. danielutils/university/probability/conditional_variable/discrete/bernoulli_sum.py +31 -0
  263. danielutils/university/probability/conditional_variable/discrete/binomial.py +40 -0
  264. danielutils/university/probability/conditional_variable/discrete/conditional_from_discrete_probability_func.py +36 -0
  265. danielutils/university/probability/conditional_variable/discrete/discrete.py +42 -0
  266. danielutils/university/probability/conditional_variable/discrete/geometric.py +43 -0
  267. danielutils/university/probability/conditional_variable/discrete/poisson.py +32 -0
  268. danielutils/university/probability/conditional_variable/discrete/uniform.py +33 -0
  269. danielutils/university/probability/distributions.py +35 -0
  270. danielutils/university/probability/expressions/__init__.py +2 -0
  271. danielutils/university/probability/expressions/accumulation_expression.py +291 -0
  272. danielutils/university/probability/expressions/probability_expression.py +110 -0
  273. danielutils/university/probability/funcs/__init__.py +4 -0
  274. danielutils/university/probability/funcs/covariance.py +12 -0
  275. danielutils/university/probability/funcs/expected_value.py +41 -0
  276. danielutils/university/probability/funcs/probability_function.py +14 -0
  277. danielutils/university/probability/funcs/variance.py +17 -0
  278. danielutils/university/probability/operator.py +79 -0
  279. danielutils/university/probability/protocols.py +32 -0
  280. danielutils/university/probability/supp.py +101 -0
  281. danielutils/university/probability/transformation.py +44 -0
  282. danielutils/versioned_imports.py +31 -0
  283. danielutils-1.1.28.dist-info/METADATA +390 -0
  284. danielutils-1.1.28.dist-info/RECORD +287 -0
  285. danielutils-1.1.28.dist-info/WHEEL +5 -0
  286. danielutils-1.1.28.dist-info/licenses/LICENSE +21 -0
  287. danielutils-1.1.28.dist-info/top_level.txt +1 -0
@@ -0,0 +1,119 @@
1
+ import logging
2
+ from typing import Union, TypeVar, Generic
3
+ from ..comparer import Comparer
4
+ from ...logging_.utils import get_logger
5
+ logger = get_logger(__name__)
6
+
7
+ T = TypeVar("T")
8
+
9
+
10
+ class Heap(Generic[T]):
11
+ """a Heap class which will do the sorting according to the supplied comparer object
12
+ """
13
+
14
+ def __init__(self, comparer: Comparer) -> None:
15
+ logger.debug("Initializing Heap with comparer: %s", type(comparer).__name__)
16
+ self.arr: list = []
17
+ self.comparer = comparer
18
+
19
+ def push(self, val: T) -> None:
20
+ """will add a new object to the heap
21
+
22
+ Args:
23
+ val (Any): the object to add to the heap
24
+ """
25
+ logger.debug("Pushing value to heap: %s", val)
26
+ res: Union[int, float] = -1
27
+ curr_index = len(self)
28
+ self.arr.append(val)
29
+ logger.debug("Added value at index %s, heap size: %s", curr_index, len(self.arr))
30
+ parent_index = curr_index // 2 - (1 - curr_index % 2)
31
+ while res < 0 and parent_index >= 0:
32
+ res = self.comparer.compare(
33
+ self[parent_index], self[curr_index])
34
+ if res < 0:
35
+ logger.debug("Swapping values at indices %s and %s", parent_index, curr_index)
36
+ self.arr[parent_index], self.arr[curr_index] = self[curr_index], self[parent_index]
37
+ curr_index = parent_index
38
+ parent_index = curr_index // 2 - (1 - curr_index % 2)
39
+
40
+ def __len__(self):
41
+ return len(self.arr)
42
+
43
+ def __getitem__(self, index: int) -> T:
44
+ return self.arr[index]
45
+
46
+ def is_empty(self) -> bool:
47
+ """return whether the heap is empty
48
+
49
+ Returns:
50
+ bool: result
51
+ """
52
+ return len(self) == 0
53
+
54
+ def pop(self) -> T:
55
+ """return the value at the top of the heap while removing it
56
+
57
+ Returns:
58
+ Any: the result
59
+ """
60
+ if self.is_empty():
61
+ logger.warning("Attempted to pop from empty heap")
62
+ raise IndexError("pop from empty heap")
63
+
64
+ logger.debug("Popping from heap, current size: %s", len(self))
65
+ res = self[0]
66
+ self.arr[0], self.arr[-1] = self[-1], self[0]
67
+ self.arr.pop()
68
+ logger.debug("Swapped root with last element, new size: %s", len(self))
69
+ flag = True
70
+ curr_index = 0
71
+ while flag:
72
+ child1_index = curr_index * 2 + 1
73
+ child2_index = curr_index * 2 + 2
74
+ if len(self) > child2_index:
75
+ if self.comparer.compare(self[child1_index], self[child2_index]) < 0:
76
+ logger.debug("Swapping with right child at index %s", child2_index)
77
+ self.arr[curr_index], self.arr[child2_index] = self[child2_index], self[curr_index]
78
+ curr_index = child2_index
79
+ elif self.comparer.compare(self[child1_index], self[child2_index]) > 0:
80
+ logger.debug("Swapping with left child at index %s", child1_index)
81
+ self.arr[curr_index], self.arr[child1_index] = self[child1_index], self[curr_index]
82
+ curr_index = child1_index
83
+ else:
84
+ logger.debug("Children are equal, heap property satisfied")
85
+ flag = False
86
+ else:
87
+ if len(self) > child1_index:
88
+ if self.comparer.compare(self[child1_index], self[curr_index]) > 0:
89
+ logger.debug("Swapping with only child at index %s", child1_index)
90
+ self.arr[curr_index], self.arr[child1_index] = self[child1_index], self[curr_index]
91
+ curr_index = child1_index
92
+ else:
93
+ logger.debug("Heap property satisfied with only child")
94
+ flag = False
95
+ else:
96
+ logger.debug("No children, heap property satisfied")
97
+ flag = False
98
+ logger.debug("Heap pop completed, returning: %s", res)
99
+ return res
100
+
101
+ def __str__(self):
102
+ return str(self.arr)
103
+
104
+ def peek(self) -> T:
105
+ """return the value at the top of the Heap without removing it
106
+
107
+ Returns:
108
+ Any: the result
109
+ """
110
+ if self.is_empty():
111
+ logger.warning("Attempted to peek at empty heap")
112
+ raise IndexError("peek at empty heap")
113
+ logger.debug("Peeking at heap top: %s", self[0])
114
+ return self[0]
115
+
116
+
117
+ __all__ = [
118
+ "Heap",
119
+ ]
@@ -0,0 +1,18 @@
1
+ from typing import TypeVar
2
+ from ..comparer import CompareGreater
3
+ from .heap import Heap
4
+
5
+ T = TypeVar("T")
6
+
7
+
8
+ class MaxHeap(Heap[T]):
9
+ """classic MaxHeap implementation
10
+ """
11
+
12
+ def __init__(self):
13
+ super().__init__(CompareGreater)
14
+
15
+
16
+ __all__ = [
17
+ "MaxHeap"
18
+ ]
@@ -0,0 +1,18 @@
1
+ from typing import TypeVar
2
+ from ..comparer import CompareSmaller
3
+ from .heap import Heap
4
+
5
+ T = TypeVar("T")
6
+
7
+
8
+ class MinHeap(Heap[T]):
9
+ """classic MinHeap implementation
10
+ """
11
+
12
+ def __init__(self) -> None:
13
+ super().__init__(CompareSmaller)
14
+
15
+
16
+ __all__ = [
17
+ "MinHeap"
18
+ ]
@@ -0,0 +1,3 @@
1
+ from .queue import *
2
+ from .atomic_queue import *
3
+ from .priority_queue import *
@@ -0,0 +1,15 @@
1
+ from typing import TypeVar
2
+ from ...metaclasses import AtomicClassMeta
3
+ from .queue import Queue
4
+
5
+ T = TypeVar("T")
6
+
7
+
8
+ class AtomicQueue(Queue[T], metaclass=AtomicClassMeta):
9
+ """Same as Queue but atomic
10
+ """
11
+
12
+
13
+ __all__ = [
14
+ "AtomicQueue"
15
+ ]
@@ -0,0 +1,110 @@
1
+ from typing import Callable, Any, Union, TypeVar
2
+ from ..heap import Heap
3
+ from ..comparer import Comparer, CompareGreater
4
+ from ..functions import default_weight_function
5
+ from .queue import Queue
6
+
7
+ T = TypeVar("T")
8
+
9
+
10
+ class PriorityQueue(Queue[T]):
11
+ """
12
+ A priority queue implementation based on a binary heap.
13
+
14
+ Args:
15
+ weight_func (Callable[[T], Union[int, float]], optional): A function to calculate the weight of items added
16
+ to the queue. Defaults to default_weight_function.
17
+ comparer (Comparer, optional): The comparer to use when comparing weights of items in the queue.
18
+ Defaults to Comparer.GREATER.
19
+
20
+ Raises:
21
+ ValueError: Raised if an item with the same weight value is added more than once.
22
+
23
+ Methods:
24
+ pop() -> T:
25
+ Removes and returns the item with the highest priority (i.e., the lowest weight value) from the queue.
26
+ push(value: T):
27
+ Adds a new item to the queue with the specified value and weight.
28
+ peek() -> T:
29
+ Returns the item with the highest priority
30
+ (i.e., the lowest weight value) from the queue without removing it.
31
+ __str__() -> str:
32
+ Returns a string representation of the queue.
33
+
34
+ Example:
35
+ >>> pq = PriorityQueue()
36
+ >>> pq.push(5)
37
+ >>> pq.push(10)
38
+ >>> pq.push(3)
39
+ >>> pq.pop()
40
+ 10
41
+ """
42
+
43
+ def __init__(self, weight_func: Callable[[Any], Union[int, float]] = default_weight_function):
44
+ super().__init__()
45
+ comparer = CompareGreater if weight_func is default_weight_function else Comparer( # type:ignore
46
+ lambda a, b: weight_func(a) - weight_func(b)) # type:ignore
47
+ self.data: Heap = Heap(comparer) # type:ignore
48
+ self.weight_func = weight_func
49
+ self.dct: dict = {}
50
+
51
+ def pop(self) -> T:
52
+ """
53
+ Removes and returns the item with the highest priority (i.e., the lowest weight value) from the queue.
54
+
55
+ Returns:
56
+ T: The item with the highest priority in the queue.
57
+
58
+ Raises:
59
+ KeyError: Raised if the queue is empty.
60
+ """
61
+ item_weight = self.data.pop()
62
+ res = self.dct[item_weight]
63
+ del self.dct[item_weight]
64
+ return res
65
+
66
+ def push(self, value: T) -> None:
67
+ """
68
+ Adds a new item to the queue with the specified value and weight.
69
+
70
+ Args:
71
+ value (T): The value of the item to add to the queue.
72
+
73
+ Returns:
74
+ None
75
+
76
+ Raises:
77
+ ValueError: Raised if an item with the same weight value is added more than once.
78
+ """
79
+ item_weight = self.weight_func(value)
80
+ if item_weight in self.dct:
81
+ raise ValueError(
82
+ "Can't have same weight value more than once in current implementation")
83
+ self.data.push(item_weight)
84
+ self.dct[item_weight] = value
85
+
86
+ def peek(self) -> T:
87
+ """
88
+ Returns the item with the highest priority (i.e., the lowest weight value) from the queue without removing it.
89
+
90
+ Returns:
91
+ T: The item with the highest priority in the queue.
92
+
93
+ Raises:
94
+ KeyError: Raised if the queue is empty.
95
+ """
96
+ return self.dct[self.data.peek()]
97
+
98
+ def __str__(self) -> str:
99
+ """
100
+ Returns a string representation of the queue.
101
+
102
+ Returns:
103
+ str: A string representation of the queue.
104
+ """
105
+ return str([str(self.dct[w]) for w in [self.data[i] for i in range(len(self.data))]])
106
+
107
+
108
+ __all__ = [
109
+ "PriorityQueue"
110
+ ]
@@ -0,0 +1,92 @@
1
+ import logging
2
+ from typing import Generic, TypeVar, Iterator, List as List
3
+ from ...reflection import get_python_version
4
+ from ...logging_.utils import get_logger
5
+
6
+ if get_python_version() >= (3, 9):
7
+ from builtins import list as List
8
+ T = TypeVar("T")
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ class Queue(Generic[T]):
14
+ """classic Queue data structure"""
15
+
16
+ def __init__(self) -> None:
17
+ self.data: list = []
18
+ logger.debug("Queue initialized")
19
+
20
+ def pop(self) -> T:
21
+ """return the oldest element while removing it from the queue
22
+
23
+ Returns:
24
+ Any: result
25
+ """
26
+ if self.is_empty():
27
+ logger.warning("Attempted to pop from empty queue")
28
+ raise IndexError("pop from empty queue")
29
+
30
+ result = self.data.pop()
31
+ logger.debug("Popped element from queue, remaining size: %s", len(self.data))
32
+ return result
33
+
34
+ def push(self, value: T) -> None:
35
+ """adds a new element to the queue
36
+
37
+ Args:
38
+ value (Any): the value to add
39
+ """
40
+ self.data.insert(0, value)
41
+ logger.debug("Pushed element to queue, new size: %s", len(self.data))
42
+
43
+ def peek(self) -> T:
44
+ """returns the oldest element in the queue
45
+ without removing it from the queue
46
+
47
+ Returns:
48
+ Any: result
49
+ """
50
+ if self.is_empty():
51
+ logger.warning("Attempted to peek at empty queue")
52
+ raise IndexError("peek at empty queue")
53
+
54
+ result = self.data[-1]
55
+ logger.debug("Peeked at element in queue, size: %s", len(self.data))
56
+ return result
57
+
58
+ def __len__(self) -> int:
59
+ return len(self.data)
60
+
61
+ def is_empty(self) -> bool:
62
+ """returns whether the queue is empty
63
+
64
+ Returns:
65
+ bool: result
66
+ """
67
+ return len(self) == 0
68
+
69
+ def __str__(self) -> str:
70
+ return repr(self)
71
+
72
+ def __repr__(self) -> str:
73
+ return str(self.data)
74
+
75
+ def __iter__(self) -> Iterator[T]:
76
+ return iter(self.data)
77
+
78
+ def push_many(self, arr: List[T]):
79
+ """will push many objects to the Queue
80
+
81
+ Args:
82
+ arr (list): the objects to push
83
+ """
84
+ logger.debug("Pushing %s elements to queue", len(arr))
85
+ for v in arr:
86
+ self.push(v)
87
+ logger.info("Successfully pushed %s elements to queue", len(arr))
88
+
89
+
90
+ __all__ = [
91
+ "Queue",
92
+ ]
@@ -0,0 +1,102 @@
1
+ import logging
2
+ from typing import Optional, Generator, TypeVar, Generic
3
+ from .graph import Node
4
+ from ..logging_.utils import get_logger
5
+ logger = get_logger(__name__)
6
+
7
+ T = TypeVar('T')
8
+
9
+
10
+ class Stack(Generic[T]):
11
+ """A classic Stack class
12
+ """
13
+
14
+ def __init__(self) -> None:
15
+ self.head: Optional[Node[T]] = None
16
+ self.size = 0
17
+ logger.debug("Stack initialized")
18
+
19
+ def push(self, value: T):
20
+ """push an item to the stack
21
+
22
+ Args:
23
+ value (Any): item to push
24
+ """
25
+ logger.debug("Pushing value to stack: %s", value)
26
+ if self.head is None:
27
+ self.head = Node(value)
28
+ logger.debug("Created first node in stack")
29
+ else:
30
+ new_head = Node(value, self.head)
31
+ self.head = new_head
32
+ logger.debug("Added new head node to stack")
33
+ self.size += 1
34
+ logger.debug("Stack size is now: %s", self.size)
35
+
36
+ def pop(self) -> T:
37
+ """pop an item from the stack
38
+
39
+ Returns:
40
+ Any: poped item
41
+ """
42
+ if not self.is_empty():
43
+ res = self.head.data # type:ignore
44
+ self.size -= 1
45
+ self.head = self.head.next # type:ignore
46
+ logger.debug("Popped value from stack: %s, remaining size: %s", res, self.size)
47
+ return res
48
+ logger.warning("Attempted to pop from empty stack")
49
+ raise RuntimeError("Can't pop from an empty stack")
50
+
51
+ def peek(self) -> Optional[T]:
52
+ """
53
+ Returns the top element of the stack
54
+ Returns:
55
+ Optional[T]
56
+ """
57
+ if self.is_empty():
58
+ logger.debug("Peek called on empty stack")
59
+ return None
60
+ result = self.head.data # type:ignore
61
+ logger.debug("Peeked at stack top: %s", result)
62
+ return result
63
+
64
+ def __len__(self) -> int:
65
+ return self.size
66
+
67
+ def __iter__(self) -> Generator[T, None, None]:
68
+ while self:
69
+ yield self.pop()
70
+
71
+ def is_empty(self) -> bool:
72
+ """return whether the stack is empty
73
+ """
74
+ return len(self) == 0
75
+
76
+ def __bool__(self) -> bool:
77
+ return not self.is_empty()
78
+
79
+ def __contains__(self, value: T) -> bool:
80
+ curr = self.head
81
+ while curr is not None:
82
+ if curr.data == value:
83
+ return True
84
+ curr = curr.next
85
+ return False
86
+
87
+ def __str__(self) -> str:
88
+ values = []
89
+ curr = self.head
90
+ while curr:
91
+ values.append(str(curr.data))
92
+ curr = curr.next
93
+ inside = ", ".join(values)
94
+ return f"Stack({inside})"
95
+
96
+ def __repr__(self) -> str:
97
+ return str(self)
98
+
99
+
100
+ __all__ = [
101
+ "Stack"
102
+ ]
@@ -0,0 +1,2 @@
1
+ from .binary_tree import *
2
+ from .binary_syntax_tree import *
@@ -0,0 +1,84 @@
1
+ from typing import Union, Any, Callable,Dict as Dict
2
+ from .binary_tree import BinaryTree
3
+ from ..graph import BinaryNode
4
+ from ...reflection import get_python_version
5
+ if get_python_version()>=(3,9):
6
+ from builtins import dict as Dict
7
+
8
+ class BinarySyntaxTree(BinaryTree):
9
+ """
10
+ Binary tree data structure to represent syntax of expressions
11
+ """
12
+
13
+ @staticmethod
14
+ def _evaluate_node(v: BinaryNode, operator_func_dict: Dict[Any, Callable[[Any, Any], Any]]):
15
+ if not isinstance(v, BinaryNode) or v.left is None and v.right is None:
16
+ return v
17
+
18
+ lres = BinarySyntaxTree._evaluate_node(v.left, operator_func_dict)
19
+ rres = BinarySyntaxTree._evaluate_node(v.right, operator_func_dict)
20
+
21
+ return operator_func_dict[v.data](lres, rres)
22
+
23
+ @property
24
+ def bottom_right(self) -> BinaryNode:
25
+ cur = self.root
26
+ while hasattr(cur, "right"):
27
+ if isinstance(cur, BinaryNode):
28
+ if cur.right is None:
29
+ return cur
30
+ cur = cur.right
31
+ else:
32
+ break
33
+ return cur
34
+
35
+ @bottom_right.setter
36
+ def bottom_right(self, v: BinaryNode) -> None:
37
+ cur = self.root
38
+ while (
39
+ hasattr(cur, "right") and
40
+ isinstance(cur.right, BinaryNode) and
41
+ hasattr(cur.right, "right") and
42
+ isinstance(cur.right.right, BinaryNode)
43
+ ):
44
+ cur = cur.right
45
+ cur.right = v
46
+
47
+ @property
48
+ def bottom_left(self) -> BinaryNode:
49
+ cur = self.root
50
+ while hasattr(cur, "left"):
51
+ if isinstance(cur, BinaryNode):
52
+ if cur.left is None:
53
+ return cur
54
+ cur = cur.left
55
+ else:
56
+ break
57
+ return cur
58
+
59
+ @bottom_left.setter
60
+ def bottom_left(self, v: BinaryNode) -> None:
61
+ cur = self.root
62
+ while (
63
+ hasattr(cur, "left") and
64
+ isinstance(cur.left, BinaryNode) and
65
+ hasattr(cur.left, "left") and
66
+ isinstance(cur.left.left, BinaryNode)
67
+ ):
68
+ cur = cur.left
69
+ cur.left = v
70
+
71
+ def reverse(self) -> "BinarySyntaxTree":
72
+ return BinarySyntaxTree(self.root.reverse())
73
+
74
+ def __reversed__(self) -> "BinarySyntaxTree":
75
+ return self.reverse()
76
+
77
+ def evaluate(self, operator_func_dict: Dict[Any, Callable[[Any, Any], Any]]) -> Any:
78
+ return BinarySyntaxTree._evaluate_node(self.root, operator_func_dict)
79
+
80
+
81
+
82
+ __all__ = [
83
+ "BinarySyntaxTree"
84
+ ]
@@ -0,0 +1,63 @@
1
+ from enum import Enum
2
+
3
+ from ..graph import BinaryNode
4
+ from typing import TypeVar, Generic, Iterator
5
+
6
+ T = TypeVar("T")
7
+
8
+
9
+ class BinaryTree(Generic[T]):
10
+ Node: type = BinaryNode
11
+
12
+ class TraversalMode(Enum):
13
+ First = 1
14
+ Middle = 2
15
+ Last = 3
16
+
17
+ def __init__(self, root: BinaryNode[T]):
18
+ self._root = root
19
+
20
+ def __reversed__(self) -> 'BinaryTree[T]':
21
+ return self.reverse()
22
+
23
+ def __iter__(self) -> Iterator[BinaryNode[T]]:
24
+ yield from self.traverse(BinaryTree.TraversalMode.First)
25
+
26
+ def __eq__(self, other):
27
+ if not isinstance(other, BinaryTree):
28
+ return False
29
+
30
+ for a, b in zip(self, other):
31
+ if not (a == b):
32
+ return False
33
+ return True
34
+
35
+ @property
36
+ def root(self) -> BinaryNode[T]:
37
+ return self._root
38
+
39
+ def traverse(self, mode: 'TraversalMode') -> Iterator[BinaryNode[T]]:
40
+ def helper(node: BinaryNode[T]):
41
+ if mode == self.TraversalMode.First:
42
+ yield node
43
+ if node.left is not None:
44
+ yield from helper(node.left)
45
+ if mode == self.TraversalMode.Middle:
46
+ yield node
47
+ if node.right is not None:
48
+ yield from helper(node.right)
49
+ if mode == self.TraversalMode.Last:
50
+ yield node
51
+
52
+ yield from helper(self._root)
53
+
54
+ def reverse(self) -> "BinaryTree[T]":
55
+ return BinaryTree(self.root.reverse())
56
+
57
+ def depth(self) -> int:
58
+ return self.root.depth()
59
+
60
+
61
+ __all__ = [
62
+ 'BinaryTree'
63
+ ]
danielutils/date.py ADDED
@@ -0,0 +1,43 @@
1
+ import json
2
+ import logging
3
+ from .decorators import validate
4
+ from .logging_.utils import get_logger
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ @validate # type:ignore # type:ignore
9
+ def dict_to_json(dct: dict) -> str:
10
+ """converts a python dict to a json object
11
+
12
+ Args:
13
+ d (dict): the dict to convert
14
+
15
+ Returns:
16
+ str: the json as string
17
+ """
18
+ logger.debug("Converting dict with %d keys to JSON", len(dct))
19
+ result = json.dumps(dct, indent=4)
20
+ logger.debug("JSON conversion completed, result length: %d", len(result))
21
+ return result
22
+
23
+
24
+ @validate # type:ignore
25
+ def json_to_dict(json_str: str) -> dict:
26
+ """converts a json object from a string to a python dict
27
+
28
+ Args:
29
+ j (str): the json str to convert
30
+
31
+ Returns:
32
+ dict: a python dict from the json
33
+ """
34
+ logger.debug("Converting JSON string (length: %d) to dict", len(json_str))
35
+ result = json.loads(json_str)
36
+ logger.debug("JSON parsing completed, dict has %d keys", len(result))
37
+ return result
38
+
39
+
40
+ __all__ = [
41
+ "dict_to_json",
42
+ "json_to_dict"
43
+ ]