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,48 @@
1
+ import logging
2
+ import functools
3
+ from typing import Callable
4
+ from ..decorators import overload
5
+ from ..logging_.utils import get_logger
6
+
7
+ logger = get_logger(__name__)
8
+
9
+
10
+ class OverloadMeta(type):
11
+ """A meta-class for overloading functions in a class
12
+ """
13
+
14
+ @staticmethod # type:ignore
15
+ def overload(func: Callable) -> overload:
16
+ """overloads a function
17
+
18
+ Args:
19
+ func (Callable): function ot overload
20
+
21
+ Returns:
22
+ overload: _description_
23
+ """
24
+ return overload(func) # type:ignore
25
+
26
+ def __new__(mcs, name, bases, namespace):
27
+ logger.info("Creating overload class: %s", name)
28
+
29
+ def create_wrapper(v: overload):
30
+ @functools.wraps(next(iter(v._functions.values()))[0]) # type:ignore# pylint: disable=protected-access
31
+ def wrapper(*args, **kwargs):
32
+ return v(*args, **kwargs)
33
+
34
+ return wrapper
35
+
36
+ overloaded_functions = 0
37
+ for k, v in namespace.items():
38
+ if isinstance(v, overload): # type:ignore
39
+ namespace[k] = create_wrapper(v)
40
+ overloaded_functions += 1
41
+
42
+ logger.info("OverloadMeta: %s created with %s overloaded functions", name, overloaded_functions)
43
+ return super().__new__(mcs, name, bases, namespace)
44
+
45
+
46
+ __all__ = [
47
+ "OverloadMeta"
48
+ ]
@@ -0,0 +1 @@
1
+ from .mock_module import *
@@ -0,0 +1,27 @@
1
+ import logging
2
+ from ..logging_.utils import get_logger
3
+
4
+ logger = get_logger(__name__)
5
+
6
+
7
+ class MockImportObject:
8
+ """
9
+ A class to create a mock object that will raise an import error when you try to interact with it in some way
10
+ """
11
+
12
+ def __init__(self, msg: str):
13
+ logger.info("Initializing MockImportObject with message: %s", msg)
14
+ self._msg = msg
15
+
16
+ def __getattr__(self, item):
17
+ logger.warning("MockImportObject attribute access blocked: %s - %s", item, self._msg)
18
+ raise ImportError(self._msg)
19
+
20
+ def __call__(self, *args, **kwargs):
21
+ logger.warning("MockImportObject call blocked with %s args and %s kwargs - %s", len(args), len(kwargs), self._msg)
22
+ raise ImportError(self._msg)
23
+
24
+
25
+ __all__ = [
26
+ "MockImportObject"
27
+ ]
danielutils/path.py ADDED
@@ -0,0 +1,55 @@
1
+ import logging
2
+ import os
3
+ from .logging_.utils import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ def get_current_working_directory() -> str:
9
+ """return the current working directory
10
+
11
+ Returns:
12
+ str: current working directory
13
+ """
14
+ return os.getcwd()
15
+
16
+
17
+ def set_current_working_directory(path: str) -> None:
18
+ """sets the current working directory
19
+
20
+ Args:
21
+ path (str): directory to set to
22
+ """
23
+ os.chdir(path)
24
+
25
+
26
+ def get_absolute_path(path: str) -> str:
27
+ """return the absolute path of given path
28
+
29
+ Args:
30
+ path (str): a path
31
+
32
+ Returns:
33
+ str: absolute version of that path
34
+ """
35
+ return os.path.abspath(path)
36
+
37
+
38
+ def get_relative_path(path: str) -> str:
39
+ """return the relative path of given path
40
+
41
+ Args:
42
+ path (str): a path
43
+
44
+ Returns:
45
+ str: relative (to current working directory) version of that path
46
+ """
47
+ return os.path.realpath(path)
48
+
49
+
50
+ __all__ = [
51
+ "get_current_working_directory",
52
+ "set_current_working_directory",
53
+ "get_absolute_path",
54
+ "get_relative_path"
55
+ ]
danielutils/print_.py ADDED
@@ -0,0 +1,123 @@
1
+ import logging
2
+ import sys
3
+ from typing import IO, List
4
+ from .functions.areoneof import areoneof
5
+ from .math_.math_print import mprint_parse_one
6
+ from .decorators import atomic, deprecate
7
+ from .colors import warning
8
+ from .logging_.utils import get_logger
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ def mprint(*args, sep: str = " ", end: str = "\n", stream=sys.stdout) -> None:
14
+ """Prints a formatted representation of mathematical expressions to the specified stream.
15
+
16
+ Args:
17
+ *args: The mathematical expressions to print.
18
+ sep (str, optional): The separator to use between the expressions. Defaults to " ".
19
+ end (str, optional): The string to append to the end of the printed expressions. Defaults to "\n".
20
+ stream (file object, optional): The stream to write the output to. Defaults to sys.stdout.
21
+
22
+ Raises:
23
+ TypeError: If any of the arguments is not a string.
24
+
25
+ Returns:
26
+ None
27
+ """
28
+ if not areoneof(args, [str]):
29
+ raise TypeError("s must be a string")
30
+ logger.debug("Printing %d mathematical expressions to %s", len(args), stream)
31
+ stream.write(sep.join([mprint_parse_one(s) for s in args]) + end)
32
+
33
+
34
+ @deprecate("The built-in 'print' function has an argument called 'file', use this instead") # type:ignore
35
+ def sprint(*args, sep: str = " ", end: str = "\n", stream=sys.stdout) -> None:
36
+ """Writes a string representation of the given arguments to the specified stream.
37
+
38
+ Args:
39
+ *args: The arguments to print.
40
+ sep (str, optional): The separator to use between the arguments. Defaults to " ".
41
+ end (str, optional): The string to append to the end of the printed arguments. Defaults to "\n".
42
+ stream (file object, optional): The stream to write the output to. Defaults to sys.stdout.
43
+
44
+ Returns:
45
+ None
46
+ """
47
+ stream.write(sep.join(args) + end)
48
+
49
+
50
+ @atomic # type:ignore
51
+ def aprint(*args, sep=" ", end="\n") -> None:
52
+ """Prints a string representation of the given arguments to the console.
53
+
54
+ Args:
55
+ *args: The arguments to print.
56
+ sep (str, optional): The separator to use between the arguments. Defaults to " ".
57
+ end (str, optional): The string to append to the end of the printed arguments. Defaults to "\n".
58
+
59
+ Returns:
60
+ None
61
+ """
62
+ print(*args, sep=sep, end=end)
63
+
64
+
65
+ class BetterPrinter:
66
+ def __init__(self, stream: IO = sys.stdout, thread_safe: bool = False):
67
+ self.stream: IO = stream
68
+ if thread_safe:
69
+ self.__call__ = atomic(self.__call__) # type:ignore
70
+ self._current_row: int = 0
71
+ self.rows: List[str] = []
72
+
73
+ def clear(self, flush: bool = True) -> None:
74
+ if not self.stream.isatty():
75
+ warning(f"Cannot clear because {self.stream} is not a terminal stream")
76
+ return
77
+ self.write("\033[2J", flush=flush)
78
+ self.rows.pop()
79
+
80
+ def clear_line(self) -> None:
81
+ self.write("\033[2K", end="")
82
+ self.rows.pop()
83
+
84
+ def move_up(self, num_lines: int = 1) -> None:
85
+ self.write(f"\033[{num_lines}A", end="")
86
+ self.rows.pop()
87
+ self._current_row -= 1
88
+
89
+ def write(self, *args, sep: str = " ", end: str = "\n", flush: bool = True):
90
+ text = sep.join(args) + end
91
+ self._current_row += text.count("\n")
92
+ self.rows.extend([f"{s}\n" for s in text.splitlines() if len(s) > 0])
93
+ self.stream.write(text)
94
+ if flush:
95
+ self.stream.flush()
96
+
97
+ def __call__(self, *args, sep: str = " ", end: str = "\n", flush: bool = True) -> None:
98
+ self.write(*args, sep=sep, end=end, flush=flush)
99
+
100
+ @property
101
+ def current_row(self) -> int:
102
+ return self._current_row
103
+
104
+ def insert(self, text: str, row: int) -> None:
105
+ for _ in range(len(self.rows)):
106
+ bprint.move_up()
107
+ bprint.clear_line()
108
+ self.rows.insert(row, text)
109
+ num = len(self.rows)
110
+ self.write(*self.rows, end="")
111
+ for _ in range(num):
112
+ self.rows.pop()
113
+
114
+
115
+ bprint = BetterPrinter()
116
+
117
+ __all__ = [
118
+ "sprint",
119
+ "mprint",
120
+ "aprint",
121
+ "bprint",
122
+ 'BetterPrinter'
123
+ ]
@@ -0,0 +1,3 @@
1
+ from .progress_bar import *
2
+ from .progress_bar_pool import *
3
+ from .ascii_progress_bar import *
@@ -0,0 +1,161 @@
1
+ import logging
2
+ import time
3
+ from typing import Optional, Iterable, Sized, Iterator
4
+
5
+ from .progress_bar import ProgressBar
6
+ from .progress_bar_pool import ProgressBarPool
7
+ from ..print_ import bprint
8
+ from ..logging_.utils import get_logger
9
+
10
+ logger = get_logger(__name__)
11
+
12
+
13
+ class AsciiProgressBar(ProgressBar):
14
+
15
+ def __init__(
16
+ self,
17
+ iterator: Iterator,
18
+ position: int,
19
+ *,
20
+ total: Optional[float] = None,
21
+ desc: str = "",
22
+ leave: bool = True,
23
+ num_bars: int = 1,
24
+ ncols: int = 50,
25
+ pool: Optional[ProgressBarPool] = None,
26
+ **kwargs
27
+ ):
28
+ total_ = 1
29
+ if isinstance(iterator, Sized):
30
+ total_ = len(iterator)
31
+ if total is not None:
32
+ total_ = total # type:ignore
33
+ ProgressBar.__init__(self, total_, position, desc=desc)
34
+ self.iterator: Iterator = iterator
35
+ self.pool: ProgressBarPool = pool # type:ignore
36
+ self.num_bars: int = num_bars
37
+ self.leave: bool = leave
38
+ self.initial_value: float = 0
39
+ self.current_value: float = 0
40
+ self.ncols: int = ncols
41
+ self.unit: str = "it"
42
+ self.pbar_format = "{l_bar} |{bar}| {n_fmt:.2f}/{total_fmt:.2f}{unit}" \
43
+ " [{elapsed:.2f}<{remaining}, {rate_fmt:.2f}{unit}{postfix}]"
44
+ self.__dict__.update(kwargs)
45
+ self.initial_start_time = time.time()
46
+ self.prev_update: float = self.initial_start_time
47
+ self.delta: float = 0
48
+ self.prev_value: float = self.initial_value
49
+ self.bprint_row_index = bprint.current_row
50
+ logger.info("AsciiProgressBar initialized: %s (total=%s, position=%s)", desc, total_, position)
51
+
52
+ def __iter__(self):
53
+ logger.info("Starting iteration over AsciiProgressBar: %s", self.desc)
54
+ self.bprint_row_index = bprint.current_row
55
+ items_processed = 0
56
+ for v in self.iterator:
57
+ self.update(0)
58
+ yield v
59
+ bprint.move_up()
60
+ bprint.clear_line()
61
+ if len(bprint.rows) > 0:
62
+ bprint.rows.pop()
63
+ self.update(1)
64
+ items_processed += 1
65
+ bprint.move_up()
66
+ bprint.clear_line()
67
+ if len(bprint.rows) > 0:
68
+ bprint.rows.pop()
69
+ logger.info("Completed iteration: processed %s items", items_processed)
70
+ if self.position > 0:
71
+ self.reset()
72
+ else:
73
+ self.draw()
74
+
75
+ def draw(self, *, refresh: bool = False) -> None:
76
+ percent = self.current_value / self.total
77
+ num_to_fill = int(percent * self.ncols)
78
+ progress_str = num_to_fill * "#" + (self.ncols - num_to_fill) * " "
79
+ to_print = self.pbar_format.format(
80
+ l_bar=self.desc,
81
+ bar=progress_str,
82
+ n_fmt=self.current_value,
83
+ total_fmt=self.total,
84
+ elapsed=self.prev_update - self.initial_start_time,
85
+ remaining="?",
86
+ rate_fmt=(self.current_value - self.prev_value) /
87
+ self.delta if self.delta != 0 else 0,
88
+ postfix="/s",
89
+ unit=self.unit
90
+ )
91
+ if refresh and self.pool is not None and len(self.pool.bars) > 1:
92
+ i = bprint.rows.index(f"{self.prev_print}\n") # type:ignore
93
+ rows = [to_print]
94
+ for j, row in enumerate(bprint.rows[i + 1:]):
95
+ rows.append(row)
96
+ for row in rows:
97
+ bprint.move_up(1)
98
+ bprint.clear_line()
99
+ bprint.rows.pop()
100
+ for row in rows:
101
+ bprint(row)
102
+ else:
103
+ bprint(to_print)
104
+ self.prev_print = to_print
105
+
106
+ def update(self, amount: float = 1, refresh: bool = False): # type:ignore
107
+ self.prev_value = self.current_value
108
+ self.current_value = min(
109
+ self.current_value + amount, self.total) # type:ignore
110
+ current_time = time.time()
111
+ self.delta = current_time - self.prev_update
112
+ self.prev_update = current_time
113
+ self.draw(refresh=refresh)
114
+
115
+ def _write(self, *args: str, sep: str = " ", end: str = "\n") -> None:
116
+ if not end.endswith("\n"):
117
+ end += "\n"
118
+ if self.pool is not None and len(self.pool.bars) > 0:
119
+ succeeding_bars = self.pool.bars[self.position + 1:]
120
+ if succeeding_bars:
121
+ for succeeding_bar in succeeding_bars:
122
+ # clear child
123
+ bprint.move_up()
124
+ bprint.clear_line()
125
+ bprint.rows.pop()
126
+ for _ in range(succeeding_bar.num_writes):
127
+ # clear child's writes
128
+ bprint.move_up()
129
+ bprint.clear_line()
130
+ bprint.rows.pop()
131
+ # clear self
132
+ bprint.move_up()
133
+ bprint.clear_line()
134
+ bprint.rows.pop()
135
+ bprint(sep.join(map(str, args)), end=end)
136
+ self.draw()
137
+ for succeeding_bar in succeeding_bars:
138
+ succeeding_bar.update(0, refresh=True)
139
+ return
140
+
141
+ bprint.move_up()
142
+ bprint.clear_line()
143
+ bprint.rows.pop()
144
+ bprint(sep.join(map(str, args)), end=end)
145
+ self.draw()
146
+
147
+ def reset(self) -> None:
148
+ self.current_value = self.initial_value
149
+ self.initial_start_time = time.time()
150
+ self.delta = 0
151
+ self.prev_value = self.initial_value
152
+ for _ in range(self.num_writes):
153
+ bprint.move_up()
154
+ bprint.clear_line()
155
+ bprint.rows.pop()
156
+ self.writes.clear()
157
+
158
+
159
+ __all__ = [
160
+ 'AsciiProgressBar'
161
+ ]
@@ -0,0 +1,75 @@
1
+ import logging
2
+ import math
3
+ import time
4
+ from abc import ABC, abstractmethod
5
+ from typing import Optional, Type, List, Iterable, Any
6
+ from ..logging_.utils import get_logger
7
+
8
+ try:
9
+ from tqdm import tqdm
10
+ except ImportError:
11
+ from ..mock_ import MockImportObject
12
+
13
+ tqdm = MockImportObject("`tqdm` is not installed") # type:ignore
14
+
15
+ logger = get_logger(__name__)
16
+
17
+
18
+ class ProgressBar(ABC):
19
+ """An interface
20
+
21
+ Args:
22
+ ABC (_type_): _description_
23
+ """
24
+ DEFAULT_BAR_FORMAT = "{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}"
25
+
26
+ @abstractmethod
27
+ def __init__(self, total, position: int, unit="it", bar_format: str = DEFAULT_BAR_FORMAT, *, desc: str,
28
+ **kwargs) -> None:
29
+ self.desc: str = desc
30
+ self.total = total
31
+ self.position = position
32
+ self.unit = unit
33
+ self.bar_format = bar_format
34
+ self.writes: List[str] = []
35
+ logger.info("ProgressBar initialized: %s (total=%s, position=%s, unit=%s)", desc, total, position, unit)
36
+
37
+ @property
38
+ def num_writes(self):
39
+ return len(self.writes)
40
+
41
+ @abstractmethod
42
+ def update(self, amount: float = 1, **kwargs) -> None:
43
+ """A function to update the progress-bar's value by a positive relative amount
44
+ """
45
+
46
+ @abstractmethod
47
+ def _write(self, *args: str, sep: str = " ", end: str = "\n") -> None: ...
48
+
49
+ def write(self, *args: Any, sep: str = " ", end: str = "\n") -> None:
50
+ """A function to write additional text with the progress bar
51
+ """
52
+ processed = list(map(str, args))
53
+ message = sep.join(processed) + end
54
+ self._write(*processed, sep=sep, end=end)
55
+ self.writes.append(message)
56
+
57
+ @abstractmethod
58
+ def reset(self) -> None:
59
+ """A function to reset the progress-bar's progress
60
+ """
61
+
62
+ @abstractmethod
63
+ def __iter__(self): ...
64
+
65
+
66
+ try:
67
+ from tqdm import tqdm
68
+
69
+ ProgressBar.register(tqdm)
70
+ except ImportError:
71
+ pass
72
+
73
+ __all__ = [
74
+ 'ProgressBar',
75
+ ]
@@ -0,0 +1,72 @@
1
+ import logging
2
+ from typing import Type, List, Optional, Iterator
3
+ from .progress_bar import ProgressBar
4
+ from ..print_ import bprint
5
+ from ..logging_.utils import get_logger
6
+
7
+ logger = get_logger(__name__)
8
+
9
+
10
+ class ProgressBarPool:
11
+ def __init__(
12
+ self,
13
+ pbar_class: Type[ProgressBar],
14
+ num_of_bars: int = 1,
15
+ global_options: Optional[dict] = None,
16
+ individual_options: Optional[List[Optional[dict]]] = None
17
+ ) -> None:
18
+ logger.info("Creating ProgressBarPool with %s bars using %s", num_of_bars, pbar_class.__name__)
19
+ self.bars: List[ProgressBar] = []
20
+ if global_options is None:
21
+ global_options = {}
22
+ if individual_options is None:
23
+ individual_options = [{} for _ in range(num_of_bars)]
24
+ if len(individual_options) != num_of_bars:
25
+ error_msg = "must supply the same number of options as there are bars"
26
+ logger.error("ProgressBarPool initialization failed: %s", error_msg)
27
+ raise ValueError(error_msg)
28
+ for i in range(num_of_bars):
29
+ if individual_options[i] is None:
30
+ individual_options[i] = {}
31
+ max_desc_length: int = max([len(individual_options[i].get("desc", f"pbar {i}")) for i in range(num_of_bars)])
32
+
33
+ for i in range(num_of_bars):
34
+ final_options: dict = global_options.copy()
35
+ final_options.update(individual_options[i]) # type:ignore
36
+ if "desc" not in final_options:
37
+ final_options["desc"] = f"pbar {i}"
38
+ final_options["desc"] = final_options["desc"].ljust(max_desc_length, " ")
39
+ t = pbar_class(
40
+ position=i,
41
+ pool=self,
42
+ **final_options
43
+ )
44
+ self.bars.append(t)
45
+ self.writes: List[str] = []
46
+ logger.info("ProgressBarPool created successfully with %s progress bars", len(self.bars))
47
+
48
+ def __getitem__(self, index: int) -> ProgressBar:
49
+ return self.bars[index]
50
+
51
+ def write(self, msg: str, end: str = "\n") -> None:
52
+ prev_rows = bprint.rows.copy()
53
+ for w in self.writes:
54
+ prev_rows.remove(w)
55
+ self.writes.append(msg + end)
56
+ rows = self.writes.copy() + prev_rows
57
+ for _ in bprint.rows:
58
+ bprint.move_up()
59
+ bprint.clear_line()
60
+ bprint.rows.clear()
61
+
62
+ for row in rows:
63
+ bprint(row, end="")
64
+ pass
65
+
66
+ def __iter__(self) -> Iterator[ProgressBar]:
67
+ return iter(self.bars)
68
+
69
+
70
+ __all__ = [
71
+ "ProgressBarPool",
72
+ ]
@@ -0,0 +1,3 @@
1
+ from .evaluable import *
2
+ from .dictable import *
3
+ from .serializable import *
@@ -0,0 +1,38 @@
1
+ import logging
2
+ from typing import Protocol, TypeVar, runtime_checkable,Dict as Dict
3
+ from ..reflection import get_python_version
4
+ from ..logging_.utils import get_logger
5
+
6
+ logger = get_logger(__name__)
7
+
8
+ if get_python_version() >= (3, 9):
9
+ from builtins import dict as Dict
10
+
11
+ K = TypeVar('K')
12
+ V = TypeVar('V')
13
+
14
+ @runtime_checkable
15
+ class Dictable(Protocol[K, V]):
16
+ @classmethod
17
+ def from_dict(cls, d: Dict[K, V]) -> 'Dictable[K,V]':
18
+ """
19
+ Create a Dictable object from a dictionary.
20
+
21
+ Note: This is a protocol method. Implementations should add logging
22
+ to track dictionary conversion operations.
23
+ """
24
+ ...
25
+
26
+ def to_dict(self) -> Dict[K, V]:
27
+ """
28
+ Convert the object to a dictionary.
29
+
30
+ Note: This is a protocol method. Implementations should add logging
31
+ to track dictionary conversion operations.
32
+ """
33
+ ...
34
+
35
+
36
+ __all__ = [
37
+ 'Dictable'
38
+ ]
@@ -0,0 +1,26 @@
1
+ import logging
2
+ from abc import abstractmethod
3
+ from typing import Protocol, TypeVar, runtime_checkable
4
+ from ..logging_.utils import get_logger
5
+
6
+ logger = get_logger(__name__)
7
+
8
+ T = TypeVar('T', covariant=True)
9
+
10
+
11
+ @runtime_checkable
12
+ class Evaluable(Protocol[T]):
13
+ @abstractmethod
14
+ def evaluate(self) -> T:
15
+ """
16
+ Evaluate the object and return a value of type T.
17
+
18
+ Note: This is a protocol method. Implementations should add logging
19
+ to track evaluation operations.
20
+ """
21
+ ...
22
+
23
+
24
+ __all__ = [
25
+ "Evaluable"
26
+ ]
@@ -0,0 +1,51 @@
1
+ import logging
2
+ from typing import Protocol, runtime_checkable, Any
3
+ from ..logging_.utils import get_logger
4
+
5
+ logger = get_logger(__name__)
6
+
7
+
8
+ @runtime_checkable
9
+ class Serializable(Protocol):
10
+ def serialize(self) -> bytes:
11
+ """
12
+ Serialize the object to bytes.
13
+
14
+ Note: This is a protocol method. Implementations should add logging
15
+ to track serialization operations.
16
+ """
17
+ ...
18
+
19
+ def deserialize(self, serealized: bytes) -> 'Serializable':
20
+ """
21
+ Deserialize bytes back to a Serializable object.
22
+
23
+ Note: This is a protocol method. Implementations should add logging
24
+ to track deserialization operations.
25
+ """
26
+ ...
27
+
28
+
29
+ def serialize(obj: Any) -> bytes:
30
+ logger.info("Serializing object of type: %s", type(obj).__name__)
31
+ if isinstance(obj, Serializable):
32
+ result = obj.serialize()
33
+ logger.info("Serialization successful, returned %s bytes", len(result))
34
+ return result
35
+ logger.warning("Object %s does not implement Serializable protocol", type(obj).__name__)
36
+ #TODO
37
+ return b""
38
+
39
+
40
+ def deserialize(obj: bytes) -> Any:
41
+ logger.info("Deserializing %s bytes", len(obj))
42
+ logger.warning("Deserialize function not implemented (TODO)")
43
+ #TODO
44
+ return None
45
+
46
+
47
+ __all__ = [
48
+ 'Serializable',
49
+ 'serialize',
50
+ 'deserialize',
51
+ ]
danielutils/py.typed ADDED
File without changes