danielutils 1.0.46__tar.gz → 1.0.50__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-1.0.46/danielutils.egg-info → danielutils-1.0.50}/PKG-INFO +3 -4
- {danielutils-1.0.46 → danielutils-1.0.50}/README.md +1 -1
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_initializer.py +1 -1
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/logger.py +1 -1
- danielutils-1.0.50/danielutils/reflection/__init__.py +6 -0
- danielutils-1.0.50/danielutils/reflection/info_classes/__init__.py +6 -0
- {danielutils-1.0.46/danielutils/reflection → danielutils-1.0.50/danielutils/reflection/info_classes}/argument_info.py +8 -2
- {danielutils-1.0.46/danielutils/reflection → danielutils-1.0.50/danielutils/reflection/info_classes}/class_info.py +8 -4
- danielutils-1.0.50/danielutils/reflection/info_classes/file_info.py +267 -0
- {danielutils-1.0.46/danielutils/reflection → danielutils-1.0.50/danielutils/reflection/info_classes}/function_info.py +10 -3
- danielutils-1.0.50/danielutils/reflection/info_classes/import_info.py +100 -0
- {danielutils-1.0.46 → danielutils-1.0.50/danielutils.egg-info}/PKG-INFO +3 -4
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils.egg-info/SOURCES.txt +7 -4
- {danielutils-1.0.46 → danielutils-1.0.50}/pyproject.toml +1 -1
- danielutils-1.0.46/danielutils/reflection/__init__.py +0 -53
- {danielutils-1.0.46 → danielutils-1.0.50}/LICENSE +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/MANIFEST.in +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_definitions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_exceptions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_factory.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_models.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/dependencies.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/implementations/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/implementations/in_memory_database.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/implementations/persistent_in_memory_database.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/implementations/redis_database.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/implementations/sqlite_database.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/multiprogramming/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/multiprogramming/multi_id.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/multiprogramming/worker.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/multiprogramming/worker_pool.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/repl.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/aliases.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/async_cmd.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/async_layered_command.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/async_retry_executor.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/async_worker_pool.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/time_strategy.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/async_/utils.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/counter.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/frange.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/factory.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/tdict.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/tlist.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/tset.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/better_builtins/typed_builtins/ttuple.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/colors.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/attr_context.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/multi_context.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/optional_context.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/state_context.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/context_managers/temporary_file.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/convenience.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/conversions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/conversions/main_conversions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/conversions/specialized_conversions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/conversions/specialized_conversions/to_hex.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/conversions/specialized_conversions/to_int.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/custom_types.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/algorithms.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/comparer.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/default_dict.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/functions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/graph/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/graph/binary_node.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/graph/graph.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/graph/multinode.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/graph/node.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/heap/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/heap/heap.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/heap/max_heap.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/heap/min_heap.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/queue/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/queue/atomic_queue.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/queue/priority_queue.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/queue/queue.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/stack.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/trees/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/trees/binary_syntax_tree.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/data_structures/trees/binary_tree.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/date.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/date_time.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/atomic.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/attach.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/chain_decorators.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/decorate_conditionally.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/delay_call.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/deprecate.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/final.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/limit_recursion.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/memo.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/normalize_decorator.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/overload.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/partially_implemented.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/processify.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/property.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/singleton.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/threadify.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/timeout.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/total_ordering.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/decorators/validate.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/exceptions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/file_specifications/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/areoneof.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/check_foreach.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/factorial.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/flatten.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/foreach.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/isoftype.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/isoneof.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/multiloop.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/parallel_for.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/partition.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/powerset.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/subseteq.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/functions/types_subseteq.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/generators/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/generators/conditional_generator.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/generators/generator_from_stream.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/generators/join_generators.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/internet.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/io_.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/java/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/java/interfaces/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/java/interfaces/comparable.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/java/java_interface.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/builtin_impls/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/builtin_impls/file_logger.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/builtin_impls/print_logger.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/log_level.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/logging_/logger_strategy_impl_base.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/lombok/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/lombok/builder.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/math_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/math_/constants.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/math_/functions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/math_/math_print.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/math_/math_symbols.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/atomic_class_meta.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/implicit_data_deleter_meta.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/instance_cache_meta.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/interface.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/metaclasses/overload_meta.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/mock_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/mock_/mock_module.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/path.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/print_.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/progress_bar/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/progress_bar/ascii_progress_bar.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/progress_bar/progress_bar.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/progress_bar/progress_bar_pool.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/protocols/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/protocols/dictable.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/protocols/evaluable.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/protocols/serializable.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/py.typed +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/random_.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/class_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/class_/class_reflection.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/file/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/file/file_reflection.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/function/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/function/function_reflections.py +0 -0
- {danielutils-1.0.46/danielutils/reflection → danielutils-1.0.50/danielutils/reflection/info_classes}/decoration_info.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/callstack.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/get_traceback.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/interpreter.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/is_debugging.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/os_.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/packages.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/python_version.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/signals.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/interpreter/tracer.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/module/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/module/module_reflections.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/reflection/module/package_reflection.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/constant_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/exponential_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/functional_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/linear_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/multiplicative_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategies/no_backoff.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/backoff_strategy.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/retry_executor/retry_executor.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/snippets/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/snippets/try_get.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/independent.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/layered_command.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/windows/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/windows/utils/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/windows/utils/filetime.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/windows/win32_ctime.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/system/windows/windows.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/testing/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/testing/unittest_/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/testing/unittest_/always_teardown_testcase.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/testing/unittest_/auto_cwd_testcase.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/text.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/time.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/discreate_finite_automaton.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/languages/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/languages/language.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/languages/sat.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/computability_and_complexity/turing_machine.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/databases/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/databases/all.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/encoding.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossless/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossless/huffman.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossless/lossless_encoding.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossless/lzw.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossless/run_length.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossy/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/encoding/lossy/lossy_encoding.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/gaussian.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/gradient.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/hough.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/laplacian.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/image_proccesing/tansformations/transformation.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/linear_algebra/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/linear_algebra/matrix.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/machine_learning/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/machine_learning/activation_functions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/machine_learning/activation_functions/activation_function.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/machine_learning/activation_functions/relu.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/machine_learning/neuron.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/oop/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/oop/observer.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/oop/strategy.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/conditional_variable.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/continuous/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/bernoulli.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/binomial.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/conditional_from_discrete_probability_func.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/discrete.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/geometric.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/poisson.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/conditional_variable/discrete/uniform.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/distributions.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/expressions/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/expressions/accumulation_expression.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/expressions/probability_expression.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/funcs/__init__.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/funcs/covariance.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/funcs/expected_value.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/funcs/probability_function.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/funcs/variance.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/operator.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/protocols.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/supp.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/university/probability/transformation.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils/versioned_imports.py +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils.egg-info/dependency_links.txt +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/danielutils.egg-info/top_level.txt +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/setup.cfg +0 -0
- {danielutils-1.0.46 → danielutils-1.0.50}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: danielutils
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.50
|
|
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
|
|
@@ -33,7 +33,6 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
33
33
|
Requires-Python: >=3.8.0
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
|
-
Dynamic: license-file
|
|
37
36
|
|
|
38
37
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/python-package.yml)
|
|
39
38
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/pylint.yml)
|
|
@@ -41,7 +40,7 @@ Dynamic: license-file
|
|
|
41
40
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
42
41
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
43
42
|
|
|
44
|
-
# danielutils v1.0.
|
|
43
|
+
# danielutils v1.0.50
|
|
45
44
|
|
|
46
45
|
A comprehensive Python utilities library designed to enhance your development workflow with powerful tools for type safety, async programming, database operations, and much more.
|
|
47
46
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
5
5
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
6
6
|
|
|
7
|
-
# danielutils v1.0.
|
|
7
|
+
# danielutils v1.0.50
|
|
8
8
|
|
|
9
9
|
A comprehensive Python utilities library designed to enhance your development workflow with powerful tools for type safety, async programming, database operations, and much more.
|
|
10
10
|
|
{danielutils-1.0.46 → danielutils-1.0.50}/danielutils/abstractions/db/database_initializer.py
RENAMED
|
@@ -238,7 +238,7 @@ class DatabaseInitializer(ABC):
|
|
|
238
238
|
await db.create_table(expected_schema)
|
|
239
239
|
else:
|
|
240
240
|
logger.info(f"Validating table '{table_name}'")
|
|
241
|
-
if not validate_schema(db, table_name, expected_schema):
|
|
241
|
+
if not await validate_schema(db, table_name, expected_schema):
|
|
242
242
|
raise ValueError(
|
|
243
243
|
f"Schema validation failed for table '{table_name}'. "
|
|
244
244
|
"Please check the logs for details."
|
|
@@ -70,7 +70,7 @@ class _LoggerImpl:
|
|
|
70
70
|
|
|
71
71
|
class Logger:
|
|
72
72
|
@classmethod
|
|
73
|
-
def __init_subclass__(cls, **kwargs):
|
|
73
|
+
def __init_subclass__(cls, **kwargs) -> None:
|
|
74
74
|
cls._logger = _LoggerImpl(cls)
|
|
75
75
|
cls._registered_loggers: List[LoggerStrategyImplBase] = []
|
|
76
76
|
cls.init_subscribers()
|
|
@@ -62,7 +62,7 @@ class ArgumentInfo:
|
|
|
62
62
|
if self.default is not None:
|
|
63
63
|
res += f", default={self.default}"
|
|
64
64
|
if self.is_parameterized:
|
|
65
|
-
res+=f", parameters={self.parameters}"
|
|
65
|
+
res += f", parameters={self.parameters}"
|
|
66
66
|
return res + ")"
|
|
67
67
|
|
|
68
68
|
def __str__(self) -> str:
|
|
@@ -75,8 +75,11 @@ class ArgumentInfo:
|
|
|
75
75
|
raise ValueError(f"Invalid argument info string: {string}")
|
|
76
76
|
|
|
77
77
|
kwargs, args, kwarg_only, pname, parameters, name, type, default_value = m.groups()
|
|
78
|
+
type = None if type is None else type.strip()
|
|
79
|
+
default_value = None if default_value is None else default_value.strip()
|
|
78
80
|
return ArgumentInfo(
|
|
79
|
-
name=name or pname
|
|
81
|
+
name=name or pname or (args.strip("*") if args else None) or (
|
|
82
|
+
kwargs.strip("*") if kwargs else None) or (kwarg_only.strip("/") if kwarg_only else None) or None,
|
|
80
83
|
type=type,
|
|
81
84
|
default=default_value,
|
|
82
85
|
is_kwargs=kwargs is not None,
|
|
@@ -90,6 +93,9 @@ class ArgumentInfo:
|
|
|
90
93
|
if string is None:
|
|
91
94
|
return []
|
|
92
95
|
string = string.strip()
|
|
96
|
+
if not string:
|
|
97
|
+
return []
|
|
98
|
+
string = string.strip()
|
|
93
99
|
indices = [-1]
|
|
94
100
|
stack: List[str] = []
|
|
95
101
|
for i, c in enumerate(string):
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
import json
|
|
3
3
|
import re
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import List, Iterable, Type, TypeVar, Generic, get_origin
|
|
5
5
|
from .function_info import FunctionInfo
|
|
6
6
|
from .decoration_info import DecorationInfo
|
|
7
7
|
from .argument_info import ArgumentInfo
|
|
8
|
-
from
|
|
8
|
+
from ...functions import isoftype
|
|
9
9
|
|
|
10
10
|
T = TypeVar("T")
|
|
11
11
|
|
|
@@ -62,10 +62,14 @@ class ClassInfo:
|
|
|
62
62
|
elif inspect.isdatadescriptor(obj):
|
|
63
63
|
inspect.getsource(obj.fget) # type:ignore
|
|
64
64
|
else:
|
|
65
|
-
|
|
65
|
+
continue
|
|
66
66
|
except:
|
|
67
67
|
continue
|
|
68
|
-
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
self._functions.append(FunctionInfo(obj, self._cls)) # type: ignore
|
|
71
|
+
except Exception as e:
|
|
72
|
+
raise Exception(f"Error parsing function '{attr}' of class '{self._name}': {e}", e) from e
|
|
69
73
|
|
|
70
74
|
def __str__(self) -> str:
|
|
71
75
|
body = json.dumps({
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import tokenize
|
|
3
|
+
import io
|
|
4
|
+
import importlib.util
|
|
5
|
+
import inspect
|
|
6
|
+
from collections import Counter
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import List, Set, Dict, Any
|
|
9
|
+
|
|
10
|
+
from .import_info import ImportInfo
|
|
11
|
+
from .class_info import ClassInfo
|
|
12
|
+
from .function_info import FunctionInfo
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FileInfo:
|
|
16
|
+
"""
|
|
17
|
+
A class for static analysis of a Python source file.
|
|
18
|
+
|
|
19
|
+
Analysis includes:
|
|
20
|
+
• Tokenization: token count and token frequency distribution.
|
|
21
|
+
• Extraction of comments.
|
|
22
|
+
• Listing names of classes and functions.
|
|
23
|
+
• Identification of import statements, now represented by ImportInfo objects.
|
|
24
|
+
• Basic import usage analysis (which imports appear to be used).
|
|
25
|
+
• (Dynamic) loading of the file to create detailed ClassInfo and FunctionInfo objects.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, file_path: str) -> None:
|
|
29
|
+
self.file_path = str(Path(file_path).resolve())
|
|
30
|
+
self._content: str = self._read_file()
|
|
31
|
+
self._tree: ast.AST = self._parse_content()
|
|
32
|
+
self._tokens: List[tokenize.TokenInfo] = None
|
|
33
|
+
|
|
34
|
+
def _read_file(self) -> str:
|
|
35
|
+
"""Reads and returns the file content as UTF-8 text."""
|
|
36
|
+
try:
|
|
37
|
+
with open(self.file_path, "r", encoding="utf-8") as f:
|
|
38
|
+
return f.read()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
raise Exception(f"Error reading {self.file_path}: {e}")
|
|
41
|
+
|
|
42
|
+
def _parse_content(self) -> ast.AST:
|
|
43
|
+
"""Parses the file content into an AST."""
|
|
44
|
+
try:
|
|
45
|
+
return ast.parse(self._content, filename=self.file_path)
|
|
46
|
+
except Exception as e:
|
|
47
|
+
raise Exception(f"Error parsing {self.file_path}: {e}")
|
|
48
|
+
|
|
49
|
+
def _tokenize(self) -> None:
|
|
50
|
+
"""Tokenizes the file content using tokenize.tokenize()."""
|
|
51
|
+
self._tokens = []
|
|
52
|
+
stream = io.BytesIO(self._content.encode("utf-8"))
|
|
53
|
+
try:
|
|
54
|
+
for tok in tokenize.tokenize(stream.readline):
|
|
55
|
+
if tok.type == tokenize.ENCODING:
|
|
56
|
+
continue
|
|
57
|
+
self._tokens.append(tok)
|
|
58
|
+
except tokenize.TokenError as te:
|
|
59
|
+
print(f"Tokenize error: {te}")
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def tokens(self) -> List[tokenize.TokenInfo]:
|
|
63
|
+
"""Returns the list of tokens from the file."""
|
|
64
|
+
if self._tokens is None:
|
|
65
|
+
self._tokenize()
|
|
66
|
+
return self._tokens
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def token_count(self) -> int:
|
|
70
|
+
"""Total number of tokens in the file."""
|
|
71
|
+
return len(self.tokens)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def token_distribution(self) -> Dict[str, int]:
|
|
75
|
+
"""A dictionary mapping token strings to their frequency."""
|
|
76
|
+
return dict(Counter(tok.string for tok in self.tokens))
|
|
77
|
+
|
|
78
|
+
@property
|
|
79
|
+
def comments(self) -> List[str]:
|
|
80
|
+
"""A list of all comment strings in the file."""
|
|
81
|
+
return [tok.string for tok in self.tokens if tok.type == tokenize.COMMENT]
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def class_names(self) -> List[str]:
|
|
85
|
+
"""Names of all classes defined in the file."""
|
|
86
|
+
return [node.name for node in ast.walk(self._tree) if isinstance(node, ast.ClassDef)]
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def function_names(self) -> List[str]:
|
|
90
|
+
"""Names of all functions (including async) defined in the file."""
|
|
91
|
+
return [
|
|
92
|
+
node.name
|
|
93
|
+
for node in ast.walk(self._tree)
|
|
94
|
+
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def imports(self) -> List[Any]:
|
|
99
|
+
"""
|
|
100
|
+
Returns a list of ImportInfo objects representing all import statements.
|
|
101
|
+
Each AST node of type ast.Import or ast.ImportFrom is transformed via
|
|
102
|
+
ImportInfo.from_ast().
|
|
103
|
+
"""
|
|
104
|
+
results = []
|
|
105
|
+
if ImportInfo is None:
|
|
106
|
+
return results
|
|
107
|
+
for node in ast.walk(self._tree):
|
|
108
|
+
if isinstance(node, (ast.Import, ast.ImportFrom)):
|
|
109
|
+
results.extend(ImportInfo.from_ast(node))
|
|
110
|
+
return results
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def used_names(self) -> Set[str]:
|
|
114
|
+
"""
|
|
115
|
+
A set of all names (identifiers) used in the file,
|
|
116
|
+
based on ast.Name nodes.
|
|
117
|
+
"""
|
|
118
|
+
names = set()
|
|
119
|
+
for node in ast.walk(self._tree):
|
|
120
|
+
if isinstance(node, ast.Name):
|
|
121
|
+
names.add(node.id)
|
|
122
|
+
return names
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def import_usage(self) -> Dict[str, List[Any]]:
|
|
126
|
+
"""
|
|
127
|
+
Returns a dictionary with two keys:
|
|
128
|
+
• 'used' : list of ImportInfo objects for which the alias is found in the file,
|
|
129
|
+
• 'unused' : list of ImportInfo objects whose alias is never referenced.
|
|
130
|
+
Wildcard imports (alias "*") are assumed to be used.
|
|
131
|
+
"""
|
|
132
|
+
used, unused = [], []
|
|
133
|
+
for imp in self.imports:
|
|
134
|
+
if imp.alias == "*" or imp.alias is None or imp.alias in self.used_names:
|
|
135
|
+
used.append(imp)
|
|
136
|
+
else:
|
|
137
|
+
unused.append(imp)
|
|
138
|
+
return {"used": used, "unused": unused}
|
|
139
|
+
|
|
140
|
+
def _load_module(self) -> Any:
|
|
141
|
+
"""
|
|
142
|
+
Dynamically loads the file as a module and returns the module object.
|
|
143
|
+
Returns None if the loading fails.
|
|
144
|
+
|
|
145
|
+
Warning: This executes the file's top-level code.
|
|
146
|
+
"""
|
|
147
|
+
try:
|
|
148
|
+
module_name = "_temp_module_" + str(abs(hash(self.file_path)))
|
|
149
|
+
spec = importlib.util.spec_from_file_location(module_name, self.file_path)
|
|
150
|
+
module = importlib.util.module_from_spec(spec)
|
|
151
|
+
spec.loader.exec_module(module)
|
|
152
|
+
return module
|
|
153
|
+
except Exception as e:
|
|
154
|
+
print(f"Error loading module from {self.file_path}: {e}")
|
|
155
|
+
return None
|
|
156
|
+
|
|
157
|
+
def get_dynamic_class_info(self) -> List[Any]:
|
|
158
|
+
"""
|
|
159
|
+
Dynamically imports the file as a module and returns a list of ClassInfo objects,
|
|
160
|
+
one per class defined at module level.
|
|
161
|
+
|
|
162
|
+
Warning: This executes the file's top-level code.
|
|
163
|
+
"""
|
|
164
|
+
if ClassInfo is None:
|
|
165
|
+
print("ClassInfo unavailable; skipping dynamic class analysis.")
|
|
166
|
+
return []
|
|
167
|
+
module = self._load_module()
|
|
168
|
+
if module is None:
|
|
169
|
+
return []
|
|
170
|
+
infos = []
|
|
171
|
+
for name, obj in inspect.getmembers(module, inspect.isclass):
|
|
172
|
+
if inspect.getmodule(obj) == module:
|
|
173
|
+
try:
|
|
174
|
+
infos.append(ClassInfo(obj))
|
|
175
|
+
except Exception as e:
|
|
176
|
+
print(f"Error processing class {name}: {e}")
|
|
177
|
+
return infos
|
|
178
|
+
|
|
179
|
+
def get_dynamic_function_info(self) -> List[Any]:
|
|
180
|
+
"""
|
|
181
|
+
Dynamically imports the file as a module and returns a list of FunctionInfo objects,
|
|
182
|
+
one per function defined at module level.
|
|
183
|
+
|
|
184
|
+
Warning: This executes the file's top-level code.
|
|
185
|
+
"""
|
|
186
|
+
if FunctionInfo is None:
|
|
187
|
+
print("FunctionInfo unavailable; skipping dynamic function analysis.")
|
|
188
|
+
return []
|
|
189
|
+
module = self._load_module()
|
|
190
|
+
if module is None:
|
|
191
|
+
return []
|
|
192
|
+
infos = []
|
|
193
|
+
for name, obj in inspect.getmembers(module, inspect.isfunction):
|
|
194
|
+
if inspect.getmodule(obj) == module:
|
|
195
|
+
try:
|
|
196
|
+
infos.append(FunctionInfo(obj))
|
|
197
|
+
except Exception as e:
|
|
198
|
+
print(f"Error processing function {name}: {e}")
|
|
199
|
+
return infos
|
|
200
|
+
|
|
201
|
+
def print_summary(self) -> None:
|
|
202
|
+
"""Prints a detailed summary of all analyses of the file."""
|
|
203
|
+
print(f"===== Analysis of {self.file_path} =====")
|
|
204
|
+
|
|
205
|
+
print(f"\nToken Count: {self.token_count}")
|
|
206
|
+
print("\nToken Distribution (Top 10):")
|
|
207
|
+
for token, count in sorted(self.token_distribution.items(), key=lambda x: -x[1])[:10]:
|
|
208
|
+
print(f" {repr(token)}: {count}")
|
|
209
|
+
|
|
210
|
+
print("\nComments Found:")
|
|
211
|
+
if self.comments:
|
|
212
|
+
for comment in self.comments:
|
|
213
|
+
print(" ", comment)
|
|
214
|
+
else:
|
|
215
|
+
print(" (None)")
|
|
216
|
+
|
|
217
|
+
print("\nClasses Defined:")
|
|
218
|
+
if self.class_names:
|
|
219
|
+
for cls in self.class_names:
|
|
220
|
+
print(" ", cls)
|
|
221
|
+
else:
|
|
222
|
+
print(" (None)")
|
|
223
|
+
|
|
224
|
+
print("\nFunctions Defined:")
|
|
225
|
+
if self.function_names:
|
|
226
|
+
for fn in self.function_names:
|
|
227
|
+
print(" ", fn)
|
|
228
|
+
else:
|
|
229
|
+
print(" (None)")
|
|
230
|
+
|
|
231
|
+
print("\nImports Found:")
|
|
232
|
+
for imp in self.imports:
|
|
233
|
+
print(f" {imp.alias} from {imp.module} ({imp.kind})")
|
|
234
|
+
|
|
235
|
+
usage = self.import_usage
|
|
236
|
+
print("\nUsed Imports:")
|
|
237
|
+
for imp in usage["used"]:
|
|
238
|
+
print(f" {imp.alias} from {imp.module} ({imp.kind})")
|
|
239
|
+
|
|
240
|
+
print("\nUnused Imports:")
|
|
241
|
+
if usage["unused"]:
|
|
242
|
+
for imp in usage["unused"]:
|
|
243
|
+
print(f" {imp.alias} from {imp.module} ({imp.kind})")
|
|
244
|
+
else:
|
|
245
|
+
print(" (None)")
|
|
246
|
+
|
|
247
|
+
print("\nDetailed Class Info:")
|
|
248
|
+
dynamic_class_infos = self.get_dynamic_class_info()
|
|
249
|
+
if dynamic_class_infos:
|
|
250
|
+
for info in dynamic_class_infos:
|
|
251
|
+
print(info)
|
|
252
|
+
else:
|
|
253
|
+
print(" (None)")
|
|
254
|
+
|
|
255
|
+
print("\nDetailed Function Info:")
|
|
256
|
+
dynamic_function_infos = self.get_dynamic_function_info()
|
|
257
|
+
if dynamic_function_infos:
|
|
258
|
+
for info in dynamic_function_infos:
|
|
259
|
+
print(info)
|
|
260
|
+
else:
|
|
261
|
+
print(" (None)")
|
|
262
|
+
print("========================================")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
__all__ = [
|
|
266
|
+
"FileInfo"
|
|
267
|
+
]
|
|
@@ -8,7 +8,7 @@ from .argument_info import ArgumentInfo
|
|
|
8
8
|
|
|
9
9
|
class FunctionInfo:
|
|
10
10
|
FUNCTION_DEFINITION_REGEX: re.Pattern = re.compile(
|
|
11
|
-
r"(?P<decorators>[\s\S]
|
|
11
|
+
r"(?P<decorators>(?:@[\s\S]+?)+?)?\s*(?P<async>async )?def (?P<name>\w[\w\d]*)\s*\((?P<arguments>[\s\S]+?)?\)\s*(?:\s*\-\>\s*(?P<return_type>[\s\S]+?)\s*)?:(?P<body>[\s\S]+)",
|
|
12
12
|
re.MULTILINE)
|
|
13
13
|
|
|
14
14
|
def __init__(self, func: Callable, owner: Type) -> None:
|
|
@@ -18,7 +18,7 @@ class FunctionInfo:
|
|
|
18
18
|
self._is_property = True
|
|
19
19
|
else:
|
|
20
20
|
inspect.getsource(func)
|
|
21
|
-
self._is_property = False
|
|
21
|
+
self._is_property = False # type: ignore
|
|
22
22
|
except:
|
|
23
23
|
raise TypeError(f"'{func.__name__}' is not a user defined function")
|
|
24
24
|
self._func = func
|
|
@@ -34,10 +34,13 @@ class FunctionInfo:
|
|
|
34
34
|
m = FunctionInfo.FUNCTION_DEFINITION_REGEX.match(code)
|
|
35
35
|
if m is None:
|
|
36
36
|
raise ValueError("Invalid function source code")
|
|
37
|
-
decorators, name, arguments, return_type, body = m.groups()
|
|
37
|
+
decorators, async_, name, arguments, return_type, body = m.groups()
|
|
38
38
|
if decorators is not None:
|
|
39
39
|
for substr in decorators.strip().splitlines():
|
|
40
40
|
self._decorators.append(DecorationInfo.from_str(substr.strip()))
|
|
41
|
+
|
|
42
|
+
self._is_async = async_ is not None
|
|
43
|
+
|
|
41
44
|
self._name = name
|
|
42
45
|
if arguments is not None:
|
|
43
46
|
self._arguments = ArgumentInfo.from_str(arguments)
|
|
@@ -57,6 +60,10 @@ class FunctionInfo:
|
|
|
57
60
|
def __repr__(self) -> str:
|
|
58
61
|
return f"{self.__class__.__name__}(name=\"{self.name}\")"
|
|
59
62
|
|
|
63
|
+
@property
|
|
64
|
+
def is_async(self) -> bool:
|
|
65
|
+
return self._is_async
|
|
66
|
+
|
|
60
67
|
@property
|
|
61
68
|
def is_inherited(self) -> bool:
|
|
62
69
|
return self._func in set(self._owner.__dict__.keys())
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from typing import List, Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ImportInfo:
|
|
6
|
+
"""
|
|
7
|
+
A class that encapsulates information about a single import statement element.
|
|
8
|
+
|
|
9
|
+
Depending on how the import appears in the source code, this may represent:
|
|
10
|
+
- a regular import (e.g., "import os" or "import os.path as osp"),
|
|
11
|
+
- a from-import (e.g., "from sys import version_info"), or
|
|
12
|
+
- a wildcard import (e.g., "from math import *").
|
|
13
|
+
|
|
14
|
+
The exposed properties are:
|
|
15
|
+
• alias: The accessible name in the file.
|
|
16
|
+
• module: The imported module or package.
|
|
17
|
+
• kind: A short string indicating the type. It will be one of:
|
|
18
|
+
"import", "from_import", or "from_import_all".
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def __init__(self, alias: str, module: str, kind: str) -> None:
|
|
22
|
+
"""
|
|
23
|
+
:param alias: The name used in the current file. For example, in
|
|
24
|
+
"import os as myos", the alias is 'myos'; if no alias is given,
|
|
25
|
+
a default is provided (e.g., the top-level module name).
|
|
26
|
+
:param module: The full module or package name (e.g., "os", or "os.path").
|
|
27
|
+
:param kind: A descriptor of the import kind: "import", "from_import", or "from_import_all".
|
|
28
|
+
"""
|
|
29
|
+
self._alias = alias
|
|
30
|
+
self._module = module
|
|
31
|
+
self._kind = kind
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def alias(self) -> str:
|
|
35
|
+
"""Returns the alias (or name) used for the import in the file."""
|
|
36
|
+
return self._alias
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def module(self) -> str:
|
|
40
|
+
"""Returns the module or package name as imported."""
|
|
41
|
+
return self._module
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def kind(self) -> str:
|
|
45
|
+
"""
|
|
46
|
+
Returns the type of import:
|
|
47
|
+
- "import" for a standard import statement,
|
|
48
|
+
- "from_import" for a 'from X import Y' statement,
|
|
49
|
+
- "from_import_all" for a wildcard import (e.g., 'from X import *').
|
|
50
|
+
"""
|
|
51
|
+
return self._kind
|
|
52
|
+
|
|
53
|
+
def to_dict(self) -> dict:
|
|
54
|
+
"""Returns a dictionary representation of the import information."""
|
|
55
|
+
return {"alias": self.alias, "module": self.module, "kind": self.kind}
|
|
56
|
+
|
|
57
|
+
def __str__(self) -> str:
|
|
58
|
+
return f"ImportInfo(alias={self.alias!r}, module={self.module!r}, kind={self.kind!r})"
|
|
59
|
+
|
|
60
|
+
def __repr__(self) -> str:
|
|
61
|
+
return self.__str__()
|
|
62
|
+
|
|
63
|
+
@classmethod
|
|
64
|
+
def from_ast(cls, node: Union[ast.Import, ast.ImportFrom]) -> List["ImportInfo"]:
|
|
65
|
+
"""
|
|
66
|
+
Given an AST node of type ast.Import or ast.ImportFrom, returns a list
|
|
67
|
+
of ImportInfo instances representing each imported alias in that node.
|
|
68
|
+
|
|
69
|
+
For an ast.Import node:
|
|
70
|
+
• Each alias in node.names is processed.
|
|
71
|
+
• If an alias is not provided (using the as keyword), then the first
|
|
72
|
+
part of the module name (split by '.') is used as the alias.
|
|
73
|
+
|
|
74
|
+
For an ast.ImportFrom node:
|
|
75
|
+
• The module attribute (which can be None for relative imports) is used.
|
|
76
|
+
• Each alias is processed. If alias.name equals "*", the import is considered a wildcard.
|
|
77
|
+
|
|
78
|
+
:param node: An ast.Import or ast.ImportFrom node.
|
|
79
|
+
:return: A list of ImportInfo objects.
|
|
80
|
+
"""
|
|
81
|
+
imports = []
|
|
82
|
+
if isinstance(node, ast.Import):
|
|
83
|
+
for alias in node.names:
|
|
84
|
+
# Use asname if available; otherwise use the top-level name.
|
|
85
|
+
local_alias = alias.asname if alias.asname else alias.name.split(".")[0]
|
|
86
|
+
imports.append(cls(local_alias, alias.name, "import"))
|
|
87
|
+
elif isinstance(node, ast.ImportFrom):
|
|
88
|
+
modname = node.module if node.module is not None else ""
|
|
89
|
+
for alias in node.names:
|
|
90
|
+
if alias.name == "*":
|
|
91
|
+
imports.append(cls("*", modname, "from_import_all"))
|
|
92
|
+
else:
|
|
93
|
+
local_alias = alias.asname if alias.asname else alias.name
|
|
94
|
+
imports.append(cls(local_alias, modname, "from_import"))
|
|
95
|
+
return imports
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
__all__ = [
|
|
99
|
+
"ImportInfo"
|
|
100
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: danielutils
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.50
|
|
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
|
|
@@ -33,7 +33,6 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
|
33
33
|
Requires-Python: >=3.8.0
|
|
34
34
|
Description-Content-Type: text/markdown
|
|
35
35
|
License-File: LICENSE
|
|
36
|
-
Dynamic: license-file
|
|
37
36
|
|
|
38
37
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/python-package.yml)
|
|
39
38
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/pylint.yml)
|
|
@@ -41,7 +40,7 @@ Dynamic: license-file
|
|
|
41
40
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/gitleaks.yml)
|
|
42
41
|
[](https://github.com/danielnachumdev/danielutils/actions/workflows/github-code-scanning/codeql)
|
|
43
42
|
|
|
44
|
-
# danielutils v1.0.
|
|
43
|
+
# danielutils v1.0.50
|
|
45
44
|
|
|
46
45
|
A comprehensive Python utilities library designed to enhance your development workflow with powerful tools for type safety, async programming, database operations, and much more.
|
|
47
46
|
|
|
@@ -168,16 +168,19 @@ danielutils/protocols/dictable.py
|
|
|
168
168
|
danielutils/protocols/evaluable.py
|
|
169
169
|
danielutils/protocols/serializable.py
|
|
170
170
|
danielutils/reflection/__init__.py
|
|
171
|
-
danielutils/reflection/argument_info.py
|
|
172
|
-
danielutils/reflection/class_info.py
|
|
173
|
-
danielutils/reflection/decoration_info.py
|
|
174
|
-
danielutils/reflection/function_info.py
|
|
175
171
|
danielutils/reflection/class_/__init__.py
|
|
176
172
|
danielutils/reflection/class_/class_reflection.py
|
|
177
173
|
danielutils/reflection/file/__init__.py
|
|
178
174
|
danielutils/reflection/file/file_reflection.py
|
|
179
175
|
danielutils/reflection/function/__init__.py
|
|
180
176
|
danielutils/reflection/function/function_reflections.py
|
|
177
|
+
danielutils/reflection/info_classes/__init__.py
|
|
178
|
+
danielutils/reflection/info_classes/argument_info.py
|
|
179
|
+
danielutils/reflection/info_classes/class_info.py
|
|
180
|
+
danielutils/reflection/info_classes/decoration_info.py
|
|
181
|
+
danielutils/reflection/info_classes/file_info.py
|
|
182
|
+
danielutils/reflection/info_classes/function_info.py
|
|
183
|
+
danielutils/reflection/info_classes/import_info.py
|
|
181
184
|
danielutils/reflection/interpreter/__init__.py
|
|
182
185
|
danielutils/reflection/interpreter/callstack.py
|
|
183
186
|
danielutils/reflection/interpreter/get_traceback.py
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
from .interpreter import * # this has to be first, the order matters!
|
|
2
|
-
from .file import *
|
|
3
|
-
from .function import *
|
|
4
|
-
from .class_ import *
|
|
5
|
-
from .module import *
|
|
6
|
-
from .argument_info import *
|
|
7
|
-
from .decoration_info import *
|
|
8
|
-
from .function_info import *
|
|
9
|
-
from .class_info import *
|
|
10
|
-
# def get_class(module_name: str, class_name: str) -> type:
|
|
11
|
-
# """dynammically loads the module and returns the class from this file
|
|
12
|
-
|
|
13
|
-
# Args:
|
|
14
|
-
# module_name (str): name of python module, (typically a file name without extention)
|
|
15
|
-
# class_name (str): the name of the wanted class
|
|
16
|
-
|
|
17
|
-
# Returns:
|
|
18
|
-
# type (type): The class
|
|
19
|
-
# """
|
|
20
|
-
# return dynamically_load(module_name, class_name)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# def get_function(module_name: str, func_name: str) -> Callable:
|
|
24
|
-
# """dynammically loads the module and returns the function from this file
|
|
25
|
-
|
|
26
|
-
# Args:
|
|
27
|
-
# module_name (str): name of python module, (typically a file name without extention)
|
|
28
|
-
# func_name (str): the name of the wanted function
|
|
29
|
-
|
|
30
|
-
# Returns:
|
|
31
|
-
# Callable: the function
|
|
32
|
-
# """
|
|
33
|
-
# return dynamically_load(module_name, func_name)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# def get_current_function() -> Callable:
|
|
37
|
-
# """return the function that is calling this file
|
|
38
|
-
|
|
39
|
-
# Returns:
|
|
40
|
-
# Callable: function
|
|
41
|
-
# """
|
|
42
|
-
# return get_caller()
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# def get_caller() -> Callable:
|
|
46
|
-
# """returns the caller of the function thats using this function
|
|
47
|
-
|
|
48
|
-
# Returns:
|
|
49
|
-
# Callable: caller
|
|
50
|
-
# """
|
|
51
|
-
# name = get_caller_name(1)
|
|
52
|
-
# module = get_caller_filename().removesuffix(".py")
|
|
53
|
-
# return get_function(module, name)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|