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,475 @@
1
+ import logging
2
+ from typing import get_args, get_origin, get_type_hints, Any, Union, TypeVar, \
3
+ ForwardRef, Literal, Optional, Protocol, Generic, Type, List, Tuple, Set, Dict
4
+ import inspect
5
+ from collections.abc import Callable, Generator, Iterable
6
+ from ..reflection import get_python_version
7
+ from ..logging_.utils import get_logger
8
+ logger = get_logger(__name__)
9
+
10
+
11
+ class _tmp(Protocol): ...
12
+
13
+
14
+ _ProtocolMeta = type(_tmp)
15
+ del _tmp
16
+
17
+ T = TypeVar('T')
18
+
19
+
20
+ class _tmp2(Generic[T]): ...
21
+
22
+
23
+ _GenericAlias = type(_tmp2[int])
24
+ del _tmp2, T
25
+ cmethod = type(getattr(1, "__lt__"))
26
+ try:
27
+ implicit_union_type = type(int | str)
28
+ except:
29
+ implicit_union_type = Union
30
+
31
+ ellipsis_ = ...
32
+
33
+ PARAMSPEC_STRICT: bool = True
34
+ try:
35
+ from typing import ParamSpec
36
+ except ImportError:
37
+ PARAMSPEC_STRICT = False
38
+
39
+
40
+ def __isoftype_inquire(obj: Any) -> Tuple[Optional[type], Optional[tuple], Optional[dict]]:
41
+ """
42
+ Inquires the origin, arguments, and type hints of an object.
43
+
44
+ Args:
45
+ obj: The object to inquire.
46
+
47
+ Returns:
48
+ A tuple containing the origin, arguments, and type hints of the object.
49
+ """
50
+ origin = None
51
+ args = None
52
+ type_hints = None
53
+ try:
54
+ origin = get_origin(obj)
55
+ except:
56
+ pass
57
+ try:
58
+ args = get_args(obj)
59
+ except:
60
+ pass
61
+ try:
62
+ type_hints = get_type_hints(obj)
63
+ except:
64
+ pass
65
+ return origin, args, type_hints
66
+
67
+
68
+ def __handle_list_set_iterable(params: tuple) -> bool:
69
+ """
70
+ Handles the 'list', 'set', and 'Iterable' origin types.
71
+
72
+ Args:
73
+ params: A tuple containing the required parameters.
74
+
75
+ Returns:
76
+ True if the object matches the 'list', 'set', or 'Iterable' origin type, False otherwise.
77
+ """
78
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
79
+ value_t = t_args[0]
80
+ for value in V:
81
+ if not isoftype(value, value_t, strict=strict):
82
+ return False
83
+ return True
84
+
85
+
86
+ def __handle_tuple(params: tuple) -> bool:
87
+ """
88
+ Handles the 'tuple' origin type.
89
+
90
+ Args:
91
+ params: A tuple containing the required parameters.
92
+
93
+ Returns:
94
+ True if the object matches the 'tuple' origin type, False otherwise.
95
+ """
96
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
97
+ if len(V) != len(t_args):
98
+ return False
99
+ for sub_obj, sub_t in zip(V, t_args):
100
+ if not isoftype(sub_obj, sub_t, strict=strict):
101
+ return False
102
+ return True
103
+
104
+
105
+ def __handle_dict(params: tuple) -> bool:
106
+ """
107
+ Handles the 'dict' origin type.
108
+
109
+ Args:
110
+ params: A tuple containing the required parameters.
111
+
112
+ Returns:
113
+ True if the object matches the 'dict' origin type, False otherwise.
114
+ """
115
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
116
+ key_t, value_t = t_args[0], t_args[1]
117
+ for k, v in V.items():
118
+ if not isoftype(k, key_t, strict=strict):
119
+ return False
120
+ if not isoftype(v, value_t, strict=strict):
121
+ return False
122
+ return True
123
+
124
+
125
+ def __handle_union(params: tuple) -> bool:
126
+ """
127
+ Handles the 'Union' origin type.
128
+
129
+ Args:
130
+ params: A tuple containing the required parameters.
131
+
132
+ Returns:
133
+ True if the object matches the 'Union' origin type, False otherwise.
134
+ """
135
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
136
+ for sub_t in t_args:
137
+ if isoftype(V, sub_t, strict=strict):
138
+ return True
139
+ return False
140
+
141
+
142
+ def __handle_generator(params: tuple) -> bool:
143
+ """
144
+ Handles the 'Generator' origin type.
145
+
146
+ Args:
147
+ params: A tuple containing the required parameters.
148
+
149
+ Returns:
150
+ True if the object matches the 'Generator' origin type, False otherwise.
151
+ """
152
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
153
+ yield_t, send_t, return_t = t_args
154
+ return isinstance(V, Generator)
155
+
156
+
157
+ def __handle_literal(params: tuple) -> bool:
158
+ """
159
+ Handles the 'Literal' origin type.
160
+
161
+ Args:
162
+ params: A tuple containing the required parameters.
163
+
164
+ Returns:
165
+ True if the object matches the 'Literal' origin type, False otherwise.
166
+ """
167
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
168
+ for literal in t_args:
169
+ if V is literal:
170
+ return True
171
+ return False
172
+
173
+
174
+ def __handle_callable(params: tuple) -> bool:
175
+ """
176
+ Handles the 'Callable' origin type.
177
+
178
+ Args:
179
+ params: A tuple containing the required parameters.
180
+
181
+ Returns:
182
+ True if the object matches the 'Callable' origin type, False otherwise.
183
+ """
184
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
185
+
186
+ if not callable(V):
187
+ return False
188
+
189
+ if V.__name__ == "<lambda>":
190
+ if strict:
191
+ print("Using lambda function with isoftype is ambiguous.")
192
+ return not strict
193
+
194
+ if t_args is None:
195
+ return True
196
+ if len(t_args) == 0:
197
+ return True
198
+ try:
199
+ from typing import Concatenate, ParamSpec
200
+ concatenate_t = type(Concatenate[str, ParamSpec("P_")])
201
+ if get_python_version() < (3, 10):
202
+ if isoftype(t_args[0][0], [ParamSpec, concatenate_t]):
203
+ return True
204
+ else:
205
+ if isoftype(t_args[0], [ParamSpec, concatenate_t]):
206
+ return True
207
+ except ImportError:
208
+ pass
209
+
210
+ obj_return_type = obj_hints.get('return')
211
+ obj_param_types = list(obj_hints.values())[:-1] if obj_hints else None
212
+ t_return_type = t_args[1]
213
+
214
+ if not PARAMSPEC_STRICT:
215
+ if t_args[0] == Ellipsis:
216
+ return True
217
+ if t_args[0] == [Any]:
218
+ return True
219
+
220
+ if isinstance(t_args[0], Iterable):
221
+ t_param_types = list(t_args[0])
222
+ A = obj_param_types + [obj_return_type] if obj_param_types else None
223
+ B = t_param_types + [t_return_type]
224
+
225
+ if A is None or B is None or len(A) != len(B):
226
+ return False
227
+ for a, b in zip(A, B):
228
+ if hasattr(b, "__args__"): # Union
229
+ if a not in b.__args__:
230
+ return False
231
+ elif a is not b: # otherwise
232
+ return False
233
+ return True
234
+
235
+ return False
236
+
237
+
238
+ def __handle_type_origin(params: tuple) -> bool:
239
+ """
240
+ Handles the type origin.
241
+
242
+ Args:
243
+ params: A tuple containing the required parameters.
244
+
245
+ Returns:
246
+ True if the object matches the type origin, False otherwise.
247
+ """
248
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
249
+ if T is Any:
250
+ return True
251
+
252
+ if type(T) in (list, tuple):
253
+ for sub_t in T:
254
+ if isoftype(V, sub_t, strict=strict):
255
+ return True
256
+ return False
257
+
258
+ if obj_origin is not None and obj_origin is Union:
259
+ return T is type(Union)
260
+
261
+ if isinstance(T, TypeVar):
262
+ t_args = T.__constraints__
263
+ if t_args:
264
+ for sub_t in t_args:
265
+ if isoftype(V, sub_t):
266
+ return True
267
+ return False
268
+
269
+ return True
270
+
271
+ if isinstance(T, ForwardRef):
272
+ name_of_type = T.__forward_arg__
273
+ return type(V).__name__ == name_of_type
274
+
275
+ return isinstance(V, T)
276
+
277
+
278
+ def _is_java_interface_type(cls: Any) -> bool:
279
+ try:
280
+ from ..java import JavaInterface
281
+ except ImportError:
282
+ return False
283
+ return JavaInterface in getattr(cls, "__mro__", [])
284
+
285
+
286
+ def __handle_protocol(params: tuple, /, allow_classes: bool = False) -> bool:
287
+ # TODO is_protocol, _is_runtime_protocol
288
+ from ..reflection import FunctionDeclaration, ClassDeclaration
289
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
290
+
291
+ if T is Protocol:
292
+ mro = getattr(V, "__mro__", [])
293
+ if Protocol in mro:
294
+ return True
295
+ try:
296
+ from ..java import JavaInterface
297
+ except ImportError:
298
+ return False
299
+ return JavaInterface in mro or any(getattr(base, "__is_interface__", False) for base in mro)
300
+ if T in getattr(V, "__mro__", []):
301
+ return False
302
+ if type(V) == type and type(T) == _GenericAlias and not allow_classes:
303
+ return False
304
+ if type(V) == type and len(t_args) == 0:
305
+ return isinstance(V, T)
306
+ if type(V) != type:
307
+ V = type(V)
308
+
309
+ interface_cls = T if inspect.isclass(T) else t_origin
310
+ if interface_cls is Protocol:
311
+ return False
312
+
313
+ cls = ClassDeclaration.from_cls(interface_cls)
314
+ declared_funcs: List[FunctionDeclaration] = list(FunctionDeclaration.get_declared_functions(V))
315
+ required_funcs: List[FunctionDeclaration] = list(FunctionDeclaration.get_declared_functions(interface_cls))
316
+
317
+ for i, req_func in enumerate(required_funcs):
318
+ if req_func.has_generics:
319
+ if req_func.return_type in req_func.generics:
320
+ new_req_func = req_func.duplicate(
321
+ return_type=t_args[req_func.generics.index(req_func.return_type)].__name__)
322
+ required_funcs[i] = new_req_func
323
+ for aindex, arg in enumerate(required_funcs[i].arguments):
324
+ for generic in req_func.generics:
325
+ if arg.type is not None and generic in arg.type:
326
+ if generic not in cls.generics:
327
+ return False
328
+ correct_type = t_args[cls.generics.index(generic)]
329
+ if getattr(correct_type, "__origin__", None) is Union:
330
+ new_name = str(correct_type).replace("typing.Union", "Union")
331
+ elif hasattr(correct_type, "__name__"):
332
+ new_name = correct_type.__name__
333
+ else:
334
+ new_name = str(correct_type).replace("typing.", "")
335
+ changed_argument = required_funcs[i].arguments[aindex].duplicate(type=new_name)
336
+ new_arguments = list(required_funcs[i].arguments)[::]
337
+ new_arguments[aindex] = changed_argument
338
+ required_funcs[i] = required_funcs[i].duplicate(arguments=tuple(new_arguments))
339
+
340
+ for req in required_funcs:
341
+ for dec in declared_funcs:
342
+ if not len(req.arguments) == len(dec.arguments):
343
+ return False
344
+
345
+ if not req.return_type == dec.return_type: return False
346
+
347
+ for rarg in req.arguments:
348
+ for darg in dec.arguments:
349
+ a = rarg.type
350
+ if a is not None and ("[" in a or "]" in a):
351
+ a = set([s.strip() for s in a[a.index("[") + 1:a.rindex("]")].split(",")])
352
+ else:
353
+ a = set([a])
354
+ b = darg.type
355
+ if b is not None and ("[" in b or "]" in b):
356
+ b = set([s.strip() for s in b[b.index("[") + 1:b.rindex("]")].split(",")])
357
+ else:
358
+ b = set([b])
359
+ if (len(list(b - a))) == 0: break
360
+ else:
361
+ return False
362
+
363
+ return True
364
+
365
+
366
+ def __handle_type(params: tuple) -> bool:
367
+ V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints = params
368
+ if type(V) != type:
369
+ return False
370
+ if t_args[0] in V.__mro__:
371
+ return True
372
+ t_origin, t_args, t_hints = __isoftype_inquire(t_args[0])
373
+ if type(t_origin) is _ProtocolMeta:
374
+ return __handle_protocol((V, T, strict, obj_origin, obj_args, obj_hints, t_origin, t_args, t_hints),
375
+ allow_classes=True)
376
+ return False
377
+
378
+
379
+ def __handle_unpack(params: tuple) -> bool:
380
+ # TODO see test_tlist.py -> test_wrong_values -> with self.assertRaises(TypeError):
381
+ # tlist[Tuple[int]]([[1], [2], [3], ["4"]])
382
+ raise NotImplemented
383
+
384
+
385
+ HANDLERS: Dict[type, Callable] = {
386
+ list: __handle_list_set_iterable,
387
+ tuple: __handle_tuple,
388
+ dict: __handle_dict,
389
+ set: __handle_list_set_iterable,
390
+ type: __handle_type,
391
+ List: __handle_list_set_iterable,
392
+ Tuple: __handle_tuple,
393
+ Dict: __handle_dict,
394
+ Set: __handle_list_set_iterable,
395
+ Type: __handle_type,
396
+ Iterable: __handle_list_set_iterable,
397
+ Union: __handle_union,
398
+ implicit_union_type: __handle_union,
399
+ Generator: __handle_generator,
400
+ Literal: __handle_literal,
401
+ Callable: __handle_callable,
402
+ Protocol: __handle_protocol,
403
+ }
404
+ try:
405
+ # This exists only from python version 3.11 onwards
406
+ from typing import Unpack
407
+
408
+ HANDLERS[Unpack] = __handle_unpack
409
+ except:
410
+ pass
411
+
412
+
413
+ def isoftype(V: Any, T: Any, /, strict: bool = True) -> bool:
414
+ """
415
+ Checks if an object is of a certain type.
416
+
417
+ Args:
418
+ V: The object to check.
419
+ T: The type to check against.
420
+ strict: Whether to perform strict type checking.
421
+
422
+ Returns:
423
+ True if the object is of the specified type, False otherwise.
424
+ """
425
+ if not isinstance(strict, bool):
426
+ logger.error("'strict' parameter must be of type bool")
427
+ raise TypeError("'strict' must be of type bool")
428
+
429
+ obj_origin, obj_args, obj_hints = __isoftype_inquire(V)
430
+ t_origin, t_args, t_hints = __isoftype_inquire(T)
431
+
432
+ params = (
433
+ V, T, strict,
434
+ obj_origin, obj_args, obj_hints,
435
+ t_origin, t_args, t_hints
436
+ )
437
+
438
+ if t_args is not None and Ellipsis in t_args and PARAMSPEC_STRICT:
439
+ from ..colors import warning # pylint: disable=cyclic-import
440
+ warning(
441
+ "using an ellipsis (as in '...') with isoftype is ambiguous returning False")
442
+ return False
443
+
444
+ if T is Union:
445
+ t_origin = Union # type:ignore
446
+ elif T is Protocol or Protocol in getattr(T, "__mro__", []) or _is_java_interface_type(T):
447
+ t_origin = Protocol # type:ignore
448
+ elif Protocol in getattr(V, "__mro__", []):
449
+ t_origin = Protocol # type:ignore
450
+
451
+ if t_origin is not None:
452
+ if getattr(t_origin, "_is_protocol", False) or isinstance(t_origin, _ProtocolMeta):
453
+ t_origin = Protocol # type:ignore
454
+
455
+ if t_origin in HANDLERS:
456
+ if t_origin in (list, tuple, dict, set, dict, Iterable):
457
+ if not isinstance(V, t_origin): # type:ignore
458
+ return False
459
+ result = HANDLERS[t_origin](params) # type:ignore
460
+ return result
461
+ # These imports must explicitly be specifically here and not at the top
462
+ logger.warning("Unhandled t_origin: %s, returning True", t_origin)
463
+ from danielutils import warning, get_traceback
464
+ warning(
465
+ f"In function isoftype, unhandled t_origin: {t_origin} returning True. stacktrace:")
466
+ print(*get_traceback())
467
+ return True
468
+
469
+ result = __handle_type_origin(params)
470
+ return result
471
+
472
+
473
+ __all__ = [
474
+ "isoftype"
475
+ ]
@@ -0,0 +1,71 @@
1
+ import logging
2
+ from typing import Any, Union, Sequence
3
+ from .isoftype import isoftype
4
+ from ..reflection import get_python_version
5
+ from ..logging_.utils import get_logger
6
+
7
+ logger = get_logger(__name__)
8
+ if get_python_version() < (3, 9):
9
+ from typing import List as List, Tuple as Tuple
10
+ else:
11
+ from builtins import list as List, tuple as Tuple # type:ignore
12
+
13
+
14
+ def isoneof(v: Any, types: Union[List[type], Tuple[type]]) -> bool:
15
+ """performs isoftype() or ... or isoftype()
16
+
17
+ Args:
18
+ v (Any): the value to check it's type
19
+ types (Union[list[Type], tuple[Type]): A Sequence of approved types
20
+
21
+ Raises:
22
+ TypeError: if the second argument is not from Union[list[Type], tuple[Type]
23
+
24
+ Returns:
25
+ bool: return True iff isoftype(v, types[0]) or ... isoftype(v, types[...])
26
+ """
27
+ logger.debug("Checking if %s is one of types: %s", v, types)
28
+ if not isinstance(types, (list, tuple)):
29
+ logger.error("'types' parameter must be of type 'list' or 'tuple'")
30
+ raise TypeError("'types' must be of type 'list' or 'tuple'")
31
+
32
+ for i, T in enumerate(types):
33
+ if isoftype(v, T):
34
+ logger.debug("Value %s matches type at index %s: %s", v, i, T)
35
+ return True
36
+
37
+ logger.debug("Value %s does not match any of the specified types", v)
38
+ return False
39
+
40
+
41
+ def isoneof_strict(v: Any, types: Union[List[type], Tuple[type]]) -> bool:
42
+ """performs 'type(v) in types' efficiently
43
+
44
+ Args:
45
+ v (Any): value to check
46
+ types (Sequence[Type]): sequence of approved types
47
+
48
+ Raises:
49
+ TypeError: if types is not a sequence
50
+
51
+ Returns:
52
+ bool: true if type of value appears in types
53
+ """
54
+ logger.debug("Strict type checking if %s (type: %s) is one of: %s", v, type(v), types)
55
+ if not isinstance(types, Sequence):
56
+ logger.error("'types' parameter must be of type Sequence")
57
+ raise TypeError("lst must be of type Sequence")
58
+
59
+ for i, T in enumerate(types):
60
+ if type(v) in {T}:
61
+ logger.debug("Value %s type matches at index %s: %s", v, i, T)
62
+ return True
63
+
64
+ logger.debug("Value %s type does not match any of the specified types", v)
65
+ return False
66
+
67
+
68
+ __all__ = [
69
+ "isoneof",
70
+ "isoneof_strict"
71
+ ]
@@ -0,0 +1,51 @@
1
+ import logging
2
+ from typing import Iterable, Generator, List
3
+ from .flatten import flatten
4
+ from ..logging_.utils import get_logger
5
+
6
+ logger = get_logger(__name__)
7
+
8
+
9
+ def _combine2(iter1: Iterable, iter2: Iterable) -> Generator:
10
+ for v1 in iter1:
11
+ for v2 in iter2:
12
+ yield v1, v2
13
+
14
+
15
+ def multiloop(*iterables: Iterable, pre_load: bool = False) -> Generator:
16
+ """
17
+ Generates all combinations of values from multiple iterables.
18
+
19
+ This function takes as input any number of iterables and generates all possible combinations of their values.
20
+ It also has an option to pre-load the iterables into memory before generating combinations.
21
+
22
+ Args:
23
+ *iterables (list[Iterable]): The iterables to generate combinations from.
24
+ pre_load (bool, optional): If True, pre-loads the iterables into memory. Defaults to False.
25
+
26
+ Yields:
27
+ Generator: A generator that yields tuples, each containing one combination of values from the iterables.
28
+ """
29
+ logger.info("Starting multiloop with %s iterables, pre_load=%s", len(iterables), pre_load)
30
+
31
+ if len(iterables) == 1:
32
+ yield from iterables[0]
33
+ return
34
+
35
+ arr: List[Iterable] = list(iterables)
36
+ if pre_load:
37
+ logger.info("Pre-loading iterables into memory")
38
+ arr = [list(itr) for itr in iterables]
39
+
40
+ cur = _combine2(*arr[:2])
41
+ for itr in arr[2:]:
42
+ cur = _combine2(cur, itr)
43
+
44
+ for v in cur:
45
+ flattened = tuple(flatten(v))
46
+ yield flattened
47
+
48
+
49
+ __all__ = [
50
+ "multiloop"
51
+ ]
@@ -0,0 +1,47 @@
1
+ import logging
2
+ import threading
3
+ from typing import TypeVar, Callable
4
+ from ..logging_.utils import get_logger
5
+
6
+ logger = get_logger(__name__)
7
+
8
+ T = TypeVar("T")
9
+ Consumer = Callable[[T], None]
10
+
11
+
12
+ def parallel_for(func: Consumer[T], *args: T, wait: bool = True) -> None:
13
+ """
14
+ This function will run 'func' in parallel with the given args individually
15
+ Args:
16
+ func: function to run in parallel
17
+ *args: args to call the function each time
18
+ wait: whether to wait for all the threads to join before returning
19
+
20
+ Returns:
21
+
22
+ """
23
+ logger.info("Starting parallel execution of %s with %s arguments, wait=%s", func.__name__, len(args), wait)
24
+ # this is safer... What if some other threads that were running will also end in the meantime?
25
+ threads = [threading.Thread(target=func, args=[arg]) for arg in args]
26
+
27
+ for t in threads:
28
+ t.start()
29
+
30
+ if wait:
31
+ for t in threads:
32
+ t.join()
33
+ logger.info("All threads completed successfully")
34
+ else:
35
+ logger.info("Threads started, not waiting for completion")
36
+ # before = threading.active_count()
37
+ # for arg in args:
38
+ # threadify(func)(arg)
39
+ #
40
+ # if wait:
41
+ # while threading.active_count() > before:
42
+ # pass
43
+
44
+
45
+ __all__ = [
46
+ 'parallel_for'
47
+ ]
@@ -0,0 +1,45 @@
1
+ import logging
2
+ from typing import List, Generator, Tuple, Union
3
+ from ..logging_.utils import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ def partitions(n: int, k: int) -> Generator[List[int], None, None]:
9
+ logger.info("Generating partitions of %s into %s parts", n, k)
10
+ from ..decorators import memo_generator
11
+
12
+ @memo_generator
13
+ def helper(n: int, target_sum: int, current_sum: int, topLevel: int, arr: Union[List[int], Tuple[int]]) -> \
14
+ Generator[List[int], None, None]:
15
+ arr = list(arr)
16
+ if n == 1:
17
+ if current_sum <= target_sum:
18
+ if topLevel == 1 or (target_sum - current_sum >= arr[-2]):
19
+ arr[-1] = target_sum - current_sum
20
+ yield tuple(arr)
21
+ return
22
+
23
+ start = 0
24
+ if n != topLevel:
25
+ start = arr[-1 * n - 1]
26
+
27
+ for i in range(start, target_sum + 1):
28
+ arr[-1 * n] = i
29
+ yield from helper(n - 1, target_sum, current_sum + i, topLevel, tuple(arr))
30
+
31
+ arr: List[int] = [0] * k
32
+ yield from helper(k, n, 0, k, tuple(arr))
33
+
34
+
35
+ def num_partitions(n: int, k: int) -> int:
36
+ logger.info("Counting number of partitions of %s into %s parts", n, k)
37
+ result = len(list(partitions(n, k)))
38
+ logger.info("Found %s partitions", result)
39
+ return result
40
+
41
+
42
+ __all__ = [
43
+ "partitions",
44
+ "num_partitions"
45
+ ]