danielutils 0.9.81__tar.gz → 0.9.83__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {danielutils-0.9.81/danielutils.egg-info → danielutils-0.9.83}/PKG-INFO +2 -2
- {danielutils-0.9.81 → danielutils-0.9.83}/README.md +1 -1
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/__init__.py +1 -2
- danielutils-0.9.83/danielutils/context_managers/__init__.py +2 -0
- danielutils-0.9.83/danielutils/context_managers/attr_context.py +25 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/context_managers/temporary_file.py +12 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/__init__.py +1 -0
- danielutils-0.9.83/danielutils/functions/parallel_for.py +37 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/math_/__init__.py +0 -1
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/print_.py +51 -15
- danielutils-0.9.83/danielutils/progress_bar/__init__.py +3 -0
- danielutils-0.9.83/danielutils/progress_bar/ascii_progress_bar.py +104 -0
- danielutils-0.9.83/danielutils/progress_bar/progress_bar.py +54 -0
- danielutils-0.9.81/danielutils/tqdm_.py → danielutils-0.9.83/danielutils/progress_bar/progress_bar_pool.py +19 -24
- danielutils-0.9.83/danielutils/system/layered_command.py +118 -0
- {danielutils-0.9.81 → danielutils-0.9.83/danielutils.egg-info}/PKG-INFO +2 -2
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils.egg-info/SOURCES.txt +6 -3
- {danielutils-0.9.81 → danielutils-0.9.83}/pyproject.toml +1 -1
- danielutils-0.9.81/danielutils/context_managers/__init__.py +0 -1
- danielutils-0.9.81/danielutils/math_/polynomial/__init__.py +0 -1
- danielutils-0.9.81/danielutils/math_/polynomial/polinomial.py +0 -33
- danielutils-0.9.81/danielutils/system/layered_command.py +0 -86
- {danielutils-0.9.81 → danielutils-0.9.83}/LICENSE +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/MANIFEST.in +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/database/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/database/cached_database.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/database/database.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/database/redis_database.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/multiprogramming/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/multiprogramming/multi_id.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/multiprogramming/worker.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/multiprogramming/worker_pool.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/abstractions/repl.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/aliases.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/counter.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/frange.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/factory.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/tdict.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/tlist.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/tset.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/better_builtins/typed_builtins/ttuple.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/colors.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/convenience.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/conversions/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/conversions/main_conversions.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/conversions/specialized_conversions/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/conversions/specialized_conversions/to_hex.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/conversions/specialized_conversions/to_int.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/comparer.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/default_dict.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/functions.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/graph/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/graph/binary_node.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/graph/graph.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/graph/multinode.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/graph/node.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/heap/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/heap/heap.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/heap/max_heap.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/heap/min_heap.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/queue/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/queue/atomic_queue.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/queue/priority_queue.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/queue/queue.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/stack.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/trees/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/trees/binary_syntax_tree.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/data_structures/trees/binary_tree.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/date.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/date_time.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/atomic.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/attach.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/chain_decorators.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/decorate_conditionally.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/delay_call.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/deprecate.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/final.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/limit_recursion.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/memo.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/overload.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/partially_implemented.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/processify.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/property.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/singleton.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/threadify.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/timeout.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/total_ordering.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/decorators/validate.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/exceptions.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/areoneof.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/check_foreach.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/flatten.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/isoftype.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/isoneof.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/multiloop.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/powerset.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/subseteq.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/functions/types_subseteq.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/generators/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/generators/conditional_generator.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/generators/generator_from_stream.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/generators/join_generators.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/internet.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/io_.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/math_/constants.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/math_/functions.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/math_/math_print.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/math_/math_symbols.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/atomic_class_meta.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/implicit_data_deleter_meta.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/instance_cache_meta.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/interface.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/metaclasses/overload_meta.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/mock_/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/mock_/mock_database.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/mock_/mock_module.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/path.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/protocols/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/protocols/dictable.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/protocols/evaluable.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/py.typed +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/class_/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/class_/class_reflection.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/file/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/file/file_reflection.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/function/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/function/function_reflections.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/callstack.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/get_traceback.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/os_.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/packages.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/python_version.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/signals.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/interpreter/tracer.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/module/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/module/module_reflections.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/reflection/module/package_reflection.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/snippets/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/snippets/try_get.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/independent.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/windows/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/windows/utils/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/windows/utils/filetime.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/windows/win32_ctime.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/system/windows/windows.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/text.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/time.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/databases/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/databases/all.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/oop/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/oop/observer.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/oop/strategy.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/conditional_variable.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/continuous/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/bernoulli.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/binomial.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/conditional_from_discrete_probability_func.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/discrete.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/geometric.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/poisson.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/conditional_variable/discrete/uniform.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/distributions.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/expressions/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/expressions/accumulation_expression.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/expressions/probability_expression.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/funcs/__init__.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/funcs/covariance.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/funcs/expected_value.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/funcs/probability_function.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/funcs/variance.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/operator.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/protocols.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/supp.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/university/probability/transformation.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils/versioned_imports.py +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils.egg-info/dependency_links.txt +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/danielutils.egg-info/top_level.txt +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/setup.cfg +0 -0
- {danielutils-0.9.81 → danielutils-0.9.83}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: danielutils
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.83
|
|
4
4
|
Summary: A python utils library for things I find useful
|
|
5
5
|
Author-email: danielnachumdev <danielnachumdev@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -41,7 +41,7 @@ License-File: LICENSE
|
|
|
41
41
|
[](https://www.python.org/downloads/release/python-31011/)
|
|
42
42
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
43
43
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
44
|
-
# danielutils v=0.9.
|
|
44
|
+
# danielutils v=0.9.83
|
|
45
45
|
A utils library for things that I find useful for my coding workflow.\
|
|
46
46
|
Feel free to use and / or contribute / improve my code :)
|
|
47
47
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://www.python.org/downloads/release/python-31011/)
|
|
5
5
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
6
6
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
7
|
-
# danielutils v=0.9.
|
|
7
|
+
# danielutils v=0.9.83
|
|
8
8
|
A utils library for things that I find useful for my coding workflow.\
|
|
9
9
|
Feel free to use and / or contribute / improve my code :)
|
|
10
10
|
|
|
@@ -17,9 +17,8 @@ from .protocols import *
|
|
|
17
17
|
|
|
18
18
|
from .reflection import *
|
|
19
19
|
from .decorators import *
|
|
20
|
-
|
|
21
20
|
# ========== NEEDS REFLECTION ==========
|
|
22
|
-
from .
|
|
21
|
+
from .progress_bar import *
|
|
23
22
|
# ========== NEEDS DECORATORS ==========
|
|
24
23
|
from .colors import *
|
|
25
24
|
# ========== NEEDS BOTH ==========
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
class AttrContext:
|
|
2
|
+
def __init__(self, obj: object, attr: str, new_value: object, *, nonexistent_is_error: bool = True) -> None:
|
|
3
|
+
self.obj = obj
|
|
4
|
+
self.attr = attr
|
|
5
|
+
self.new_value = new_value
|
|
6
|
+
self.old_value = None
|
|
7
|
+
self._has_attr: bool = hasattr(self.obj, self.attr)
|
|
8
|
+
if nonexistent_is_error and not self._has_attr:
|
|
9
|
+
raise RuntimeError(f"Nonexistent attribute '{self.attr}' in '{self.obj}'")
|
|
10
|
+
|
|
11
|
+
def __enter__(self) -> 'AttrContext':
|
|
12
|
+
self.old_value = getattr(self.obj, self.attr, None)
|
|
13
|
+
setattr(self.obj, self.attr, self.new_value)
|
|
14
|
+
return self
|
|
15
|
+
|
|
16
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
17
|
+
if self._has_attr:
|
|
18
|
+
setattr(self.obj, self.attr, self.old_value)
|
|
19
|
+
else:
|
|
20
|
+
delattr(self.obj, self.attr)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
'AttrContext'
|
|
25
|
+
]
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
from ..io_ import file_exists, delete_file
|
|
2
|
+
import atexit
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
class TemporaryFile:
|
|
6
|
+
_instances: set['TemporaryFile'] = set()
|
|
7
|
+
|
|
5
8
|
def __init__(self, path: str):
|
|
6
9
|
if file_exists(path):
|
|
7
10
|
raise RuntimeError(f"Can't create a temporary file if file '{path}' already exists.")
|
|
8
11
|
self.path = path
|
|
12
|
+
TemporaryFile._instances.add(self)
|
|
9
13
|
|
|
10
14
|
def __enter__(self):
|
|
11
15
|
return self
|
|
@@ -13,10 +17,18 @@ class TemporaryFile:
|
|
|
13
17
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
14
18
|
self.close()
|
|
15
19
|
|
|
20
|
+
@atexit.register
|
|
21
|
+
@staticmethod
|
|
22
|
+
def _global_close():
|
|
23
|
+
for inst in TemporaryFile._instances:
|
|
24
|
+
inst.close()
|
|
25
|
+
|
|
16
26
|
def close(self) -> None:
|
|
17
27
|
delete_file(self.path)
|
|
18
28
|
|
|
19
29
|
def read(self) -> list[str]:
|
|
30
|
+
if not file_exists(self.path):
|
|
31
|
+
return []
|
|
20
32
|
with open(self.path, 'r') as f:
|
|
21
33
|
return f.readlines()
|
|
22
34
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from typing import TypeVar, Callable
|
|
3
|
+
|
|
4
|
+
T = TypeVar("T")
|
|
5
|
+
Consumer = Callable[[T], None]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parallel_for(func: Consumer[T], *args: T, wait: bool = True) -> None:
|
|
9
|
+
"""
|
|
10
|
+
This function will run 'func' in parallel with the given args individually
|
|
11
|
+
Args:
|
|
12
|
+
func: function to run in parallel
|
|
13
|
+
*args: args to call the function each time
|
|
14
|
+
wait: whether to wait for all the threads to join before returning
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
# this is safer... What if some other threads that were running will also end in the meantime?
|
|
20
|
+
threads = [threading.Thread(target=func, args=[arg]) for arg in args]
|
|
21
|
+
for t in threads:
|
|
22
|
+
t.start()
|
|
23
|
+
if wait:
|
|
24
|
+
for t in threads:
|
|
25
|
+
t.join()
|
|
26
|
+
# before = threading.active_count()
|
|
27
|
+
# for arg in args:
|
|
28
|
+
# threadify(func)(arg)
|
|
29
|
+
#
|
|
30
|
+
# if wait:
|
|
31
|
+
# while threading.active_count() > before:
|
|
32
|
+
# pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = [
|
|
36
|
+
'parallel_for'
|
|
37
|
+
]
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import sys
|
|
2
|
+
from typing import IO
|
|
2
3
|
from .functions.areoneof import areoneof
|
|
3
4
|
from .math_.math_print import mprint_parse_one
|
|
4
5
|
from .decorators import atomic, deprecate
|
|
6
|
+
from .colors import warning
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
def mprint(*args, sep: str = " ", end: str = "\n", stream=sys.stdout) -> None:
|
|
@@ -21,7 +23,7 @@ def mprint(*args, sep: str = " ", end: str = "\n", stream=sys.stdout) -> None:
|
|
|
21
23
|
"""
|
|
22
24
|
if not areoneof(args, [str]):
|
|
23
25
|
raise TypeError("s must be a string")
|
|
24
|
-
stream.write(sep.join([mprint_parse_one(s) for s in args])+end)
|
|
26
|
+
stream.write(sep.join([mprint_parse_one(s) for s in args]) + end)
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
@deprecate("The built-in 'print' function has an argument called 'file', use this instead")
|
|
@@ -37,7 +39,7 @@ def sprint(*args, sep: str = " ", end: str = "\n", stream=sys.stdout) -> None:
|
|
|
37
39
|
Returns:
|
|
38
40
|
None
|
|
39
41
|
"""
|
|
40
|
-
stream.write(sep.join(args)+end)
|
|
42
|
+
stream.write(sep.join(args) + end)
|
|
41
43
|
|
|
42
44
|
|
|
43
45
|
@atomic
|
|
@@ -55,25 +57,59 @@ def aprint(*args, sep=" ", end="\n") -> None:
|
|
|
55
57
|
print(*args, sep=sep, end=end)
|
|
56
58
|
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
def
|
|
60
|
-
|
|
60
|
+
class BetterPrinter:
|
|
61
|
+
def __init__(self, thread_safe: bool = False):
|
|
62
|
+
if thread_safe:
|
|
63
|
+
self.__call__ = atomic(self.__call__)
|
|
64
|
+
self._current_row: int = 0
|
|
65
|
+
self.rows: list[str] = []
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
def clear(self, stream: IO = sys.stdout, flush: bool = True) -> None:
|
|
68
|
+
if not stream.isatty():
|
|
69
|
+
warning(f"Cannot clear because {stream} is not a terminal stream")
|
|
70
|
+
return
|
|
71
|
+
self.write("\033[2J", stream=stream, flush=flush)
|
|
72
|
+
self.rows.pop()
|
|
73
|
+
|
|
74
|
+
def clear_line(self) -> None:
|
|
75
|
+
self.write("\033[2K", end="")
|
|
76
|
+
self.rows.pop()
|
|
77
|
+
|
|
78
|
+
def move_up(self, num_lines: int = 1) -> None:
|
|
79
|
+
self.write(f"\033[{num_lines}A", end="")
|
|
80
|
+
self.rows.pop()
|
|
81
|
+
self._current_row -= 1
|
|
82
|
+
|
|
83
|
+
def write(self, *args, sep: str = " ", end: str = "\n", stream: IO = sys.stdout, flush: bool = True):
|
|
84
|
+
text = sep.join(args) + end
|
|
85
|
+
self._current_row += text.count("\n")
|
|
86
|
+
self.rows.extend([f"{s}\n" for s in text.splitlines() if len(s) > 0])
|
|
87
|
+
stream.write(text)
|
|
88
|
+
if flush:
|
|
89
|
+
stream.flush()
|
|
90
|
+
|
|
91
|
+
def __call__(self, *args, **kwargs) -> None:
|
|
92
|
+
self.write(*args, **kwargs)
|
|
93
|
+
|
|
94
|
+
@property
|
|
95
|
+
def current_row(self) -> int:
|
|
96
|
+
return self._current_row
|
|
97
|
+
|
|
98
|
+
def insert(self, text: str, row: int) -> None:
|
|
99
|
+
self.rows.insert(row, text)
|
|
100
|
+
num_rows = len(self.rows)
|
|
101
|
+
self.clear()
|
|
102
|
+
self.write(*self.rows)
|
|
103
|
+
for _ in range(num_rows):
|
|
104
|
+
self.rows.pop()
|
|
67
105
|
|
|
68
|
-
Returns:
|
|
69
|
-
None
|
|
70
|
-
"""
|
|
71
|
-
stream.write(sep.join(args)+end)
|
|
72
106
|
|
|
107
|
+
bprint = BetterPrinter()
|
|
73
108
|
|
|
74
109
|
__all__ = [
|
|
75
110
|
"sprint",
|
|
76
111
|
"mprint",
|
|
77
112
|
"aprint",
|
|
78
|
-
"bprint"
|
|
113
|
+
"bprint",
|
|
114
|
+
'BetterPrinter'
|
|
79
115
|
]
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from typing import Optional, Iterable, Sized
|
|
3
|
+
|
|
4
|
+
from .progress_bar import ProgressBar
|
|
5
|
+
from ..print_ import bprint
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AsciiProgressBar(ProgressBar):
|
|
9
|
+
|
|
10
|
+
def __init__(
|
|
11
|
+
self,
|
|
12
|
+
iterable: Iterable,
|
|
13
|
+
position: int,
|
|
14
|
+
*,
|
|
15
|
+
total: Optional[float] = None,
|
|
16
|
+
desc: str = "",
|
|
17
|
+
leave: bool = True,
|
|
18
|
+
num_bars: int = 1,
|
|
19
|
+
ncols: int = 50,
|
|
20
|
+
**kwargs
|
|
21
|
+
):
|
|
22
|
+
self.iterable: Iterable = iterable
|
|
23
|
+
if isinstance(self.iterable, Sized):
|
|
24
|
+
total_ = len(self.iterable)
|
|
25
|
+
if total is not None:
|
|
26
|
+
total_ = total
|
|
27
|
+
ProgressBar.__init__(self, total_, position)
|
|
28
|
+
self.num_bars: int = num_bars
|
|
29
|
+
self.leave: bool = leave
|
|
30
|
+
self.desc: str = desc
|
|
31
|
+
self.initial_value: float = 0
|
|
32
|
+
self.current_value: float = 0
|
|
33
|
+
self.ncols: int = ncols
|
|
34
|
+
self.unit: str = "it"
|
|
35
|
+
self.pbar_format = "{l_bar} |{bar}| {n_fmt:.2f}/{total_fmt:.2f}{unit}" \
|
|
36
|
+
" [{elapsed:.2f}<{remaining}, {rate_fmt:.2f}{unit}{postfix}]"
|
|
37
|
+
self.__dict__.update(kwargs)
|
|
38
|
+
self.initial_start_time = time.time()
|
|
39
|
+
self.prev_update: float = self.initial_start_time
|
|
40
|
+
self.delta: float = 0
|
|
41
|
+
self.prev_value: float = self.initial_value
|
|
42
|
+
self.bprint_row_index = bprint.current_row
|
|
43
|
+
|
|
44
|
+
def __iter__(self):
|
|
45
|
+
self.bprint_row_index = bprint.current_row
|
|
46
|
+
for v in self.iterable:
|
|
47
|
+
self.update(1)
|
|
48
|
+
yield v
|
|
49
|
+
bprint.move_up()
|
|
50
|
+
bprint.clear_line()
|
|
51
|
+
if self.position > 0:
|
|
52
|
+
self.reset()
|
|
53
|
+
else:
|
|
54
|
+
self.draw()
|
|
55
|
+
|
|
56
|
+
def draw(self) -> None:
|
|
57
|
+
percent = self.current_value / self.total
|
|
58
|
+
num_to_fill = int(percent * self.ncols)
|
|
59
|
+
progress_str = num_to_fill * "#" + (self.ncols - num_to_fill) * " "
|
|
60
|
+
to_print = self.pbar_format.format(
|
|
61
|
+
l_bar=self.desc,
|
|
62
|
+
bar=progress_str,
|
|
63
|
+
n_fmt=self.current_value,
|
|
64
|
+
total_fmt=self.total,
|
|
65
|
+
elapsed=self.prev_update - self.initial_start_time,
|
|
66
|
+
remaining="?",
|
|
67
|
+
rate_fmt=(self.current_value - self.prev_value) /
|
|
68
|
+
self.delta if self.delta != 0 else 0,
|
|
69
|
+
postfix="/s",
|
|
70
|
+
unit=self.unit
|
|
71
|
+
)
|
|
72
|
+
bprint(to_print)
|
|
73
|
+
|
|
74
|
+
def update(self, amount: float = 1):
|
|
75
|
+
self.prev_value = self.current_value
|
|
76
|
+
self.current_value = min(
|
|
77
|
+
self.current_value + amount, self.total) # type:ignore
|
|
78
|
+
current_time = time.time()
|
|
79
|
+
self.delta = current_time - self.prev_update
|
|
80
|
+
self.prev_update = current_time
|
|
81
|
+
self.draw()
|
|
82
|
+
|
|
83
|
+
def _write(self, *args: str, sep: str = " ", end: str = "\n") -> None:
|
|
84
|
+
bprint.move_up()
|
|
85
|
+
bprint.clear_line()
|
|
86
|
+
if not end.endswith("\n"):
|
|
87
|
+
end += "\n"
|
|
88
|
+
bprint(sep.join(map(str, args)), end=end)
|
|
89
|
+
self.draw()
|
|
90
|
+
|
|
91
|
+
def reset(self) -> None:
|
|
92
|
+
self.current_value = self.initial_value
|
|
93
|
+
self.initial_start_time = time.time()
|
|
94
|
+
self.delta = 0
|
|
95
|
+
self.prev_value = self.initial_value
|
|
96
|
+
for _ in range(self.num_writes):
|
|
97
|
+
bprint.move_up()
|
|
98
|
+
bprint.clear_line()
|
|
99
|
+
self.num_writes = 0
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
__all__ = [
|
|
103
|
+
'AsciiProgressBar'
|
|
104
|
+
]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import time
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import Optional, Type, List, Iterable
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
except ImportError:
|
|
9
|
+
from ..mock_ import MockImportObject
|
|
10
|
+
|
|
11
|
+
tqdm = MockImportObject("`tqdm` is not installed") # type:ignore
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ProgressBar(ABC):
|
|
15
|
+
"""An interface
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
ABC (_type_): _description_
|
|
19
|
+
"""
|
|
20
|
+
DEFAULT_BAR_FORMAT = "{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt} [{elapsed}<{remaining}"
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def __init__(self, total, position: int, unit="it", bar_format: str = DEFAULT_BAR_FORMAT, **kwargs) -> None:
|
|
24
|
+
self.total = total
|
|
25
|
+
self.position = position
|
|
26
|
+
self.unit = unit
|
|
27
|
+
self.bar_format = bar_format
|
|
28
|
+
self.num_writes = 0
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def update(self, amount: float = 1) -> None:
|
|
32
|
+
"""A function to update the progress-bar's value by a positive relative amount
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def _write(self, *args: str, sep: str = " ", end: str = "\n") -> None: ...
|
|
37
|
+
|
|
38
|
+
def write(self, *args: str, sep: str = " ", end: str = "\n") -> None:
|
|
39
|
+
"""A function to write additional text with the progress bar
|
|
40
|
+
"""
|
|
41
|
+
self._write(*args, sep=sep, end=end)
|
|
42
|
+
self.num_writes += 1
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
45
|
+
def reset(self) -> None:
|
|
46
|
+
"""A function to reset the progress-bar's progress
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
ProgressBar.register(tqdm)
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
'ProgressBar',
|
|
54
|
+
]
|
|
@@ -1,51 +1,46 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
from .
|
|
3
|
-
|
|
4
|
-
if get_python_version() >= (3, 9):
|
|
5
|
-
from builtins import list as List # type:ignore
|
|
6
|
-
try:
|
|
7
|
-
from tqdm import tqdm
|
|
8
|
-
except ImportError:
|
|
9
|
-
from .mock_ import MockImportObject
|
|
10
|
-
|
|
11
|
-
tqdm = MockImportObject("`tqdm` is not installed") # type:ignore
|
|
1
|
+
from typing import Type, List, Optional
|
|
2
|
+
from .progress_bar import ProgressBar
|
|
12
3
|
|
|
13
4
|
|
|
14
5
|
class ProgressBarPool:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
6
|
+
def __init__(
|
|
7
|
+
self,
|
|
8
|
+
pbar_class: Type[ProgressBar],
|
|
9
|
+
num_of_bars: int = 1,
|
|
10
|
+
global_options: Optional[dict] = None,
|
|
11
|
+
individual_options: Optional[List[Optional[dict]]] = None
|
|
12
|
+
) -> None:
|
|
13
|
+
self.bars: List[ProgressBar] = []
|
|
22
14
|
if global_options is None:
|
|
23
15
|
global_options = {}
|
|
24
16
|
if individual_options is None:
|
|
25
17
|
individual_options = [{} for _ in range(num_of_bars)]
|
|
26
18
|
if len(individual_options) != num_of_bars:
|
|
27
|
-
raise ValueError(
|
|
19
|
+
raise ValueError(
|
|
20
|
+
"must supply the same number of options as there are bars")
|
|
28
21
|
for i in range(num_of_bars):
|
|
29
22
|
if individual_options[i] is None:
|
|
30
23
|
individual_options[i] = {}
|
|
24
|
+
max_desc_length: int = max([len(individual_options[i].get("desc", f"pbar {i}")) for i in range(num_of_bars)])
|
|
31
25
|
for i in range(num_of_bars):
|
|
32
26
|
final_options: dict = global_options.copy()
|
|
33
27
|
final_options.update(individual_options[i]) # type:ignore
|
|
34
28
|
if "desc" not in final_options:
|
|
35
29
|
final_options["desc"] = f"pbar {i}"
|
|
36
|
-
|
|
30
|
+
final_options["desc"] = final_options["desc"].ljust(max_desc_length, " ")
|
|
31
|
+
t = pbar_class(
|
|
37
32
|
position=i,
|
|
38
33
|
**final_options
|
|
39
34
|
)
|
|
40
35
|
self.bars.append(t)
|
|
41
36
|
|
|
37
|
+
def __getitem__(self, index: int) -> ProgressBar:
|
|
38
|
+
return self.bars[index]
|
|
39
|
+
|
|
42
40
|
def write(self, *args, sep=" ", end="\n") -> None:
|
|
43
|
-
"""
|
|
44
|
-
prints texts to the console **while** using tqdm progress bars
|
|
45
|
-
"""
|
|
46
41
|
self.bars[0].write(sep.join((str(a) for a in args)), end=end)
|
|
47
42
|
|
|
48
43
|
|
|
49
44
|
__all__ = [
|
|
50
|
-
"ProgressBarPool"
|
|
45
|
+
"ProgressBarPool",
|
|
51
46
|
]
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import sys, os
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from ..context_managers import TemporaryFile
|
|
4
|
+
import random
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LayeredCommand:
|
|
8
|
+
class_flush_stdout: bool = True
|
|
9
|
+
class_flush_stderr: bool = True
|
|
10
|
+
class_raise_on_fail: bool = True
|
|
11
|
+
class_verbose: bool = False
|
|
12
|
+
_class_prev_instance: Optional['LayeredCommand'] = None
|
|
13
|
+
_id: int = 0
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def prev(self):
|
|
17
|
+
return self._prev_instance
|
|
18
|
+
|
|
19
|
+
@prev.setter
|
|
20
|
+
def prev(self, value: Optional['LayeredCommand'] = None):
|
|
21
|
+
self._prev_instance = value
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
command: Optional[str] = None,
|
|
26
|
+
*,
|
|
27
|
+
prev_instance: Optional['LayeredCommand'] = None,
|
|
28
|
+
instance_flush_stdout: Optional[bool] = None,
|
|
29
|
+
instance_flush_stderr: Optional[bool] = None,
|
|
30
|
+
instance_raise_on_fail: Optional[bool] = None,
|
|
31
|
+
instance_verbose: Optional[bool] = None
|
|
32
|
+
):
|
|
33
|
+
self._command = command if command is not None else ""
|
|
34
|
+
self._instance_flush_stdout = instance_flush_stdout
|
|
35
|
+
self._instance_flush_stderr = instance_flush_stderr
|
|
36
|
+
self._instance_raise_on_fail = instance_raise_on_fail
|
|
37
|
+
self._instance_verbose = instance_verbose
|
|
38
|
+
self._prev_instance = prev_instance if prev_instance is not None else LayeredCommand._class_prev_instance
|
|
39
|
+
self._cur_class_prev_instance = LayeredCommand._class_prev_instance
|
|
40
|
+
LayeredCommand._class_prev_instance = self
|
|
41
|
+
self._executor = os.system
|
|
42
|
+
self._has_entered: bool = False
|
|
43
|
+
|
|
44
|
+
def __enter__(self):
|
|
45
|
+
self._open()
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
49
|
+
if self.prev is self._cur_class_prev_instance:
|
|
50
|
+
LayeredCommand._class_prev_instance = self.prev
|
|
51
|
+
|
|
52
|
+
def _open(self) -> None:
|
|
53
|
+
self._has_entered = True
|
|
54
|
+
|
|
55
|
+
def _build_command(self, *commands: str) -> str:
|
|
56
|
+
res = ""
|
|
57
|
+
if self.prev is not None:
|
|
58
|
+
prev = self.prev._build_command()
|
|
59
|
+
res += f"{prev} & " if prev != "" else ""
|
|
60
|
+
if self._command != "":
|
|
61
|
+
return res + " & ".join([self._command, *commands])
|
|
62
|
+
return res + " & ".join(commands)
|
|
63
|
+
|
|
64
|
+
def _error(self, predicate: bool, command: str, code: int, command_verbose: Optional[bool]) -> None:
|
|
65
|
+
if predicate:
|
|
66
|
+
verbose = self._merge_values(command_verbose, self._instance_verbose, LayeredCommand.class_verbose)
|
|
67
|
+
if verbose:
|
|
68
|
+
raise RuntimeError(f"command '{command}' failed with exit code {code}")
|
|
69
|
+
sys.exit(1)
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def _merge_values(command: Optional[bool], instance: Optional[bool], class_: bool) -> bool:
|
|
73
|
+
return command if command is not None else (instance if instance is not None else class_)
|
|
74
|
+
|
|
75
|
+
def execute(
|
|
76
|
+
self,
|
|
77
|
+
*commands: str,
|
|
78
|
+
command_flush_stdout: Optional[bool] = None,
|
|
79
|
+
command_flush_stderr: Optional[bool] = None,
|
|
80
|
+
command_raise_on_fail: Optional[bool] = None,
|
|
81
|
+
command_verbose: Optional[bool] = None
|
|
82
|
+
) -> tuple[int, list[str], list[str]]:
|
|
83
|
+
if not self._has_entered:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
"LayeredCommand must be used with a context manager. Use as: `with LayeredCommand(...) as l1:`")
|
|
86
|
+
flush_stdout = self._merge_values(command_flush_stdout, self._instance_flush_stdout, self.class_flush_stdout)
|
|
87
|
+
flush_stderr = self._merge_values(command_flush_stderr, self._instance_flush_stderr, self.class_flush_stderr)
|
|
88
|
+
raise_on_fail = self._merge_values(command_raise_on_fail, self._instance_raise_on_fail,
|
|
89
|
+
self.class_raise_on_fail)
|
|
90
|
+
|
|
91
|
+
command = self._build_command(*commands)
|
|
92
|
+
if flush_stdout and flush_stderr:
|
|
93
|
+
code = self._executor(command)
|
|
94
|
+
self._error(raise_on_fail and code != 0, command, code, command_verbose)
|
|
95
|
+
return code, [], []
|
|
96
|
+
|
|
97
|
+
letters = "abcdefghijklmnopqrstuvwxyz"
|
|
98
|
+
temp_name = "".join(random.choices(letters, k=50)) + f"_{LayeredCommand._id}"
|
|
99
|
+
stdout_path = f"./{temp_name}_stdout.log"
|
|
100
|
+
stderr_path = f"./{temp_name}_stderr.log"
|
|
101
|
+
LayeredCommand._id += 1
|
|
102
|
+
with TemporaryFile(stdout_path) as stdout:
|
|
103
|
+
with TemporaryFile(stderr_path) as stderr:
|
|
104
|
+
if not flush_stdout:
|
|
105
|
+
command += f" > {stdout_path}"
|
|
106
|
+
if not flush_stderr:
|
|
107
|
+
command += f" 2> {stderr_path}"
|
|
108
|
+
code = self._executor(command)
|
|
109
|
+
self._error(raise_on_fail and code != 0, command, code, command_verbose)
|
|
110
|
+
return code, stdout.read(), stderr.read()
|
|
111
|
+
|
|
112
|
+
def __call__(self, *args, **kwargs) -> tuple[int, list[str], list[str]]:
|
|
113
|
+
return self.execute(*args, **kwargs)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
__all__ = [
|
|
117
|
+
'LayeredCommand'
|
|
118
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: danielutils
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.83
|
|
4
4
|
Summary: A python utils library for things I find useful
|
|
5
5
|
Author-email: danielnachumdev <danielnachumdev@gmail.com>
|
|
6
6
|
License: MIT License
|
|
@@ -41,7 +41,7 @@ License-File: LICENSE
|
|
|
41
41
|
[](https://www.python.org/downloads/release/python-31011/)
|
|
42
42
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
43
43
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
44
|
-
# danielutils v=0.9.
|
|
44
|
+
# danielutils v=0.9.83
|
|
45
45
|
A utils library for things that I find useful for my coding workflow.\
|
|
46
46
|
Feel free to use and / or contribute / improve my code :)
|
|
47
47
|
|
|
@@ -17,7 +17,6 @@ danielutils/print_.py
|
|
|
17
17
|
danielutils/py.typed
|
|
18
18
|
danielutils/text.py
|
|
19
19
|
danielutils/time.py
|
|
20
|
-
danielutils/tqdm_.py
|
|
21
20
|
danielutils/versioned_imports.py
|
|
22
21
|
danielutils.egg-info/PKG-INFO
|
|
23
22
|
danielutils.egg-info/SOURCES.txt
|
|
@@ -43,6 +42,7 @@ danielutils/better_builtins/typed_builtins/tlist.py
|
|
|
43
42
|
danielutils/better_builtins/typed_builtins/tset.py
|
|
44
43
|
danielutils/better_builtins/typed_builtins/ttuple.py
|
|
45
44
|
danielutils/context_managers/__init__.py
|
|
45
|
+
danielutils/context_managers/attr_context.py
|
|
46
46
|
danielutils/context_managers/temporary_file.py
|
|
47
47
|
danielutils/conversions/__init__.py
|
|
48
48
|
danielutils/conversions/main_conversions.py
|
|
@@ -96,6 +96,7 @@ danielutils/functions/flatten.py
|
|
|
96
96
|
danielutils/functions/isoftype.py
|
|
97
97
|
danielutils/functions/isoneof.py
|
|
98
98
|
danielutils/functions/multiloop.py
|
|
99
|
+
danielutils/functions/parallel_for.py
|
|
99
100
|
danielutils/functions/powerset.py
|
|
100
101
|
danielutils/functions/subseteq.py
|
|
101
102
|
danielutils/functions/types_subseteq.py
|
|
@@ -108,8 +109,6 @@ danielutils/math_/constants.py
|
|
|
108
109
|
danielutils/math_/functions.py
|
|
109
110
|
danielutils/math_/math_print.py
|
|
110
111
|
danielutils/math_/math_symbols.py
|
|
111
|
-
danielutils/math_/polynomial/__init__.py
|
|
112
|
-
danielutils/math_/polynomial/polinomial.py
|
|
113
112
|
danielutils/metaclasses/__init__.py
|
|
114
113
|
danielutils/metaclasses/atomic_class_meta.py
|
|
115
114
|
danielutils/metaclasses/implicit_data_deleter_meta.py
|
|
@@ -119,6 +118,10 @@ danielutils/metaclasses/overload_meta.py
|
|
|
119
118
|
danielutils/mock_/__init__.py
|
|
120
119
|
danielutils/mock_/mock_database.py
|
|
121
120
|
danielutils/mock_/mock_module.py
|
|
121
|
+
danielutils/progress_bar/__init__.py
|
|
122
|
+
danielutils/progress_bar/ascii_progress_bar.py
|
|
123
|
+
danielutils/progress_bar/progress_bar.py
|
|
124
|
+
danielutils/progress_bar/progress_bar_pool.py
|
|
122
125
|
danielutils/protocols/__init__.py
|
|
123
126
|
danielutils/protocols/dictable.py
|
|
124
127
|
danielutils/protocols/evaluable.py
|