holado 0.13.22__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- holado/__init__.py +358 -0
- holado/common/__init__.py +25 -0
- holado/common/context/__init__.py +25 -0
- holado/common/context/context.py +248 -0
- holado/common/context/service_manager.py +262 -0
- holado/common/context/session_context.py +516 -0
- holado/common/handlers/__init__.py +19 -0
- holado/common/handlers/enums.py +41 -0
- holado/common/handlers/object.py +175 -0
- holado/common/handlers/undefined.py +55 -0
- holado/common/tools/__init__.py +19 -0
- holado/common/tools/gc_manager.py +155 -0
- holado/holado_config.py +45 -0
- holado-0.13.22.dist-info/METADATA +194 -0
- holado-0.13.22.dist-info/RECORD +698 -0
- holado-0.13.22.dist-info/WHEEL +4 -0
- holado-0.13.22.dist-info/licenses/LICENSE +21 -0
- holado_ais/__init__.py +33 -0
- holado_ais/ais/MaritimeIdentificationDigits.csv +295 -0
- holado_ais/ais/ais_manager.py +151 -0
- holado_ais/ais/ais_messages.py +356 -0
- holado_ais/ais/ais_payload.py +35 -0
- holado_ais/ais/enums.py +37 -0
- holado_ais/ais/patch_pyais.py +1174 -0
- holado_ais/tests/behave/steps/__init__.py +17 -0
- holado_ais/tests/behave/steps/ais/__init__.py +0 -0
- holado_ais/tests/behave/steps/ais/ais_manager_steps.py +50 -0
- holado_ais/tests/behave/steps/ais/ais_messages_steps.py +237 -0
- holado_binary/__init__.py +17 -0
- holado_binary/ipc/binary.py +125 -0
- holado_binary/ipc/bit_series.py +307 -0
- holado_binary/tests/behave/steps/__init__.py +17 -0
- holado_binary/tests/behave/steps/ipc/binary_steps.py +57 -0
- holado_binary/tests/behave/steps/ipc/bit_series_steps.py +132 -0
- holado_context/__init__.py +16 -0
- holado_context/tests/behave/steps/__init__.py +16 -0
- holado_context/tests/behave/steps/private/__init__.py +16 -0
- holado_context/tests/behave/steps/private/common/context_steps.py +68 -0
- holado_core/__init__.py +32 -0
- holado_core/common/__init__.py +0 -0
- holado_core/common/actors/actions.py +97 -0
- holado_core/common/actors/actor.py +226 -0
- holado_core/common/actors/element_actor.py +32 -0
- holado_core/common/actors/find_actor.py +106 -0
- holado_core/common/actors/tree_actor.py +32 -0
- holado_core/common/actors/verify_actions.py +69 -0
- holado_core/common/block/base.py +122 -0
- holado_core/common/block/block_manager.py +173 -0
- holado_core/common/block/block_method.py +46 -0
- holado_core/common/block/block_steps.py +37 -0
- holado_core/common/block/function.py +42 -0
- holado_core/common/block/scope_function.py +28 -0
- holado_core/common/block/scope_manager.py +238 -0
- holado_core/common/block/scope_steps.py +141 -0
- holado_core/common/criterias/and_criteria.py +61 -0
- holado_core/common/criterias/criteria.py +78 -0
- holado_core/common/criterias/or_criteria.py +64 -0
- holado_core/common/criterias/tools/criteria_context.py +20 -0
- holado_core/common/criterias/tools/criteria_parameters.py +18 -0
- holado_core/common/drivers/driver.py +153 -0
- holado_core/common/drivers/element_driver.py +30 -0
- holado_core/common/drivers/element_internal_api.py +239 -0
- holado_core/common/drivers/internal_api.py +40 -0
- holado_core/common/drivers/tree_driver.py +30 -0
- holado_core/common/drivers/tree_internal_api.py +176 -0
- holado_core/common/exceptions/__init__.py +0 -0
- holado_core/common/exceptions/element_exception.py +28 -0
- holado_core/common/exceptions/exceptions.py +24 -0
- holado_core/common/exceptions/functional_exception.py +21 -0
- holado_core/common/exceptions/holado_exception.py +25 -0
- holado_core/common/exceptions/technical_exception.py +27 -0
- holado_core/common/exceptions/timeout_exception.py +20 -0
- holado_core/common/exceptions/verify_exception.py +20 -0
- holado_core/common/finders/after_in_tree_finder.py +87 -0
- holado_core/common/finders/element_finder.py +60 -0
- holado_core/common/finders/else_finder.py +105 -0
- holado_core/common/finders/finder.py +478 -0
- holado_core/common/finders/or_finder.py +98 -0
- holado_core/common/finders/then_finder.py +157 -0
- holado_core/common/finders/tools/enums.py +30 -0
- holado_core/common/finders/tools/find_builder.py +118 -0
- holado_core/common/finders/tools/find_context.py +405 -0
- holado_core/common/finders/tools/find_info.py +27 -0
- holado_core/common/finders/tools/find_parameters.py +240 -0
- holado_core/common/finders/tools/find_updater.py +95 -0
- holado_core/common/finders/tools/finder_info.py +26 -0
- holado_core/common/finders/tree_finder.py +146 -0
- holado_core/common/handlers/__init__.py +0 -0
- holado_core/common/handlers/abstracts/base_redo.py +702 -0
- holado_core/common/handlers/abstracts/get_or_create.py +120 -0
- holado_core/common/handlers/element_holder.py +122 -0
- holado_core/common/handlers/enums.py +23 -0
- holado_core/common/handlers/exceptions/redo_exceptions.py +28 -0
- holado_core/common/handlers/features/resource_by_name.py +187 -0
- holado_core/common/handlers/features/resource_by_type.py +174 -0
- holado_core/common/handlers/redo.py +119 -0
- holado_core/common/handlers/wait.py +127 -0
- holado_core/common/inspectors/element_inspector.py +57 -0
- holado_core/common/inspectors/inspector.py +221 -0
- holado_core/common/inspectors/tools/inspect_builder.py +169 -0
- holado_core/common/inspectors/tools/inspect_context.py +69 -0
- holado_core/common/inspectors/tools/inspect_parameters.py +181 -0
- holado_core/common/inspectors/tree_inspector.py +73 -0
- holado_core/common/resource/persisted_data_manager.py +113 -0
- holado_core/common/resource/persisted_method_to_call_manager.py +263 -0
- holado_core/common/resource/resource_manager.py +126 -0
- holado_core/common/resource/table_data_manager.py +110 -0
- holado_core/common/tables/__init__.py +1 -0
- holado_core/common/tables/comparators/__init__.py +0 -0
- holado_core/common/tables/comparators/boolean_table_cell_comparator.py +25 -0
- holado_core/common/tables/comparators/bytes_table_cell_comparator.py +25 -0
- holado_core/common/tables/comparators/datetime_table_cell_comparator.py +24 -0
- holado_core/common/tables/comparators/float_table_cell_comparator.py +31 -0
- holado_core/common/tables/comparators/integer_table_cell_comparator.py +25 -0
- holado_core/common/tables/comparators/internal_table_cell_comparator.py +30 -0
- holado_core/common/tables/comparators/string_table_cell_comparator.py +24 -0
- holado_core/common/tables/comparators/string_table_comparator.py +29 -0
- holado_core/common/tables/comparators/string_table_row_comparator.py +29 -0
- holado_core/common/tables/comparators/table_cell_comparator.py +40 -0
- holado_core/common/tables/comparators/table_comparator.py +209 -0
- holado_core/common/tables/comparators/table_comparator_manager.py +60 -0
- holado_core/common/tables/comparators/table_row_comparator.py +116 -0
- holado_core/common/tables/comparators/table_with_header_comparator.py +68 -0
- holado_core/common/tables/converters/__init__.py +0 -0
- holado_core/common/tables/converters/table_converter.py +233 -0
- holado_core/common/tables/enums.py +23 -0
- holado_core/common/tables/table.py +261 -0
- holado_core/common/tables/table_cell.py +126 -0
- holado_core/common/tables/table_manager.py +365 -0
- holado_core/common/tables/table_row.py +169 -0
- holado_core/common/tables/table_with_header.py +242 -0
- holado_core/common/tools/__init__.py +0 -0
- holado_core/common/tools/comparators/comparator.py +151 -0
- holado_core/common/tools/comparators/object_comparator.py +21 -0
- holado_core/common/tools/converters/converter.py +118 -0
- holado_core/common/tools/path_manager.py +238 -0
- holado_core/common/tools/string_tools.py +144 -0
- holado_core/common/tools/tools.py +197 -0
- holado_core/tests/behave/steps/__init__.py +20 -0
- holado_core/tests/behave/steps/common/__init__.py +0 -0
- holado_core/tests/behave/steps/common/common_steps.py +137 -0
- holado_core/tests/behave/steps/common/config_steps.py +42 -0
- holado_core/tests/behave/steps/common/resource_steps.py +62 -0
- holado_core/tests/behave/steps/common/tables_steps.py +560 -0
- holado_core/tools/__init__.py +0 -0
- holado_core/tools/abstracts/__init__.py +0 -0
- holado_core/tools/abstracts/blocking_command_service.py +64 -0
- holado_core/tools/abstracts/service.py +48 -0
- holado_crypto/__init__.py +31 -0
- holado_crypto/crypto/crypto.py +108 -0
- holado_crypto/crypto/key.py +92 -0
- holado_crypto/crypto/tcpbin.py +105 -0
- holado_crypto/crypto/transport/__init__.py +0 -0
- holado_crypto/crypto/transport/crc.py +40 -0
- holado_crypto/tests/behave/steps/__init__.py +18 -0
- holado_crypto/tests/behave/steps/crypto_steps.py +112 -0
- holado_crypto/tests/behave/steps/key_steps.py +82 -0
- holado_crypto/tests/behave/steps/tcpbin_steps.py +79 -0
- holado_data/__init__.py +31 -0
- holado_data/data/generator/base.py +93 -0
- holado_data/data/generator/generator_manager.py +27 -0
- holado_data/data/generator/python_generator.py +30 -0
- holado_data/tests/behave/steps/__init__.py +17 -0
- holado_data/tests/behave/steps/data/generator_steps.py +91 -0
- holado_data/tests/behave/steps/tools/utils_steps.py +59 -0
- holado_db/__init__.py +32 -0
- holado_db/tests/behave/steps/__init__.py +18 -0
- holado_db/tests/behave/steps/tools/db/db_client_steps.py +134 -0
- holado_db/tests/behave/steps/tools/db/postgresql_client_steps.py +59 -0
- holado_db/tests/behave/steps/tools/db/sqlite_client_steps.py +57 -0
- holado_db/tools/db/clients/base/db_audit.py +94 -0
- holado_db/tools/db/clients/base/db_client.py +344 -0
- holado_db/tools/db/clients/postgresql/postgresql_audit.py +75 -0
- holado_db/tools/db/clients/postgresql/postgresql_client.py +84 -0
- holado_db/tools/db/clients/sqlite/sqlite_audit.py +70 -0
- holado_db/tools/db/clients/sqlite/sqlite_client.py +60 -0
- holado_db/tools/db/db_manager.py +109 -0
- holado_db/tools/db/query/base/query_builder.py +138 -0
- holado_db/tools/db/query/pypika/pypika_query_builder.py +244 -0
- holado_db/tools/db/query/query_manager.py +77 -0
- holado_django/__init__.py +31 -0
- holado_django/server/HOWTO.txt +27 -0
- holado_django/server/django_projects/rest_api/db.sqlite3 +0 -0
- holado_django/server/django_projects/rest_api/manage.py +22 -0
- holado_django/server/django_projects/rest_api/rest_api/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/admin.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/apps.py +9 -0
- holado_django/server/django_projects/rest_api/rest_api/application/migrations/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/models.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/tests.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/views.py +6 -0
- holado_django/server/django_projects/rest_api/rest_api/asgi.py +16 -0
- holado_django/server/django_projects/rest_api/rest_api/settings.py +130 -0
- holado_django/server/django_projects/rest_api/rest_api/urls.py +35 -0
- holado_django/server/django_projects/rest_api/rest_api/wsgi.py +16 -0
- holado_django/server/django_server.py +110 -0
- holado_django/server/grpc_django_server.py +57 -0
- holado_django/server/patch_djangogrpcframework.py +46 -0
- holado_django/tests/behave/steps/__init__.py +16 -0
- holado_django/tests/behave/steps/django_server_steps.py +83 -0
- holado_docker/__init__.py +25 -0
- holado_docker/sdk/docker/container_logs.py +447 -0
- holado_docker/sdk/docker/docker_client.py +537 -0
- holado_docker/sdk/docker/docker_service.py +71 -0
- holado_docker/tests/behave/steps/__init__.py +16 -0
- holado_docker/tests/behave/steps/sdk/docker/container_logs_steps.py +47 -0
- holado_examples/projects/server_rest/server_rest_example/initialize_holado.py +72 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/db.sqlite3 +0 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/manage.py +22 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/__init__.py +0 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/__init__.py +0 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/admin.py +3 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/apps.py +7 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/migrations/__init__.py +0 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/models.py +3 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/serializers.py +15 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/tests.py +3 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/application/views.py +24 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/asgi.py +16 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/settings.py +130 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/urls.py +31 -0
- holado_examples/projects/server_rest/server_rest_example/rest_api/rest_api/wsgi.py +16 -0
- holado_examples/projects/server_rest/server_rest_example/rest_server.py +37 -0
- holado_examples/scripts/script_custom_initialization.py +16 -0
- holado_examples/scripts/script_minimal_initialization.py +23 -0
- holado_examples/tests/behave/testing_solution/__main__.py +13 -0
- holado_examples/tests/behave/testing_solution/behave_environment.py +35 -0
- holado_examples/tests/behave/testing_solution/environment.py +36 -0
- holado_examples/tests/behave/testing_solution/features/Configuration/Actions/configure_system.feature +10 -0
- holado_examples/tests/behave/testing_solution/features/NonReg/example.feature +26 -0
- holado_examples/tests/behave/testing_solution/initialize_holado.py +62 -0
- holado_examples/tests/behave/testing_solution/logging.conf +102 -0
- holado_examples/tests/behave/testing_solution/requirements.txt +5 -0
- holado_examples/tests/behave/testing_solution/run_test.sh +7 -0
- holado_examples/tests/behave/testing_solution/run_test_nonreg.sh +6 -0
- holado_examples/tests/behave/testing_solution/src/common/tools/path_manager.py +40 -0
- holado_examples/tests/behave/testing_solution/src/config/config_manager.py +30 -0
- holado_examples/tests/behave/testing_solution/src/context/session_context.py +45 -0
- holado_examples/tests/behave/testing_solution/steps/config_steps.py +21 -0
- holado_examples/tests/behave/testing_solution/steps/public_steps.py +10 -0
- holado_grpc/TODO +8 -0
- holado_grpc/__init__.py +40 -0
- holado_grpc/api/rpc/TODO.txt +4 -0
- holado_grpc/api/rpc/grpc_client.py +210 -0
- holado_grpc/api/rpc/grpc_manager.py +81 -0
- holado_grpc/ipc/rpc/__init__.py +0 -0
- holado_grpc/ipc/rpc/grpc_compiler.py +45 -0
- holado_grpc/ipc/rpc/grpc_services.py +165 -0
- holado_grpc/tests/behave/steps/__init__.py +16 -0
- holado_grpc/tests/behave/steps/api/grpc_client_steps.py +173 -0
- holado_grpc/tests/behave/steps/private/__init__.py +16 -0
- holado_grpc/tests/behave/steps/private/api/grpc_steps.py +77 -0
- holado_helper/__init__.py +35 -0
- holado_helper/debug/README.txt +32 -0
- holado_helper/debug/memory/memory_profiler.py +106 -0
- holado_helper/docker/init_user.sh +24 -0
- holado_helper/docker/logging.conf +44 -0
- holado_helper/docker/run_holado_test_nonreg_in_docker.sh +120 -0
- holado_helper/docker/run_terminal_in_docker.sh +101 -0
- holado_helper/holado_module_template/__init__.py +38 -0
- holado_helper/holado_module_template/tests/behave/steps/__init__.py +16 -0
- holado_helper/holado_module_template/tests/behave/steps/private/__init__.py +16 -0
- holado_helper/initialize_holado.py +72 -0
- holado_helper/script/action.py +130 -0
- holado_helper/script/action_script.py +477 -0
- holado_helper/script/any_action_script.py +126 -0
- holado_helper/script/behave_action_script.py +99 -0
- holado_helper/script/csv_action_script.py +142 -0
- holado_helper/script/initialize_script.py +95 -0
- holado_helper/script/input_output_script.py +136 -0
- holado_helper/script/job.py +75 -0
- holado_helper/script/json_action_script.py +104 -0
- holado_helper/script/script.py +110 -0
- holado_json/__init__.py +16 -0
- holado_json/filesystem/json_file.py +94 -0
- holado_json/filesystem/stream_json_file.py +117 -0
- holado_json/ipc/json.py +146 -0
- holado_json/ipc/json_converter.py +69 -0
- holado_json/ipc/json_types.py +183 -0
- holado_json/tests/behave/steps/__init__.py +16 -0
- holado_json/tests/behave/steps/ipc/__init__.py +0 -0
- holado_json/tests/behave/steps/ipc/json_steps.py +131 -0
- holado_keycloak/__init__.py +16 -0
- holado_keycloak/tests/behave/steps/__init__.py +16 -0
- holado_keycloak/tests/behave/steps/tools/keycloak_client_steps.py +73 -0
- holado_keycloak/tools/keycloak/__init__.py +0 -0
- holado_keycloak/tools/keycloak/keycloak_client.py +90 -0
- holado_logging/__init__.py +38 -0
- holado_logging/common/logging/holado_logger.py +71 -0
- holado_logging/common/logging/log_config.py +163 -0
- holado_logging/common/logging/log_manager.py +335 -0
- holado_multitask/__init__.py +33 -0
- holado_multitask/multiprocessing/context/process_context.py +35 -0
- holado_multitask/multiprocessing/function_process.py +102 -0
- holado_multitask/multiprocessing/periodic_function_process.py +137 -0
- holado_multitask/multiprocessing/process.py +213 -0
- holado_multitask/multiprocessing/processesmanager.py +137 -0
- holado_multitask/multitasking/multitask_manager.py +464 -0
- holado_multitask/multithreading/__init__.py +0 -0
- holado_multitask/multithreading/context/thread_context.py +86 -0
- holado_multitask/multithreading/functionthreaded.py +129 -0
- holado_multitask/multithreading/loopfunctionthreaded.py +45 -0
- holado_multitask/multithreading/loopthread.py +110 -0
- holado_multitask/multithreading/periodicfunctionthreaded.py +135 -0
- holado_multitask/multithreading/reflection/inspect.py +47 -0
- holado_multitask/multithreading/reflection/sys.py +29 -0
- holado_multitask/multithreading/reflection/traceback.py +35 -0
- holado_multitask/multithreading/thread.py +203 -0
- holado_multitask/multithreading/threadsmanager.py +167 -0
- holado_multitask/multithreading/timer.py +51 -0
- holado_multitask/tests/behave/steps/__init__.py +17 -0
- holado_multitask/tests/behave/steps/multiprocessing_steps.py +138 -0
- holado_multitask/tests/behave/steps/multithreading_steps.py +129 -0
- holado_protobuf/__init__.py +61 -0
- holado_protobuf/ipc/protobuf/__init__.py +0 -0
- holado_protobuf/ipc/protobuf/abstracts/type.py +45 -0
- holado_protobuf/ipc/protobuf/protobuf_compiler.py +118 -0
- holado_protobuf/ipc/protobuf/protobuf_converter.py +153 -0
- holado_protobuf/ipc/protobuf/protobuf_messages.py +968 -0
- holado_protobuf/ipc/protobuf/protobuf_modifier.py +65 -0
- holado_protobuf/ipc/protobuf/types/__init__.py +0 -0
- holado_protobuf/ipc/protobuf/types/google/__init__.py +0 -0
- holado_protobuf/ipc/protobuf/types/google/protobuf.py +124 -0
- holado_protobuf/tests/behave/steps/__init__.py +16 -0
- holado_protobuf/tests/behave/steps/ipc/protobuf_steps.py +297 -0
- holado_python/__init__.py +36 -0
- holado_python/common/enums.py +34 -0
- holado_python/common/iterables.py +38 -0
- holado_python/common/tools/comparators/boolean_comparator.py +37 -0
- holado_python/common/tools/comparators/bytes_comparator.py +48 -0
- holado_python/common/tools/comparators/datetime_comparator.py +74 -0
- holado_python/common/tools/comparators/float_comparator.py +97 -0
- holado_python/common/tools/comparators/integer_comparator.py +37 -0
- holado_python/common/tools/comparators/string_comparator.py +99 -0
- holado_python/common/tools/comparators/type_comparator.py +31 -0
- holado_python/common/tools/datetime.py +341 -0
- holado_python/standard_library/csv.py +207 -0
- holado_python/standard_library/hashlib.py +110 -0
- holado_python/standard_library/multiprocessing.py +62 -0
- holado_python/standard_library/queue.py +79 -0
- holado_python/standard_library/socket/blocking_socket.py +219 -0
- holado_python/standard_library/socket/echo_server.py +29 -0
- holado_python/standard_library/socket/message_socket.py +152 -0
- holado_python/standard_library/socket/non_blocking_socket.py +172 -0
- holado_python/standard_library/socket/socket.py +411 -0
- holado_python/standard_library/ssl/resources/certificates/NOTES.txt +5 -0
- holado_python/standard_library/ssl/resources/certificates/localhost.crt +19 -0
- holado_python/standard_library/ssl/resources/certificates/localhost.key +28 -0
- holado_python/standard_library/ssl/ssl.py +131 -0
- holado_python/standard_library/typing.py +192 -0
- holado_python/tests/behave/steps/__init__.py +27 -0
- holado_python/tests/behave/steps/builtins/str_steps.py +45 -0
- holado_python/tests/behave/steps/convert_steps.py +59 -0
- holado_python/tests/behave/steps/iterable_steps.py +87 -0
- holado_python/tests/behave/steps/standard_library/csv_steps.py +134 -0
- holado_python/tests/behave/steps/standard_library/datetime_steps.py +163 -0
- holado_python/tests/behave/steps/standard_library/hashlib_steps.py +57 -0
- holado_python/tests/behave/steps/standard_library/multiprocessing_steps.py +56 -0
- holado_python/tests/behave/steps/standard_library/queue_steps.py +358 -0
- holado_python/tests/behave/steps/standard_library/socket_steps.py +384 -0
- holado_python/tests/behave/steps/standard_library/ssl_steps.py +71 -0
- holado_rabbitmq/__init__.py +28 -0
- holado_rabbitmq/tests/behave/steps/__init__.py +17 -0
- holado_rabbitmq/tests/behave/steps/tools/rabbitmq_client_steps.py +565 -0
- holado_rabbitmq/tests/behave/steps/tools/rabbitmq_server_steps.py +64 -0
- holado_rabbitmq/tools/rabbitmq/rabbitmq_blocking_client.py +333 -0
- holado_rabbitmq/tools/rabbitmq/rabbitmq_client.py +678 -0
- holado_rabbitmq/tools/rabbitmq/rabbitmq_manager.py +146 -0
- holado_rabbitmq/tools/rabbitmq/rabbitmq_select_client.py +428 -0
- holado_rabbitmq/tools/rabbitmq/rabbitmq_server.py +24 -0
- holado_redis/__init__.py +17 -0
- holado_redis/tests/behave/steps/__init__.py +16 -0
- holado_redis/tests/behave/steps/tools/redis_client_steps.py +101 -0
- holado_redis/tools/redis/TODO.txt +7 -0
- holado_redis/tools/redis/redis_client.py +190 -0
- holado_redis/tools/redis/redis_manager.py +38 -0
- holado_report/__init__.py +36 -0
- holado_report/campaign/campaign_manager.py +348 -0
- holado_report/report/analyze/execution_historic_manager.py +96 -0
- holado_report/report/analyze/scenario_duration_manager.py +245 -0
- holado_report/report/builders/detailed_scenario_report_builder.py +172 -0
- holado_report/report/builders/execution_historic_report_builder.py +132 -0
- holado_report/report/builders/failure_report_builder.py +150 -0
- holado_report/report/builders/report_builder.py +64 -0
- holado_report/report/builders/short_scenario_report_builder.py +94 -0
- holado_report/report/builders/summary_by_category_report_builder.py +103 -0
- holado_report/report/builders/summary_report_builder.py +110 -0
- holado_report/report/builders/summary_scenario_by_category_report_builder.py +109 -0
- holado_report/report/builders/summary_scenario_report_builder.py +81 -0
- holado_report/report/execution_historic.py +144 -0
- holado_report/report/report_manager.py +424 -0
- holado_report/report/reports/base_report.py +163 -0
- holado_report/report/reports/feature_report.py +106 -0
- holado_report/report/reports/scenario_report.py +64 -0
- holado_rest/__init__.py +32 -0
- holado_rest/api/rest/TODO.txt +2 -0
- holado_rest/api/rest/rest_client.py +200 -0
- holado_rest/api/rest/rest_manager.py +72 -0
- holado_rest/tests/behave/steps/__init__.py +16 -0
- holado_rest/tests/behave/steps/api/__init__.py +0 -0
- holado_rest/tests/behave/steps/api/rest_client_steps.py +181 -0
- holado_rest/tests/behave/steps/private/__init__.py +16 -0
- holado_rest/tests/behave/steps/private/api/__init__.py +0 -0
- holado_rest/tests/behave/steps/private/api/rest_steps.py +75 -0
- holado_s3/__init__.py +17 -0
- holado_s3/tests/behave/steps/__init__.py +17 -0
- holado_s3/tests/behave/steps/private/__init__.py +16 -0
- holado_s3/tests/behave/steps/private/tools/s3_steps.py +89 -0
- holado_s3/tests/behave/steps/tools/s3_client_steps.py +403 -0
- holado_s3/tests/behave/steps/tools/s3_server_steps.py +57 -0
- holado_s3/tools/s3/__init__.py +0 -0
- holado_s3/tools/s3/boto3_s3_client.py +59 -0
- holado_s3/tools/s3/minio_client.py +75 -0
- holado_s3/tools/s3/moto_server.py +52 -0
- holado_scripting/__init__.py +54 -0
- holado_scripting/common/tools/dynamic_text_manager.py +73 -0
- holado_scripting/common/tools/evaluate_parameters.py +228 -0
- holado_scripting/common/tools/expression_evaluator.py +389 -0
- holado_scripting/common/tools/variable_manager.py +354 -0
- holado_scripting/tests/behave/steps/__init__.py +22 -0
- holado_scripting/tests/behave/steps/common/tools/variable_convert_steps.py +159 -0
- holado_scripting/tests/behave/steps/common/tools/variable_new_steps.py +130 -0
- holado_scripting/tests/behave/steps/common/tools/variable_steps.py +108 -0
- holado_scripting/tests/behave/steps/common/tools/variable_verify_steps.py +160 -0
- holado_scripting/tests/behave/steps/scenario/function_steps.py +77 -0
- holado_scripting/tests/behave/steps/scenario/if_steps.py +87 -0
- holado_scripting/tests/behave/steps/scenario/loop_steps.py +119 -0
- holado_scripting/text/base/base_function.py +25 -0
- holado_scripting/text/base/base_verify_function.py +25 -0
- holado_scripting/text/base/text_inspecter.py +204 -0
- holado_scripting/text/interpreter/exceptions/interpreter_exception.py +25 -0
- holado_scripting/text/interpreter/functions/function_apply_function.py +60 -0
- holado_scripting/text/interpreter/functions/function_cast.py +60 -0
- holado_scripting/text/interpreter/functions/function_convert.py +57 -0
- holado_scripting/text/interpreter/functions/function_dynamic_value.py +40 -0
- holado_scripting/text/interpreter/functions/function_escape_all_bytes.py +35 -0
- holado_scripting/text/interpreter/functions/function_exists_variable.py +39 -0
- holado_scripting/text/interpreter/functions/function_hex_to_bytes.py +49 -0
- holado_scripting/text/interpreter/functions/function_hex_to_int.py +53 -0
- holado_scripting/text/interpreter/functions/function_to_base_64.py +41 -0
- holado_scripting/text/interpreter/functions/function_to_bytes.py +50 -0
- holado_scripting/text/interpreter/functions/function_to_hex.py +42 -0
- holado_scripting/text/interpreter/functions/function_to_string.py +50 -0
- holado_scripting/text/interpreter/text_interpreter.py +219 -0
- holado_scripting/text/verifier/exceptions/verifier_exception.py +21 -0
- holado_scripting/text/verifier/functions/verify_function_extract_in.py +35 -0
- holado_scripting/text/verifier/functions/verify_function_match_pattern.py +63 -0
- holado_scripting/text/verifier/text_verifier.py +103 -0
- holado_sftp/__init__.py +16 -0
- holado_sftp/tests/behave/steps/__init__.py +17 -0
- holado_sftp/tests/behave/steps/private/__init__.py +16 -0
- holado_sftp/tests/behave/steps/private/tools/sftp_steps.py +78 -0
- holado_sftp/tests/behave/steps/tools/sftp_client_steps.py +94 -0
- holado_sftp/tests/behave/steps/tools/sftp_server_steps.py +82 -0
- holado_sftp/tools/sftp/__init__.py +0 -0
- holado_sftp/tools/sftp/sftp_client.py +103 -0
- holado_sftp/tools/sftp/sftp_server.py +39 -0
- holado_swagger/__init__.py +31 -0
- holado_swagger/swagger_hub/mockserver/mockserver_client.py +82 -0
- holado_swagger/swagger_hub/mockserver/mockserver_manager.py +33 -0
- holado_swagger/tests/behave/steps/__init__.py +16 -0
- holado_swagger/tests/behave/steps/swagger_hub/mockserver_steps.py +74 -0
- holado_system/system/command/command.py +247 -0
- holado_system/system/command/command_result.py +128 -0
- holado_system/system/command/curl_command.py +101 -0
- holado_system/system/command/exceptions.py +59 -0
- holado_system/system/filesystem/file.py +150 -0
- holado_system/system/global_system.py +187 -0
- holado_system/tests/behave/steps/__init__.py +18 -0
- holado_system/tests/behave/steps/system/commands_steps.py +92 -0
- holado_system/tests/behave/steps/system/file_steps.py +231 -0
- holado_system/tests/behave/steps/system/system_steps.py +84 -0
- holado_test/__init__.py +30 -0
- holado_test/behave/__init__.py +0 -0
- holado_test/behave/behave.py +400 -0
- holado_test/behave/behave_environment.py +169 -0
- holado_test/behave/behave_function.py +33 -0
- holado_test/behave/behave_manager.py +558 -0
- holado_test/behave/independant_runner.py +66 -0
- holado_test/behave/scenario/__init__.py +0 -0
- holado_test/behave/scenario/behave_step_tools.py +157 -0
- holado_test/common/context/feature_context.py +81 -0
- holado_test/common/context/scenario_context.py +169 -0
- holado_test/common/context/step_context.py +66 -0
- holado_test/common/exceptions/undefined_step_exception.py +21 -0
- holado_test/scenario/step_tools.py +547 -0
- holado_test/scenario/tester_tools.py +57 -0
- holado_test/test_config.py +26 -0
- holado_test/tests/behave/steps/__init__.py +18 -0
- holado_test/tests/behave/steps/scenario/exception_steps.py +87 -0
- holado_test/tests/behave/steps/scenario/scenario_steps.py +100 -0
- holado_test/tests/behave/steps/scenario/tester_steps.py +65 -0
- holado_test/tools/test_server/client/rest/test_server_client.py +150 -0
- holado_test/tools/test_server/server/Dockerfile +60 -0
- holado_test/tools/test_server/server/core/server_context.py +42 -0
- holado_test/tools/test_server/server/core/server_manager.py +41 -0
- holado_test/tools/test_server/server/requirements.txt +2 -0
- holado_test/tools/test_server/server/rest/README +2 -0
- holado_test/tools/test_server/server/rest/api/__init__.py +24 -0
- holado_test/tools/test_server/server/rest/api/campaign/__init__.py +32 -0
- holado_test/tools/test_server/server/rest/api/campaign/scenario.py +40 -0
- holado_test/tools/test_server/server/rest/initialize_holado.py +72 -0
- holado_test/tools/test_server/server/rest/logging.conf +51 -0
- holado_test/tools/test_server/server/rest/openapi.yaml +57 -0
- holado_test/tools/test_server/server/rest/run.py +41 -0
- holado_test/tools/test_server/server/run.sh +6 -0
- holado_test/tools/test_server/server/run_test_server_in_docker.sh +104 -0
- holado_tools/__init__.py +38 -0
- holado_tools/scripts/execute_persisted_post_processes/execute_persisted_post_processes.py +36 -0
- holado_tools/scripts/execute_persisted_post_processes/execute_persisted_post_processes.sh +6 -0
- holado_tools/scripts/execute_persisted_post_processes/initialize_holado.py +62 -0
- holado_tools/tests/behave/steps/__init__.py +16 -0
- holado_tools/tests/behave/steps/tools/host_controller/client_steps.py +97 -0
- holado_tools/tools/host_controller/client/rest/host_controller_client.py +275 -0
- holado_tools/tools/host_controller/server/Dockerfile +60 -0
- holado_tools/tools/host_controller/server/requirements.txt +2 -0
- holado_tools/tools/host_controller/server/rest/README +2 -0
- holado_tools/tools/host_controller/server/rest/api/__init__.py +24 -0
- holado_tools/tools/host_controller/server/rest/api/config.py +88 -0
- holado_tools/tools/host_controller/server/rest/api/docker/__init__.py +66 -0
- holado_tools/tools/host_controller/server/rest/api/docker/container.py +144 -0
- holado_tools/tools/host_controller/server/rest/api/docker/logs.py +66 -0
- holado_tools/tools/host_controller/server/rest/api/os.py +58 -0
- holado_tools/tools/host_controller/server/rest/initialize_holado.py +72 -0
- holado_tools/tools/host_controller/server/rest/openapi.yaml +561 -0
- holado_tools/tools/host_controller/server/rest/run.py +31 -0
- holado_tools/tools/host_controller/server/run_host_controller_in_docker.sh +107 -0
- holado_tools/tools/host_viewer/client/rest/host_viewer_client.py +190 -0
- holado_tools/tools/host_viewer/server/Dockerfile +60 -0
- holado_tools/tools/host_viewer/server/requirements.txt +2 -0
- holado_tools/tools/host_viewer/server/rest/README +2 -0
- holado_tools/tools/host_viewer/server/rest/api/__init__.py +24 -0
- holado_tools/tools/host_viewer/server/rest/api/docker/__init__.py +65 -0
- holado_tools/tools/host_viewer/server/rest/api/docker/container.py +87 -0
- holado_tools/tools/host_viewer/server/rest/api/os.py +58 -0
- holado_tools/tools/host_viewer/server/rest/initialize_holado.py +72 -0
- holado_tools/tools/host_viewer/server/rest/openapi.yaml +301 -0
- holado_tools/tools/host_viewer/server/rest/run.py +31 -0
- holado_tools/tools/host_viewer/server/run_host_viewer_in_docker.sh +107 -0
- holado_value/__init__.py +24 -0
- holado_value/common/tables/comparators/table_2_value_table_cell_comparator.py +196 -0
- holado_value/common/tables/comparators/table_2_value_table_comparator.py +27 -0
- holado_value/common/tables/comparators/table_2_value_table_row_comparator.py +27 -0
- holado_value/common/tables/comparators/table_2_value_table_with_header_comparator.py +27 -0
- holado_value/common/tables/converters/value_table_converter.py +267 -0
- holado_value/common/tables/value_table.py +29 -0
- holado_value/common/tables/value_table_cell.py +76 -0
- holado_value/common/tables/value_table_manager.py +48 -0
- holado_value/common/tables/value_table_row.py +43 -0
- holado_value/common/tables/value_table_with_header.py +28 -0
- holado_value/common/tools/unique_value_manager.py +109 -0
- holado_value/common/tools/value.py +191 -0
- holado_value/common/tools/value_types.py +41 -0
- holado_value/tests/behave/steps/__init__.py +16 -0
- holado_value/tests/behave/steps/private/__init__.py +16 -0
- holado_ws/__init__.py +16 -0
- holado_ws/api/ws/TODO.txt +2 -0
- holado_ws/tests/behave/steps/__init__.py +16 -0
- holado_ws/tests/behave/steps/api/web_service_steps.py +189 -0
- holado_xml/__init__.py +38 -0
- holado_xml/tests/behave/steps/__init__.py +16 -0
- holado_xml/tests/behave/steps/private/__init__.py +16 -0
- holado_xml/xml/stream_xml_file.py +181 -0
- holado_xml/xml/xml_file.py +97 -0
- holado_xml/xml/xml_manager.py +35 -0
- holado_yaml/__init__.py +31 -0
- holado_yaml/tests/behave/steps/__init__.py +16 -0
- holado_yaml/tests/behave/steps/yaml_steps.py +161 -0
- holado_yaml/yaml/enums.py +28 -0
- holado_yaml/yaml/pyyaml/pyyaml_client.py +72 -0
- holado_yaml/yaml/ruamel/ruamel_yaml_client.py +80 -0
- holado_yaml/yaml/yaml_client.py +203 -0
- holado_yaml/yaml/yaml_manager.py +94 -0
- test_holado/Dockerfile_test_holado +82 -0
- test_holado/__init__.py +4 -0
- test_holado/__main__.py +25 -0
- test_holado/build_docker_image_to_test_holado_in_docker.sh +7 -0
- test_holado/environment.py +60 -0
- test_holado/features/Configuration/Actions/execute_persisted_post_processes.feature +13 -0
- test_holado/features/NonReg/api/REST.feature +26 -0
- test_holado/features/NonReg/api/gRPC.feature +116 -0
- test_holado/features/NonReg/common/multiprocessing/simple.feature +60 -0
- test_holado/features/NonReg/common/system/commands.feature +43 -0
- test_holado/features/NonReg/common/system/system.feature +20 -0
- test_holado/features/NonReg/common/tables/table.feature +245 -0
- test_holado/features/NonReg/common/tables/value_table_conversion.feature +29 -0
- test_holado/features/NonReg/common/tools/DateTime.feature +88 -0
- test_holado/features/NonReg/common/tools/UniqueValueManager.feature +43 -0
- test_holado/features/NonReg/holado_ais/ais_message-bitarray_to_nmea.feature +135 -0
- test_holado/features/NonReg/holado_ais/ais_message-nmea_raw_to_dict.feature +93 -0
- test_holado/features/NonReg/holado_ais/message_types/type-10.feature +38 -0
- test_holado/features/NonReg/holado_ais/message_types/type-12.feature +37 -0
- test_holado/features/NonReg/holado_ais/message_types/type-14.feature +36 -0
- test_holado/features/NonReg/holado_ais/message_types/type-15.feature +36 -0
- test_holado/features/NonReg/holado_ais/message_types/type-16.feature +38 -0
- test_holado/features/NonReg/holado_ais/message_types/type-17.feature +46 -0
- test_holado/features/NonReg/holado_ais/message_types/type-18.feature +37 -0
- test_holado/features/NonReg/holado_ais/message_types/type-19.feature +38 -0
- test_holado/features/NonReg/holado_ais/message_types/type-1_2_3.feature +42 -0
- test_holado/features/NonReg/holado_ais/message_types/type-20.feature +38 -0
- test_holado/features/NonReg/holado_ais/message_types/type-21.feature +37 -0
- test_holado/features/NonReg/holado_ais/message_types/type-22.feature +84 -0
- test_holado/features/NonReg/holado_ais/message_types/type-23.feature +49 -0
- test_holado/features/NonReg/holado_ais/message_types/type-24.feature +72 -0
- test_holado/features/NonReg/holado_ais/message_types/type-25.feature +143 -0
- test_holado/features/NonReg/holado_ais/message_types/type-26.feature +144 -0
- test_holado/features/NonReg/holado_ais/message_types/type-27.feature +36 -0
- test_holado/features/NonReg/holado_ais/message_types/type-4_11.feature +39 -0
- test_holado/features/NonReg/holado_ais/message_types/type-5.feature +33 -0
- test_holado/features/NonReg/holado_ais/message_types/type-6.feature +37 -0
- test_holado/features/NonReg/holado_ais/message_types/type-7_13.feature +43 -0
- test_holado/features/NonReg/holado_ais/message_types/type-8.feature +37 -0
- test_holado/features/NonReg/holado_ais/message_types/type-9.feature +37 -0
- test_holado/features/NonReg/holado_binary/bit_series.error.feature +33 -0
- test_holado/features/NonReg/holado_binary/bit_series.feature +144 -0
- test_holado/features/NonReg/holado_protobuf/protobuf.feature +291 -0
- test_holado/features/NonReg/holado_python/convert.feature +20 -0
- test_holado/features/NonReg/holado_python/iterable.feature +61 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_reset.feature +191 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_with_tls_and_verify.feature +279 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_with_tls_without_verify.feature +299 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/local_echo_server/socket_without_tls.feature +163 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_with_mtls.feature +214 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_with_tls.feature +184 -0
- test_holado/features/NonReg/holado_python/standard_library/socket/tcpbin.com/socket_without_tls.feature +169 -0
- test_holado/features/NonReg/holado_scripting/common/tools/dynamic_text_manager.feature +18 -0
- test_holado/features/NonReg/holado_scripting/common/tools/expression_evaluator.feature +185 -0
- test_holado/features/NonReg/holado_scripting/common/tools/variable_manager.feature +71 -0
- test_holado/features/NonReg/holado_scripting/text/interpreter/interpreter.error.feature +21 -0
- test_holado/features/NonReg/holado_scripting/text/interpreter/interpreter.feature +120 -0
- test_holado/features/NonReg/holado_yaml/yaml.feature +514 -0
- test_holado/features/NonReg/ipc/json.feature +20 -0
- test_holado/features/NonReg/scenario/scenario.feature +183 -0
- test_holado/features/NonReg/test_steps/behave.feature +275 -0
- test_holado/features/NonReg/test_steps/common.feature +100 -0
- test_holado/features/NonReg/tools/RabbitMQ.feature +445 -0
- test_holado/features/NonReg/tools/RabbitMQ_steps.feature +276 -0
- test_holado/features/NonReg/tools/S3/boto3_client.feature +73 -0
- test_holado/features/NonReg/tools/S3/minio_client.feature +75 -0
- test_holado/features/NonReg/tools/db_sqlite3.feature +41 -0
- test_holado/features/NonReg/tools/sFTP.feature +25 -0
- test_holado/features/Test/logger.feature +28 -0
- test_holado/features/Test/test_host_controller.feature +13 -0
- test_holado/features/Test/test_parameter.feature +15 -0
- test_holado/features/__init__.py +0 -0
- test_holado/initialize_holado.py +62 -0
- test_holado/logging.conf +53 -0
- test_holado/resources/proto/definitions/protobuf/custom_types/field_types.proto +24 -0
- test_holado/resources/proto/definitions/protobuf/protobuf.dev/tutorial/addressbook.proto +56 -0
- test_holado/resources/proto/generated/protobuf/custom_types/field_types_pb2.py +34 -0
- test_holado/resources/proto/generated/protobuf/protobuf/dev/tutorial/addressbook_pb2.py +34 -0
- test_holado/resources/scripts/list_tags.sh +2 -0
- test_holado/resources/scripts/update_resources_proto_generated.py +70 -0
- test_holado/steps/__init__.py +0 -0
- test_holado/steps/private_steps.py +20 -0
- test_holado/steps/public_steps.py +23 -0
- test_holado/test_holado_session_context.py +43 -0
- test_holado/tools/connexion/api_rest/openapi.yaml +16 -0
- test_holado/tools/connexion/api_rest/run.py +19 -0
- test_holado/tools/django/README.txt +3 -0
- test_holado/tools/django/api_grpc/api_grpc/__init__.py +0 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/__init__.py +0 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/admin.py +3 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/apps.py +6 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/migrations/__init__.py +0 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/models.py +3 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/proto/__init__.py +0 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/proto/account.proto +27 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/proto/account_pb2.py +33 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/proto/account_pb2_grpc.py +199 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/serializers.py +12 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/services.py +11 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/tests.py +3 -0
- test_holado/tools/django/api_grpc/api_grpc/api1/views.py +3 -0
- test_holado/tools/django/api_grpc/api_grpc/asgi.py +16 -0
- test_holado/tools/django/api_grpc/api_grpc/settings.py +126 -0
- test_holado/tools/django/api_grpc/api_grpc/urls.py +27 -0
- test_holado/tools/django/api_grpc/api_grpc/wsgi.py +16 -0
- test_holado/tools/django/api_grpc/db.sqlite3 +0 -0
- test_holado/tools/django/api_grpc/manage.py +29 -0
- test_holado/tools/django/api_grpc/manual_test_commands.txt +25 -0
- test_holado/tools/django/api_grpc/patch_djangogrpcframework.py +42 -0
- test_holado/tools/django/api_rest/api_rest/__init__.py +0 -0
- test_holado/tools/django/api_rest/api_rest/api1/__init__.py +0 -0
- test_holado/tools/django/api_rest/api_rest/api1/admin.py +3 -0
- test_holado/tools/django/api_rest/api_rest/api1/apps.py +6 -0
- test_holado/tools/django/api_rest/api_rest/api1/migrations/__init__.py +0 -0
- test_holado/tools/django/api_rest/api_rest/api1/models.py +3 -0
- test_holado/tools/django/api_rest/api_rest/api1/serializers.py +15 -0
- test_holado/tools/django/api_rest/api_rest/api1/tests.py +3 -0
- test_holado/tools/django/api_rest/api_rest/api1/views.py +24 -0
- test_holado/tools/django/api_rest/api_rest/asgi.py +16 -0
- test_holado/tools/django/api_rest/api_rest/settings.py +133 -0
- test_holado/tools/django/api_rest/api_rest/urls.py +32 -0
- test_holado/tools/django/api_rest/api_rest/wsgi.py +16 -0
- test_holado/tools/django/api_rest/db.sqlite3 +0 -0
- test_holado/tools/django/api_rest/manage.py +22 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
from builtins import super
|
|
15
|
+
import logging
|
|
16
|
+
from holado_multitask.multithreading.functionthreaded import FunctionThreaded
|
|
17
|
+
from holado_multitask.multithreading.loopthread import LoopThread
|
|
18
|
+
from holado.common.handlers.undefined import default_context
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class LoopFunctionThreaded(LoopThread):
|
|
24
|
+
'''
|
|
25
|
+
Execute in a thread given function with given arguments.
|
|
26
|
+
'''
|
|
27
|
+
|
|
28
|
+
def __init__(self, target, args=None, kwargs=None, name=None, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, delay_between_run_sec=None, nb_times=None, with_next_loop_datetime=False):
|
|
29
|
+
super().__init__(name if name is not None else f"Loop function '{target}'", default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec, delay_between_run_sec=delay_between_run_sec, nb_times=nb_times, with_next_loop_datetime=with_next_loop_datetime)
|
|
30
|
+
|
|
31
|
+
self.__function_threaded = FunctionThreaded(target, args, kwargs)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def function_threaded(self):
|
|
35
|
+
return self.__function_threaded
|
|
36
|
+
|
|
37
|
+
def run_loop(self):
|
|
38
|
+
try:
|
|
39
|
+
self.__function_threaded.run()
|
|
40
|
+
except Exception as exc:
|
|
41
|
+
msg = "Exception catched while processing function:\n [{}]".format(repr(exc))
|
|
42
|
+
logger.exception(msg)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
import threading
|
|
15
|
+
import time
|
|
16
|
+
import logging
|
|
17
|
+
import holado_multitask.multithreading.thread as ctt
|
|
18
|
+
from holado.common.handlers.undefined import default_context
|
|
19
|
+
from holado_python.common.tools.datetime import DateTime
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class LoopThread(ctt.InterruptableThread):
|
|
25
|
+
""" Helper class managing a loop in a thread."""
|
|
26
|
+
|
|
27
|
+
def __init__(self, name, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, delay_between_run_sec=None, nb_times=None, with_next_loop_datetime=False):
|
|
28
|
+
super().__init__(name, default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec, delay_between_run_sec=delay_between_run_sec)
|
|
29
|
+
|
|
30
|
+
self.__nb_times = nb_times
|
|
31
|
+
|
|
32
|
+
# Manage loops
|
|
33
|
+
self.__with_next_loop_datetime = with_next_loop_datetime
|
|
34
|
+
self.__is_under_loop = threading.Event()
|
|
35
|
+
self.__next_loop_datetime = DateTime.now() if self.__with_next_loop_datetime else None
|
|
36
|
+
self.__loop_counter = 0
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def next_loop_datetime(self):
|
|
40
|
+
return self.__next_loop_datetime
|
|
41
|
+
|
|
42
|
+
@next_loop_datetime.setter
|
|
43
|
+
def next_loop_datetime(self, dt):
|
|
44
|
+
self.__next_loop_datetime = dt
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def loop_counter(self):
|
|
48
|
+
return self.__loop_counter
|
|
49
|
+
|
|
50
|
+
def run(self):
|
|
51
|
+
logger.info("Loop thread '{}' is launched.".format(self.name))
|
|
52
|
+
|
|
53
|
+
self.wait_before_run()
|
|
54
|
+
|
|
55
|
+
counter = 0
|
|
56
|
+
while not self.is_interrupted:
|
|
57
|
+
# logger.debug("[Thread '{}'] New run".format(self.name))
|
|
58
|
+
try:
|
|
59
|
+
if self.does_need_run_loop():
|
|
60
|
+
with self._is_lock:
|
|
61
|
+
self._is_idle.clear()
|
|
62
|
+
self.__is_under_loop.set()
|
|
63
|
+
self.__loop_counter += 1
|
|
64
|
+
|
|
65
|
+
self.run_loop()
|
|
66
|
+
counter += 1
|
|
67
|
+
|
|
68
|
+
with self._is_lock:
|
|
69
|
+
self.__is_under_loop.clear()
|
|
70
|
+
self._is_idle.set()
|
|
71
|
+
|
|
72
|
+
# Stop if nb_times is reached
|
|
73
|
+
if self.__nb_times is not None:
|
|
74
|
+
if counter >= self.__nb_times:
|
|
75
|
+
break
|
|
76
|
+
|
|
77
|
+
if not self.__with_next_loop_datetime:
|
|
78
|
+
self.wait_between_run()
|
|
79
|
+
else:
|
|
80
|
+
time.sleep(self._get_sleep_time_before_next_loop())
|
|
81
|
+
|
|
82
|
+
except:
|
|
83
|
+
logger.exception(f"[Thread '{self.name}'] Exception catched during loop")
|
|
84
|
+
|
|
85
|
+
logger.info(f"Loop thread '{self.name}' has finished.")
|
|
86
|
+
|
|
87
|
+
def does_need_run_loop(self):
|
|
88
|
+
if self.__with_next_loop_datetime:
|
|
89
|
+
return DateTime.now() >= self.__next_loop_datetime
|
|
90
|
+
else:
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
def _get_sleep_time_before_next_loop(self):
|
|
94
|
+
if self.__with_next_loop_datetime:
|
|
95
|
+
now = DateTime.now()
|
|
96
|
+
if now < self.__next_loop_datetime:
|
|
97
|
+
delta = self.__next_loop_datetime - now
|
|
98
|
+
res = delta.total_seconds()
|
|
99
|
+
if res > 1:
|
|
100
|
+
return 1
|
|
101
|
+
else:
|
|
102
|
+
return res
|
|
103
|
+
return 0
|
|
104
|
+
|
|
105
|
+
def run_loop(self):
|
|
106
|
+
raise NotImplementedError()
|
|
107
|
+
|
|
108
|
+
def wait_is_under_loop(self, timeout=None):
|
|
109
|
+
self._wait(self.__is_under_loop, "is under loop", timeout=timeout)
|
|
110
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
from builtins import super
|
|
15
|
+
import logging
|
|
16
|
+
import threading
|
|
17
|
+
import time
|
|
18
|
+
from holado_multitask.multithreading.thread import InterruptableThread
|
|
19
|
+
from holado_multitask.multithreading.functionthreaded import FunctionThreaded
|
|
20
|
+
from holado_core.common.tools.tools import Tools
|
|
21
|
+
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
22
|
+
from holado.common.handlers.undefined import default_context
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PeriodicFunctionThreaded(InterruptableThread):
|
|
28
|
+
'''
|
|
29
|
+
Execute periodically in a thread given function with given arguments.
|
|
30
|
+
|
|
31
|
+
Implementation uses a precise timer, in order to globally satisfy the desired periodicity (with a precision of around a nanosecond, depending to system latency).
|
|
32
|
+
But implementation is quite simple, function is executed around each timer ticks : it is based on waits after function execution of the time needed to satisfy periodicity.
|
|
33
|
+
If function execution is greater than periodicity, a warning is logged, and function is run immediately without waiting next timer tick.
|
|
34
|
+
|
|
35
|
+
For fast periodicity, it is recommended to disable logs by setting property 'do_log' to False (and also 'do_log_warning' if needed).
|
|
36
|
+
'''
|
|
37
|
+
|
|
38
|
+
def __init__(self, period_seconds, target, args=None, kwargs=None, name=None, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, nb_times=None):
|
|
39
|
+
super().__init__(name if name is not None else f"PeriodicFunctionThreaded({repr(target)})", default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec, delay_between_run_sec=None)
|
|
40
|
+
|
|
41
|
+
self.__period_seconds = period_seconds
|
|
42
|
+
if self.__period_seconds < 1e-8:
|
|
43
|
+
raise TechnicalException(f"Periodicity must be at least 10ns")
|
|
44
|
+
self.__nb_times = nb_times
|
|
45
|
+
self.__function_threaded = FunctionThreaded(target, args, kwargs)
|
|
46
|
+
self.__do_log = True
|
|
47
|
+
self.__do_log_warning = True
|
|
48
|
+
|
|
49
|
+
if isinstance(self.__period_seconds, int) or self.__period_seconds % 1 < 1e-9 or self.__period_seconds % 1 > 1 - 1e-9:
|
|
50
|
+
self.__timer = Tools.timer_s
|
|
51
|
+
self.__timer_period = self.__period_seconds
|
|
52
|
+
self.__timer_unity = "s"
|
|
53
|
+
self.__timer_s_value = 1
|
|
54
|
+
else:
|
|
55
|
+
self.__timer = Tools.timer_ns
|
|
56
|
+
self.__timer_period = self.__period_seconds * 1e9
|
|
57
|
+
self.__timer_unity = "ns"
|
|
58
|
+
self.__timer_s_value = 1e9
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def function_threaded(self):
|
|
62
|
+
return self.__function_threaded
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
def do_log(self):
|
|
66
|
+
return self.__do_log
|
|
67
|
+
|
|
68
|
+
@do_log.setter
|
|
69
|
+
def do_log(self, do_log):
|
|
70
|
+
self.__do_log = do_log
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def do_log_warning(self):
|
|
74
|
+
return self.__do_log_warning
|
|
75
|
+
|
|
76
|
+
@do_log_warning.setter
|
|
77
|
+
def do_log_warning(self, do_log):
|
|
78
|
+
self.__do_log_warning = do_log
|
|
79
|
+
|
|
80
|
+
def run(self):
|
|
81
|
+
logger.info(f"[{self.name}] Thread managing periodic function.")
|
|
82
|
+
|
|
83
|
+
self.wait_before_run()
|
|
84
|
+
|
|
85
|
+
start = self.__timer()
|
|
86
|
+
count = 0
|
|
87
|
+
while not self.is_interrupted:
|
|
88
|
+
# Process function
|
|
89
|
+
if self.do_log:
|
|
90
|
+
logger.info(f"[{self.name}] Processing periodic iteration {count+1}...")
|
|
91
|
+
beg = self.__timer()
|
|
92
|
+
try:
|
|
93
|
+
self.__function_threaded.run()
|
|
94
|
+
except Exception as exc:
|
|
95
|
+
logger.exception(f"[{self.name}] Exception catched while processing function:\n [{repr(exc)}]")
|
|
96
|
+
finally:
|
|
97
|
+
count += 1
|
|
98
|
+
iter_dur = self.__timer() - beg
|
|
99
|
+
|
|
100
|
+
# Define next iteration timer
|
|
101
|
+
next_timer = start + count * self.__timer_period
|
|
102
|
+
wait_duration = next_timer - self.__timer()
|
|
103
|
+
skip_wait = wait_duration < 0
|
|
104
|
+
if skip_wait:
|
|
105
|
+
if self.do_log_warning:
|
|
106
|
+
logger.warning(f"[{self.name}] {count}'th iteration finished too late (of {-wait_duration} {self.__timer_unity}) to process next iteration on time (duration: {iter_dur} {self.__timer_unity} ; periodicity: {self.__timer_period} {self.__timer_unity}). Processing immediatelly next iteration")
|
|
107
|
+
|
|
108
|
+
while wait_duration + self.__timer_period < 0:
|
|
109
|
+
if self.do_log_warning:
|
|
110
|
+
logger.warning(f"[{self.name}] Failed to process {count+1}'th iteration, its activity period is passed")
|
|
111
|
+
count += 1
|
|
112
|
+
next_timer = start + count * self.__timer_period
|
|
113
|
+
wait_duration = next_timer - self.__timer()
|
|
114
|
+
|
|
115
|
+
# Stop if nb_times is reached
|
|
116
|
+
if self.__nb_times is not None:
|
|
117
|
+
if count >= self.__nb_times:
|
|
118
|
+
break
|
|
119
|
+
|
|
120
|
+
# Wait periodicity
|
|
121
|
+
if not skip_wait:
|
|
122
|
+
if self.do_log:
|
|
123
|
+
logger.info(f"[{self.name}] Waiting {wait_duration} {self.__timer_unity} to process next periodic function...")
|
|
124
|
+
while not self.is_interrupted and threading.active_count() > 0:
|
|
125
|
+
if wait_duration > 0.1 * self.__timer_s_value:
|
|
126
|
+
time.sleep(0.1)
|
|
127
|
+
wait_duration = next_timer - self.__timer()
|
|
128
|
+
else:
|
|
129
|
+
if wait_duration > 1e-9 * self.__timer_s_value:
|
|
130
|
+
time.sleep(wait_duration / self.__timer_s_value)
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
logger.info(f"[{self.name}] Thead of periodic function has finished.")
|
|
134
|
+
|
|
135
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import inspect
|
|
16
|
+
from holado_core.common.tools.tools import Tools
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_stack(limit=None, start=0):
|
|
20
|
+
"""
|
|
21
|
+
Get the call stack at the point of the caller.
|
|
22
|
+
|
|
23
|
+
@param limit: the number of frames to get (default: all remaining frames)
|
|
24
|
+
@param start: the offset of the first frame preceding the caller (default 0 means the method calling get_stack)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
# The call stack.
|
|
28
|
+
stack = inspect.stack()
|
|
29
|
+
|
|
30
|
+
# The index of the first frame to print.
|
|
31
|
+
begin = start + 1
|
|
32
|
+
if limit:
|
|
33
|
+
end = min(begin + limit, len(stack))
|
|
34
|
+
else:
|
|
35
|
+
end = len(stack)
|
|
36
|
+
|
|
37
|
+
return stack[begin:end]
|
|
38
|
+
|
|
39
|
+
def represent_stack(limit=None, start=0, indent=0):
|
|
40
|
+
res_list = []
|
|
41
|
+
for frame in get_stack(limit, start+1):
|
|
42
|
+
file, line, func = frame[1:4]
|
|
43
|
+
res_list.append(f"{file}, line {line} in function {func}")
|
|
44
|
+
return Tools.indent_string(indent, "\n".join(res_list))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def get_current_function_name(offset=0):
|
|
19
|
+
"""
|
|
20
|
+
Get the name of the function at the point of the caller.
|
|
21
|
+
|
|
22
|
+
@param offset: the offset of the target function (default 0 means the method calling get_current_function_name)
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
frame = sys._getframe(1 + offset)
|
|
26
|
+
return frame.f_code.co_name
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import traceback
|
|
16
|
+
from holado_core.common.tools.tools import Tools
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_stack(limit=None, start=0):
|
|
20
|
+
"""
|
|
21
|
+
Get the call stack at the point of the caller.
|
|
22
|
+
|
|
23
|
+
@param limit: the number of frames to get (default: all remaining frames)
|
|
24
|
+
@param start: the offset of the first frame preceding the caller (default 0 means the method calling get_stack)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
stack = traceback.extract_stack(limit=limit+2 if limit is not None else None)
|
|
28
|
+
return stack[:-1-start]
|
|
29
|
+
|
|
30
|
+
def represent_stack(limit=None, start=0, indent=0):
|
|
31
|
+
frames = get_stack(limit, start+1)
|
|
32
|
+
return Tools.indent_string(indent, "".join(traceback.format_list(frames)))
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
import threading
|
|
15
|
+
from holado.holado_config import Config
|
|
16
|
+
import logging
|
|
17
|
+
from holado.common.context.session_context import SessionContext
|
|
18
|
+
import time
|
|
19
|
+
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
20
|
+
from holado_python.standard_library.typing import Typing
|
|
21
|
+
from holado.common.handlers.undefined import undefined_argument, default_context
|
|
22
|
+
from holado_core.common.exceptions.technical_exception import TimeoutTechnicalException
|
|
23
|
+
from holado_core.common.exceptions.functional_exception import FunctionalException
|
|
24
|
+
from holado_python.common.tools.datetime import DateTime, FORMAT_DATETIME_ISO
|
|
25
|
+
from holado.common.handlers.object import DeleteableObject
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Thread(threading.Thread, DeleteableObject):
|
|
31
|
+
""" Helper class managing a thread."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, name, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, delay_between_run_sec=None):
|
|
34
|
+
threading.Thread.__init__(self)
|
|
35
|
+
DeleteableObject.__init__(self, name)
|
|
36
|
+
|
|
37
|
+
if default_wait_timeout is None:
|
|
38
|
+
default_wait_timeout = Config.timeout_seconds * 1000
|
|
39
|
+
|
|
40
|
+
# Note: if SessionContext doesn't have an instance (like during session context reset), use name+now as unique name
|
|
41
|
+
self.__unique_name = SessionContext.instance().multitask_manager.prepare_thread(name) if SessionContext.has_instance() else f"{name}_{DateTime.datetime_2_str(DateTime.now(), FORMAT_DATETIME_ISO)}"
|
|
42
|
+
self.__default_wait_timeout = default_wait_timeout
|
|
43
|
+
self.__delay_before_run_sec = delay_before_run_sec
|
|
44
|
+
self.__delay_between_run_sec = delay_between_run_sec
|
|
45
|
+
|
|
46
|
+
# Put thread as daemon
|
|
47
|
+
self.daemon = True
|
|
48
|
+
|
|
49
|
+
# Manage thread status
|
|
50
|
+
self._is_lock = threading.Lock()
|
|
51
|
+
self._is_idle = threading.Event()
|
|
52
|
+
self._is_idle.set()
|
|
53
|
+
|
|
54
|
+
# Register thread
|
|
55
|
+
# Note: Do not register thread if session context doesn't have an instance (like during session context reset)
|
|
56
|
+
self.__is_registered = False
|
|
57
|
+
self.__register_scope = None
|
|
58
|
+
if register_thread and SessionContext.has_instance():
|
|
59
|
+
# Registered name has to be unique
|
|
60
|
+
SessionContext.instance().threads_manager.register_thread(self.__unique_name, self, scope=register_scope)
|
|
61
|
+
self.__is_registered = True
|
|
62
|
+
self.__register_scope = register_scope
|
|
63
|
+
self.on_delete_call_func(self.__unregister_thread)
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def unique_name(self):
|
|
67
|
+
return self.__unique_name
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def default_wait_timeout(self):
|
|
71
|
+
return self.__default_wait_timeout
|
|
72
|
+
|
|
73
|
+
@default_wait_timeout.setter
|
|
74
|
+
def default_wait_timeout(self, timeout):
|
|
75
|
+
self.__default_wait_timeout = timeout
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def delay_before_run_seconds(self):
|
|
79
|
+
return self.__delay_before_run_sec
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def delay_between_run_seconds(self):
|
|
83
|
+
return self.__delay_between_run_sec
|
|
84
|
+
|
|
85
|
+
def _set_ident(self):
|
|
86
|
+
super()._set_ident()
|
|
87
|
+
if not MultitaskManager.has_thread_native_id() and SessionContext.has_instance():
|
|
88
|
+
SessionContext.instance().multitask_manager.set_thread_uid(self.__unique_name, MultitaskManager.get_thread_uid(thread=self))
|
|
89
|
+
|
|
90
|
+
if MultitaskManager.has_thread_native_id():
|
|
91
|
+
def _set_native_id(self):
|
|
92
|
+
super()._set_native_id()
|
|
93
|
+
if SessionContext.has_instance():
|
|
94
|
+
SessionContext.instance().multitask_manager.set_thread_uid(self.__unique_name, MultitaskManager.get_thread_uid(thread=self))
|
|
95
|
+
|
|
96
|
+
def join(self, timeout=undefined_argument, raise_if_still_alive=True):
|
|
97
|
+
"""
|
|
98
|
+
See Thread.join documentation for default behavior.
|
|
99
|
+
|
|
100
|
+
This implementation returns if join succeeded, ie if thread is still alive after join.
|
|
101
|
+
|
|
102
|
+
This implementation also tries to avoid deadlocks by special and default timeout value undefined_argument.
|
|
103
|
+
With any other timeout value, including None, default behavior is happening.
|
|
104
|
+
If timeout argument is undefined_argument, it means that it should stop by itself without deadlock.
|
|
105
|
+
In this case, a timeout value Config.join_timeout_seconds is used.
|
|
106
|
+
|
|
107
|
+
If argument raise_if_still_alive is True (default) after join and if thread is still alive after join, an exception is raised.
|
|
108
|
+
If timeout is undefined_argument, a TimeoutTechnicalException is raised, else a FunctionalException.
|
|
109
|
+
"""
|
|
110
|
+
timeout_str = "long and finite" if timeout is undefined_argument else f"{timeout}s" if timeout else "none"
|
|
111
|
+
logger.debug(f"Joining thread '{self.name}' ; timeout={timeout_str} ...")
|
|
112
|
+
|
|
113
|
+
real_timeout = timeout if timeout is not undefined_argument else Config.join_timeout_seconds
|
|
114
|
+
super().join(real_timeout)
|
|
115
|
+
|
|
116
|
+
logger.debug(f"End of joining thread '{self.name}' ; timeout={timeout_str} ; alive:{self.is_alive()}")
|
|
117
|
+
|
|
118
|
+
if self.is_alive():
|
|
119
|
+
if raise_if_still_alive:
|
|
120
|
+
if timeout is undefined_argument:
|
|
121
|
+
raise TimeoutTechnicalException(f"Thread '{self.name}' is still alive after join (timeout: {real_timeout} s)")
|
|
122
|
+
else:
|
|
123
|
+
raise FunctionalException(f"Thread '{self.name}' is still alive after join (timeout: {real_timeout} s)")
|
|
124
|
+
else:
|
|
125
|
+
logger.error(f"Thread '{self.name}' is still alive after join (timeout: {real_timeout} s)")
|
|
126
|
+
|
|
127
|
+
return self.is_alive()
|
|
128
|
+
|
|
129
|
+
def wait_before_run(self, do_log_exception=True):
|
|
130
|
+
if self.delay_before_run_seconds is not None:
|
|
131
|
+
try:
|
|
132
|
+
time.sleep(self.delay_before_run_seconds)
|
|
133
|
+
except Exception:
|
|
134
|
+
if do_log_exception:
|
|
135
|
+
logger.exception(f"[Thread '{self.name}'] Exception while waiting delay before run (delay: {self.delay_before_run_seconds} ; type: {Typing.get_object_class_fullname(self.delay_before_run_seconds)})")
|
|
136
|
+
|
|
137
|
+
def wait_between_run(self, do_log_exception=True):
|
|
138
|
+
if self.delay_between_run_seconds is not None:
|
|
139
|
+
try:
|
|
140
|
+
time.sleep(self.delay_between_run_seconds)
|
|
141
|
+
except Exception:
|
|
142
|
+
if do_log_exception:
|
|
143
|
+
logger.exception(f"[Thread '{self.name}'] Exception while waiting delay between run (delay: {self.delay_between_run_seconds} ; type: {Typing.get_object_class_fullname(self.delay_between_run_seconds)})")
|
|
144
|
+
|
|
145
|
+
def wait_is_idle(self, timeout=None):
|
|
146
|
+
""" Wait event self._is_idle"""
|
|
147
|
+
self._wait(self.__is_idle, "is idle", timeout=timeout)
|
|
148
|
+
|
|
149
|
+
def _wait(self, event, event_details, timeout=None):
|
|
150
|
+
""" Wait given threading.Event"""
|
|
151
|
+
is_set = False
|
|
152
|
+
wait_round_counter = 0
|
|
153
|
+
round_wait_seconds = 1
|
|
154
|
+
if timeout is None:
|
|
155
|
+
timeout = self.__default_wait_timeout
|
|
156
|
+
|
|
157
|
+
logger.debug("[{}] Waiting {}...".format(self.name, event_details))
|
|
158
|
+
while not is_set:
|
|
159
|
+
wait_round_counter += 1
|
|
160
|
+
is_set = event.wait(round_wait_seconds)
|
|
161
|
+
|
|
162
|
+
if not is_set:
|
|
163
|
+
if wait_round_counter * round_wait_seconds * 1000 > timeout:
|
|
164
|
+
raise TimeoutError("[{}] Timeout when waiting {}".format(self.name, event_details))
|
|
165
|
+
elif wait_round_counter % 10 == 0:
|
|
166
|
+
logger.debug("[{}] Still waiting {} (round {})".format(self.name, event_details, wait_round_counter))
|
|
167
|
+
logger.debug("[{}] Finished waiting {}...".format(self.name, event_details))
|
|
168
|
+
|
|
169
|
+
def __unregister_thread(self):
|
|
170
|
+
if self.__is_registered:
|
|
171
|
+
if SessionContext.instance().threads_manager.is_thread_registered(self.__unique_name, scope=self.__register_scope):
|
|
172
|
+
SessionContext.instance().threads_manager.unregister_thread(self.__unique_name, scope=self.__register_scope)
|
|
173
|
+
self.__is_registered = False
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class InterruptableThread(Thread):
|
|
177
|
+
""" Helper class managing a thread interruptable."""
|
|
178
|
+
|
|
179
|
+
def __init__(self, name, default_wait_timeout=None, register_thread=True, register_scope=default_context, delay_before_run_sec=None, delay_between_run_sec=None):
|
|
180
|
+
super().__init__(name, default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec, delay_between_run_sec=delay_between_run_sec)
|
|
181
|
+
|
|
182
|
+
# Manage interrupt
|
|
183
|
+
self.__interrupt_lock = threading.Lock()
|
|
184
|
+
self.__interrupt_event = threading.Event()
|
|
185
|
+
|
|
186
|
+
@property
|
|
187
|
+
def is_interruptable(self):
|
|
188
|
+
return True
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def is_interrupted(self):
|
|
192
|
+
with self.__interrupt_lock:
|
|
193
|
+
return self.__interrupt_event.is_set()
|
|
194
|
+
|
|
195
|
+
def interrupt(self):
|
|
196
|
+
if not self.is_interrupted:
|
|
197
|
+
logger.debug("Interrupt thread '{}'".format(self.name))
|
|
198
|
+
with self.__interrupt_lock:
|
|
199
|
+
self.__interrupt_event.set()
|
|
200
|
+
|
|
201
|
+
def _raise_if_interrupted(self):
|
|
202
|
+
if self.is_interrupted:
|
|
203
|
+
raise InterruptedError
|