holado 0.2.1__py3-none-any.whl → 0.2.3__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.

Potentially problematic release.


This version of holado might be problematic. Click here for more details.

Files changed (524) hide show
  1. holado/__init__.py +8 -4
  2. {holado-0.2.1.dist-info → holado-0.2.3.dist-info}/METADATA +13 -9
  3. holado-0.2.3.dist-info/RECORD +535 -0
  4. holado_ais/__init__.py +33 -0
  5. holado_ais/ais/MaritimeIdentificationDigits.csv +295 -0
  6. holado_ais/ais/ais_manager.py +151 -0
  7. holado_ais/ais/ais_messages.py +203 -0
  8. holado_ais/ais/ais_payload.py +35 -0
  9. holado_ais/ais/enums.py +37 -0
  10. holado_ais/ais/patch_pyais.py +1303 -0
  11. holado_ais/tests/behave/steps/__init__.py +17 -0
  12. holado_ais/tests/behave/steps/ais/__init__.py +0 -0
  13. holado_ais/tests/behave/steps/ais/ais_manager_steps.py +50 -0
  14. holado_ais/tests/behave/steps/ais/ais_messages_steps.py +182 -0
  15. holado_binary/__init__.py +17 -0
  16. holado_binary/ipc/binary.py +125 -0
  17. holado_binary/ipc/bit_series.py +307 -0
  18. holado_binary/tests/behave/steps/__init__.py +17 -0
  19. holado_binary/tests/behave/steps/ipc/binary_steps.py +57 -0
  20. holado_binary/tests/behave/steps/ipc/bit_series_steps.py +131 -0
  21. holado_context/__init__.py +16 -0
  22. holado_context/tests/behave/steps/__init__.py +16 -0
  23. holado_context/tests/behave/steps/private/__init__.py +16 -0
  24. holado_context/tests/behave/steps/private/common/context_steps.py +36 -0
  25. holado_core/__init__.py +32 -0
  26. holado_core/common/__init__.py +0 -0
  27. holado_core/common/actors/actions.py +97 -0
  28. holado_core/common/actors/actor.py +226 -0
  29. holado_core/common/actors/element_actor.py +32 -0
  30. holado_core/common/actors/find_actor.py +106 -0
  31. holado_core/common/actors/tree_actor.py +32 -0
  32. holado_core/common/actors/verify_actions.py +69 -0
  33. holado_core/common/block/base.py +122 -0
  34. holado_core/common/block/block_manager.py +173 -0
  35. holado_core/common/block/block_method.py +46 -0
  36. holado_core/common/block/block_steps.py +37 -0
  37. holado_core/common/block/function.py +42 -0
  38. holado_core/common/block/scope_function.py +28 -0
  39. holado_core/common/block/scope_manager.py +238 -0
  40. holado_core/common/block/scope_steps.py +141 -0
  41. holado_core/common/criterias/and_criteria.py +61 -0
  42. holado_core/common/criterias/criteria.py +78 -0
  43. holado_core/common/criterias/or_criteria.py +64 -0
  44. holado_core/common/criterias/tools/criteria_context.py +20 -0
  45. holado_core/common/criterias/tools/criteria_parameters.py +18 -0
  46. holado_core/common/drivers/driver.py +153 -0
  47. holado_core/common/drivers/element_driver.py +30 -0
  48. holado_core/common/drivers/element_internal_api.py +239 -0
  49. holado_core/common/drivers/internal_api.py +40 -0
  50. holado_core/common/drivers/tree_driver.py +30 -0
  51. holado_core/common/drivers/tree_internal_api.py +176 -0
  52. holado_core/common/exceptions/__init__.py +0 -0
  53. holado_core/common/exceptions/element_exception.py +28 -0
  54. holado_core/common/exceptions/exceptions.py +24 -0
  55. holado_core/common/exceptions/functional_exception.py +21 -0
  56. holado_core/common/exceptions/holado_exception.py +25 -0
  57. holado_core/common/exceptions/technical_exception.py +27 -0
  58. holado_core/common/exceptions/timeout_exception.py +20 -0
  59. holado_core/common/exceptions/verify_exception.py +20 -0
  60. holado_core/common/finders/after_in_tree_finder.py +87 -0
  61. holado_core/common/finders/element_finder.py +60 -0
  62. holado_core/common/finders/else_finder.py +105 -0
  63. holado_core/common/finders/finder.py +478 -0
  64. holado_core/common/finders/or_finder.py +98 -0
  65. holado_core/common/finders/then_finder.py +157 -0
  66. holado_core/common/finders/tools/enums.py +30 -0
  67. holado_core/common/finders/tools/find_builder.py +118 -0
  68. holado_core/common/finders/tools/find_context.py +405 -0
  69. holado_core/common/finders/tools/find_info.py +27 -0
  70. holado_core/common/finders/tools/find_parameters.py +240 -0
  71. holado_core/common/finders/tools/find_updater.py +95 -0
  72. holado_core/common/finders/tools/finder_info.py +26 -0
  73. holado_core/common/finders/tree_finder.py +146 -0
  74. holado_core/common/handlers/__init__.py +0 -0
  75. holado_core/common/handlers/abstracts/base_redo.py +695 -0
  76. holado_core/common/handlers/abstracts/get_or_create.py +120 -0
  77. holado_core/common/handlers/element_holder.py +122 -0
  78. holado_core/common/handlers/enums.py +23 -0
  79. holado_core/common/handlers/exceptions/redo_exceptions.py +28 -0
  80. holado_core/common/handlers/features/resource_by_name.py +187 -0
  81. holado_core/common/handlers/features/resource_by_type.py +174 -0
  82. holado_core/common/handlers/redo.py +119 -0
  83. holado_core/common/handlers/wait.py +127 -0
  84. holado_core/common/inspectors/element_inspector.py +57 -0
  85. holado_core/common/inspectors/inspector.py +221 -0
  86. holado_core/common/inspectors/tools/inspect_builder.py +169 -0
  87. holado_core/common/inspectors/tools/inspect_context.py +69 -0
  88. holado_core/common/inspectors/tools/inspect_parameters.py +181 -0
  89. holado_core/common/inspectors/tree_inspector.py +73 -0
  90. holado_core/common/resource/persisted_data_manager.py +113 -0
  91. holado_core/common/resource/persisted_method_to_call_manager.py +133 -0
  92. holado_core/common/resource/resource_manager.py +143 -0
  93. holado_core/common/tables/__init__.py +1 -0
  94. holado_core/common/tables/comparators/__init__.py +0 -0
  95. holado_core/common/tables/comparators/boolean_table_cell_comparator.py +25 -0
  96. holado_core/common/tables/comparators/bytes_table_cell_comparator.py +25 -0
  97. holado_core/common/tables/comparators/datetime_table_cell_comparator.py +24 -0
  98. holado_core/common/tables/comparators/float_table_cell_comparator.py +31 -0
  99. holado_core/common/tables/comparators/integer_table_cell_comparator.py +25 -0
  100. holado_core/common/tables/comparators/internal_table_cell_comparator.py +30 -0
  101. holado_core/common/tables/comparators/string_table_cell_comparator.py +24 -0
  102. holado_core/common/tables/comparators/string_table_comparator.py +29 -0
  103. holado_core/common/tables/comparators/string_table_row_comparator.py +29 -0
  104. holado_core/common/tables/comparators/table_cell_comparator.py +40 -0
  105. holado_core/common/tables/comparators/table_comparator.py +209 -0
  106. holado_core/common/tables/comparators/table_comparator_manager.py +60 -0
  107. holado_core/common/tables/comparators/table_row_comparator.py +116 -0
  108. holado_core/common/tables/comparators/table_with_header_comparator.py +68 -0
  109. holado_core/common/tables/converters/__init__.py +0 -0
  110. holado_core/common/tables/converters/table_converter.py +194 -0
  111. holado_core/common/tables/enums.py +23 -0
  112. holado_core/common/tables/table.py +261 -0
  113. holado_core/common/tables/table_cell.py +126 -0
  114. holado_core/common/tables/table_manager.py +366 -0
  115. holado_core/common/tables/table_row.py +169 -0
  116. holado_core/common/tables/table_with_header.py +236 -0
  117. holado_core/common/tools/__init__.py +0 -0
  118. holado_core/common/tools/comparators/comparator.py +151 -0
  119. holado_core/common/tools/comparators/object_comparator.py +21 -0
  120. holado_core/common/tools/converters/converter.py +107 -0
  121. holado_core/common/tools/path_manager.py +185 -0
  122. holado_core/common/tools/string_tools.py +135 -0
  123. holado_core/common/tools/tools.py +172 -0
  124. holado_core/common/transport/__init__.py +0 -0
  125. holado_core/common/transport/crc.py +40 -0
  126. holado_core/tests/behave/steps/__init__.py +20 -0
  127. holado_core/tests/behave/steps/common/__init__.py +0 -0
  128. holado_core/tests/behave/steps/common/common_steps.py +136 -0
  129. holado_core/tests/behave/steps/common/config_steps.py +42 -0
  130. holado_core/tests/behave/steps/common/resource_steps.py +62 -0
  131. holado_core/tests/behave/steps/common/tables_steps.py +537 -0
  132. holado_core/tools/__init__.py +0 -0
  133. holado_core/tools/abstracts/__init__.py +0 -0
  134. holado_core/tools/abstracts/blocking_command_service.py +56 -0
  135. holado_core/tools/abstracts/service.py +48 -0
  136. holado_data/__init__.py +31 -0
  137. holado_data/data/generator/base.py +93 -0
  138. holado_data/data/generator/python_generator.py +30 -0
  139. holado_data/tests/behave/steps/__init__.py +17 -0
  140. holado_data/tests/behave/steps/data/generator_steps.py +91 -0
  141. holado_data/tests/behave/steps/tools/utils_steps.py +60 -0
  142. holado_db/__init__.py +32 -0
  143. holado_db/tests/behave/steps/__init__.py +18 -0
  144. holado_db/tests/behave/steps/tools/db/db_client_steps.py +134 -0
  145. holado_db/tests/behave/steps/tools/db/postgresql_client_steps.py +59 -0
  146. holado_db/tests/behave/steps/tools/db/sqlite_client_steps.py +57 -0
  147. holado_db/tools/db/clients/base/db_client.py +206 -0
  148. holado_db/tools/db/clients/postgresql/postgresql_client.py +65 -0
  149. holado_db/tools/db/clients/sqlite/sqlite_client.py +56 -0
  150. holado_db/tools/db/db_manager.py +109 -0
  151. holado_db/tools/db/query/base/query_builder.py +87 -0
  152. holado_db/tools/db/query/pypika/pypika_query_builder.py +193 -0
  153. holado_db/tools/db/query/query_manager.py +77 -0
  154. holado_docker/__init__.py +25 -0
  155. holado_docker/sdk/docker/docker_client.py +268 -0
  156. holado_docker/sdk/docker/docker_service.py +71 -0
  157. holado_docker/tests/behave/steps/__init__.py +16 -0
  158. holado_docker/tests/behave/steps/tools/docker_steps.py +33 -0
  159. holado_docker/tools/docker_controler/__init__.py +26 -0
  160. holado_docker/tools/docker_controler/docker_controler_client.py +36 -0
  161. holado_docker/tools/docker_controler/docker_controler_server.py +31 -0
  162. holado_docker/tools/docker_controler/proto/compile_proto.py +60 -0
  163. holado_docker/tools/docker_controler/proto/definitions/docker_controler.proto +63 -0
  164. holado_docker/tools/docker_controler/proto/generated/docker_controler_pb2.py +52 -0
  165. holado_docker/tools/docker_controler/proto/generated/docker_controler_pb2_grpc.py +233 -0
  166. holado_grpc/__init__.py +32 -0
  167. holado_grpc/api/rpc/TODO.txt +4 -0
  168. holado_grpc/api/rpc/grpc_client.py +181 -0
  169. holado_grpc/api/rpc/grpc_manager.py +81 -0
  170. holado_grpc/ipc/rpc/__init__.py +0 -0
  171. holado_grpc/ipc/rpc/grpc_compiler.py +45 -0
  172. holado_grpc/ipc/rpc/grpc_services.py +165 -0
  173. holado_grpc/tests/behave/steps/__init__.py +16 -0
  174. holado_grpc/tests/behave/steps/api/grpc_client_steps.py +173 -0
  175. holado_grpc/tests/behave/steps/private/__init__.py +16 -0
  176. holado_grpc/tests/behave/steps/private/api/grpc_steps.py +77 -0
  177. holado_helper/__init__.py +35 -0
  178. holado_helper/debug/README.txt +32 -0
  179. holado_helper/debug/memory/memory_profiler.py +106 -0
  180. holado_helper/docker/init_user.sh +24 -0
  181. holado_helper/docker/logging.conf +42 -0
  182. holado_helper/docker/run_holado_test_nonreg_in_docker.sh +120 -0
  183. holado_helper/docker/run_terminal_in_docker-with_docker_control.sh +103 -0
  184. holado_helper/docker/run_terminal_in_docker.sh +101 -0
  185. holado_helper/holado_module_template/__init__.py +31 -0
  186. holado_helper/holado_module_template/test/behave/steps/__init__.py +16 -0
  187. holado_helper/holado_module_template/test/behave/steps/private/__init__.py +16 -0
  188. holado_helper/script/action.py +109 -0
  189. holado_helper/script/action_script.py +477 -0
  190. holado_helper/script/any_action_script.py +126 -0
  191. holado_helper/script/behave_action_script.py +99 -0
  192. holado_helper/script/csv_action_script.py +142 -0
  193. holado_helper/script/initialize_script.py +115 -0
  194. holado_helper/script/input_output_script.py +136 -0
  195. holado_helper/script/job.py +75 -0
  196. holado_helper/script/json_action_script.py +104 -0
  197. holado_helper/script/script.py +110 -0
  198. holado_json/__init__.py +16 -0
  199. holado_json/ipc/json.py +125 -0
  200. holado_json/ipc/json_converter.py +69 -0
  201. holado_json/ipc/json_types.py +183 -0
  202. holado_json/tests/behave/steps/__init__.py +16 -0
  203. holado_json/tests/behave/steps/ipc/__init__.py +0 -0
  204. holado_json/tests/behave/steps/ipc/json_steps.py +120 -0
  205. holado_keycloak/__init__.py +16 -0
  206. holado_keycloak/tests/behave/steps/__init__.py +16 -0
  207. holado_keycloak/tests/behave/steps/tools/keycloak_client_steps.py +59 -0
  208. holado_keycloak/tools/keycloak/__init__.py +0 -0
  209. holado_keycloak/tools/keycloak/keycloak_client.py +61 -0
  210. holado_logging/__init__.py +36 -0
  211. holado_logging/common/logging/holado_logger.py +75 -0
  212. holado_logging/common/logging/log_config.py +128 -0
  213. holado_logging/common/logging/log_manager.py +292 -0
  214. holado_multitask/__init__.py +33 -0
  215. holado_multitask/multiprocessing/context/process_context.py +35 -0
  216. holado_multitask/multiprocessing/function_process.py +102 -0
  217. holado_multitask/multiprocessing/periodic_function_process.py +135 -0
  218. holado_multitask/multiprocessing/process.py +196 -0
  219. holado_multitask/multiprocessing/processesmanager.py +133 -0
  220. holado_multitask/multitasking/multitask_manager.py +439 -0
  221. holado_multitask/multithreading/__init__.py +0 -0
  222. holado_multitask/multithreading/context/thread_context.py +84 -0
  223. holado_multitask/multithreading/functionthreaded.py +129 -0
  224. holado_multitask/multithreading/loopfunctionthreaded.py +45 -0
  225. holado_multitask/multithreading/loopthread.py +100 -0
  226. holado_multitask/multithreading/periodicfunctionthreaded.py +136 -0
  227. holado_multitask/multithreading/reflection/inspect.py +47 -0
  228. holado_multitask/multithreading/reflection/sys.py +29 -0
  229. holado_multitask/multithreading/reflection/traceback.py +35 -0
  230. holado_multitask/multithreading/thread.py +177 -0
  231. holado_multitask/multithreading/threadsmanager.py +162 -0
  232. holado_multitask/multithreading/timer.py +48 -0
  233. holado_multitask/tests/behave/steps/__init__.py +17 -0
  234. holado_multitask/tests/behave/steps/multiprocessing_steps.py +138 -0
  235. holado_multitask/tests/behave/steps/multithreading_steps.py +129 -0
  236. holado_protobuf/__init__.py +61 -0
  237. holado_protobuf/ipc/protobuf/__init__.py +0 -0
  238. holado_protobuf/ipc/protobuf/abstracts/type.py +45 -0
  239. holado_protobuf/ipc/protobuf/protobuf_compiler.py +118 -0
  240. holado_protobuf/ipc/protobuf/protobuf_converter.py +153 -0
  241. holado_protobuf/ipc/protobuf/protobuf_messages.py +965 -0
  242. holado_protobuf/ipc/protobuf/protobuf_modifier.py +65 -0
  243. holado_protobuf/ipc/protobuf/types/__init__.py +0 -0
  244. holado_protobuf/ipc/protobuf/types/google/__init__.py +0 -0
  245. holado_protobuf/ipc/protobuf/types/google/protobuf.py +124 -0
  246. holado_protobuf/tests/behave/steps/__init__.py +16 -0
  247. holado_protobuf/tests/behave/steps/ipc/protobuf_steps.py +297 -0
  248. holado_python/__init__.py +35 -0
  249. holado_python/common/enums.py +34 -0
  250. holado_python/common/iterables.py +30 -0
  251. holado_python/common/tools/comparators/boolean_comparator.py +37 -0
  252. holado_python/common/tools/comparators/bytes_comparator.py +48 -0
  253. holado_python/common/tools/comparators/datetime_comparator.py +74 -0
  254. holado_python/common/tools/comparators/float_comparator.py +97 -0
  255. holado_python/common/tools/comparators/integer_comparator.py +37 -0
  256. holado_python/common/tools/comparators/string_comparator.py +99 -0
  257. holado_python/common/tools/comparators/type_comparator.py +31 -0
  258. holado_python/common/tools/datetime.py +279 -0
  259. holado_python/standard_library/csv.py +207 -0
  260. holado_python/standard_library/hashlib.py +82 -0
  261. holado_python/standard_library/multiprocessing.py +62 -0
  262. holado_python/standard_library/queue.py +79 -0
  263. holado_python/standard_library/socket/blocking_socket.py +136 -0
  264. holado_python/standard_library/socket/echo_server.py +28 -0
  265. holado_python/standard_library/socket/message_socket.py +91 -0
  266. holado_python/standard_library/socket/non_blocking_socket.py +151 -0
  267. holado_python/standard_library/socket/socket.py +148 -0
  268. holado_python/standard_library/ssl/resources/certificates/NOTES.txt +5 -0
  269. holado_python/standard_library/ssl/resources/certificates/localhost.crt +19 -0
  270. holado_python/standard_library/ssl/resources/certificates/localhost.key +28 -0
  271. holado_python/standard_library/ssl/ssl.py +81 -0
  272. holado_python/standard_library/typing.py +192 -0
  273. holado_python/tests/behave/steps/__init__.py +27 -0
  274. holado_python/tests/behave/steps/builtins/str_steps.py +45 -0
  275. holado_python/tests/behave/steps/convert_steps.py +59 -0
  276. holado_python/tests/behave/steps/iterable_steps.py +87 -0
  277. holado_python/tests/behave/steps/standard_library/csv_steps.py +134 -0
  278. holado_python/tests/behave/steps/standard_library/datetime_steps.py +163 -0
  279. holado_python/tests/behave/steps/standard_library/hashlib_steps.py +57 -0
  280. holado_python/tests/behave/steps/standard_library/multiprocessing_steps.py +56 -0
  281. holado_python/tests/behave/steps/standard_library/queue_steps.py +358 -0
  282. holado_python/tests/behave/steps/standard_library/socket_steps.py +258 -0
  283. holado_python/tests/behave/steps/standard_library/ssl_steps.py +67 -0
  284. holado_rabbitmq/__init__.py +28 -0
  285. holado_rabbitmq/tests/behave/steps/__init__.py +17 -0
  286. holado_rabbitmq/tests/behave/steps/tools/rabbitmq_client_steps.py +537 -0
  287. holado_rabbitmq/tests/behave/steps/tools/rabbitmq_server_steps.py +64 -0
  288. holado_rabbitmq/tools/rabbitmq/rabbitmq_blocking_client.py +311 -0
  289. holado_rabbitmq/tools/rabbitmq/rabbitmq_client.py +675 -0
  290. holado_rabbitmq/tools/rabbitmq/rabbitmq_manager.py +173 -0
  291. holado_rabbitmq/tools/rabbitmq/rabbitmq_select_client.py +428 -0
  292. holado_rabbitmq/tools/rabbitmq/rabbitmq_server.py +24 -0
  293. holado_redis/__init__.py +17 -0
  294. holado_redis/tests/behave/steps/__init__.py +16 -0
  295. holado_redis/tests/behave/steps/tools/redis_client_steps.py +101 -0
  296. holado_redis/tools/redis/TODO.txt +7 -0
  297. holado_redis/tools/redis/redis_client.py +190 -0
  298. holado_redis/tools/redis/redis_manager.py +38 -0
  299. holado_report/__init__.py +27 -0
  300. holado_report/report/analyze/execution_historic_manager.py +96 -0
  301. holado_report/report/analyze/scenario_duration_manager.py +245 -0
  302. holado_report/report/builders/detailed_scenario_failed_report_builder.py +146 -0
  303. holado_report/report/builders/json_execution_historic_report_builder.py +123 -0
  304. holado_report/report/builders/report_builder.py +64 -0
  305. holado_report/report/builders/short_scenario_failed_report_builder.py +76 -0
  306. holado_report/report/builders/summary_report_builder.py +89 -0
  307. holado_report/report/builders/summary_scenario_failed_report_builder.py +56 -0
  308. holado_report/report/builders/summary_scenario_report_builder.py +74 -0
  309. holado_report/report/execution_historic.py +141 -0
  310. holado_report/report/report_manager.py +256 -0
  311. holado_report/report/reports/base_report.py +163 -0
  312. holado_report/report/reports/feature_report.py +106 -0
  313. holado_report/report/reports/scenario_report.py +64 -0
  314. holado_rest/__init__.py +24 -0
  315. holado_rest/api/rest/TODO.txt +2 -0
  316. holado_rest/api/rest/rest_client.py +113 -0
  317. holado_rest/api/rest/rest_manager.py +62 -0
  318. holado_rest/tests/behave/steps/__init__.py +16 -0
  319. holado_rest/tests/behave/steps/api/__init__.py +0 -0
  320. holado_rest/tests/behave/steps/api/rest_client_steps.py +141 -0
  321. holado_rest/tests/behave/steps/private/__init__.py +16 -0
  322. holado_rest/tests/behave/steps/private/api/__init__.py +0 -0
  323. holado_rest/tests/behave/steps/private/api/rest_steps.py +70 -0
  324. holado_s3/__init__.py +17 -0
  325. holado_s3/tests/behave/steps/__init__.py +17 -0
  326. holado_s3/tests/behave/steps/private/__init__.py +16 -0
  327. holado_s3/tests/behave/steps/private/tools/s3_steps.py +89 -0
  328. holado_s3/tests/behave/steps/tools/s3_client_steps.py +403 -0
  329. holado_s3/tests/behave/steps/tools/s3_server_steps.py +57 -0
  330. holado_s3/tools/s3/__init__.py +0 -0
  331. holado_s3/tools/s3/boto3_s3_client.py +59 -0
  332. holado_s3/tools/s3/minio_client.py +75 -0
  333. holado_s3/tools/s3/moto_server.py +52 -0
  334. holado_scripting/__init__.py +53 -0
  335. holado_scripting/common/tools/dynamic_text_manager.py +73 -0
  336. holado_scripting/common/tools/evaluate_parameters.py +210 -0
  337. holado_scripting/common/tools/expression_evaluator.py +387 -0
  338. holado_scripting/common/tools/variable_manager.py +321 -0
  339. holado_scripting/tests/behave/steps/__init__.py +22 -0
  340. holado_scripting/tests/behave/steps/common/tools/variable_convert_steps.py +158 -0
  341. holado_scripting/tests/behave/steps/common/tools/variable_new_steps.py +130 -0
  342. holado_scripting/tests/behave/steps/common/tools/variable_steps.py +108 -0
  343. holado_scripting/tests/behave/steps/common/tools/variable_verify_steps.py +160 -0
  344. holado_scripting/tests/behave/steps/scenario/function_steps.py +77 -0
  345. holado_scripting/tests/behave/steps/scenario/if_steps.py +87 -0
  346. holado_scripting/tests/behave/steps/scenario/loop_steps.py +119 -0
  347. holado_scripting/text/base/base_function.py +25 -0
  348. holado_scripting/text/base/base_verify_function.py +25 -0
  349. holado_scripting/text/base/text_inspecter.py +204 -0
  350. holado_scripting/text/interpreter/exceptions/interpreter_exception.py +25 -0
  351. holado_scripting/text/interpreter/functions/function_cast.py +60 -0
  352. holado_scripting/text/interpreter/functions/function_convert.py +57 -0
  353. holado_scripting/text/interpreter/functions/function_dynamic_value.py +40 -0
  354. holado_scripting/text/interpreter/functions/function_escape_all_bytes.py +35 -0
  355. holado_scripting/text/interpreter/functions/function_exists_variable.py +39 -0
  356. holado_scripting/text/interpreter/functions/function_hex_to_bytes.py +49 -0
  357. holado_scripting/text/interpreter/functions/function_hex_to_int.py +53 -0
  358. holado_scripting/text/interpreter/functions/function_to_base_64.py +41 -0
  359. holado_scripting/text/interpreter/functions/function_to_bytes.py +50 -0
  360. holado_scripting/text/interpreter/functions/function_to_hex.py +42 -0
  361. holado_scripting/text/interpreter/text_interpreter.py +216 -0
  362. holado_scripting/text/verifier/exceptions/verifier_exception.py +21 -0
  363. holado_scripting/text/verifier/functions/verify_function_extract_in.py +35 -0
  364. holado_scripting/text/verifier/functions/verify_function_match_pattern.py +63 -0
  365. holado_scripting/text/verifier/text_verifier.py +103 -0
  366. holado_sftp/__init__.py +16 -0
  367. holado_sftp/tests/behave/steps/__init__.py +17 -0
  368. holado_sftp/tests/behave/steps/private/__init__.py +16 -0
  369. holado_sftp/tests/behave/steps/private/tools/sftp_steps.py +78 -0
  370. holado_sftp/tests/behave/steps/tools/sftp_client_steps.py +94 -0
  371. holado_sftp/tests/behave/steps/tools/sftp_server_steps.py +82 -0
  372. holado_sftp/tools/sftp/__init__.py +0 -0
  373. holado_sftp/tools/sftp/sftp_client.py +103 -0
  374. holado_sftp/tools/sftp/sftp_server.py +39 -0
  375. holado_swagger/__init__.py +31 -0
  376. holado_swagger/swagger_hub/mockserver/mockserver_client.py +82 -0
  377. holado_swagger/swagger_hub/mockserver/mockserver_manager.py +32 -0
  378. holado_swagger/tests/behave/steps/__init__.py +16 -0
  379. holado_swagger/tests/behave/steps/swagger_hub/mockserver_steps.py +74 -0
  380. holado_system/system/command/command.py +216 -0
  381. holado_system/system/command/command_result.py +128 -0
  382. holado_system/system/command/curl_command.py +101 -0
  383. holado_system/system/command/exceptions.py +59 -0
  384. holado_system/system/filesystem/file.py +76 -0
  385. holado_system/system/global_system.py +187 -0
  386. holado_system/tests/behave/steps/__init__.py +18 -0
  387. holado_system/tests/behave/steps/system/commands_steps.py +92 -0
  388. holado_system/tests/behave/steps/system/file_steps.py +215 -0
  389. holado_system/tests/behave/steps/system/system_steps.py +84 -0
  390. holado_test/__init__.py +27 -0
  391. holado_test/behave/__init__.py +0 -0
  392. holado_test/behave/behave.py +397 -0
  393. holado_test/behave/behave_environment.py +143 -0
  394. holado_test/behave/behave_function.py +33 -0
  395. holado_test/behave/behave_manager.py +555 -0
  396. holado_test/behave/independant_runner.py +68 -0
  397. holado_test/behave/scenario/__init__.py +0 -0
  398. holado_test/behave/scenario/behave_step_tools.py +157 -0
  399. holado_test/common/context/feature_context.py +79 -0
  400. holado_test/common/context/scenario_context.py +217 -0
  401. holado_test/common/context/step_context.py +66 -0
  402. holado_test/common/exceptions/undefined_step_exception.py +21 -0
  403. holado_test/scenario/step_tools.py +523 -0
  404. holado_test/scenario/tester_tools.py +52 -0
  405. holado_test/test_config.py +26 -0
  406. holado_test/tests/behave/steps/__init__.py +18 -0
  407. holado_test/tests/behave/steps/scenario/exception_steps.py +87 -0
  408. holado_test/tests/behave/steps/scenario/scenario_steps.py +87 -0
  409. holado_test/tests/behave/steps/scenario/tester_steps.py +65 -0
  410. holado_value/__init__.py +24 -0
  411. holado_value/common/tables/comparators/table_2_value_table_cell_comparator.py +195 -0
  412. holado_value/common/tables/comparators/table_2_value_table_comparator.py +27 -0
  413. holado_value/common/tables/comparators/table_2_value_table_row_comparator.py +27 -0
  414. holado_value/common/tables/comparators/table_2_value_table_with_header_comparator.py +27 -0
  415. holado_value/common/tables/converters/value_table_converter.py +217 -0
  416. holado_value/common/tables/value_table.py +29 -0
  417. holado_value/common/tables/value_table_cell.py +67 -0
  418. holado_value/common/tables/value_table_manager.py +58 -0
  419. holado_value/common/tables/value_table_row.py +44 -0
  420. holado_value/common/tables/value_table_with_header.py +28 -0
  421. holado_value/common/tools/unique_value_manager.py +108 -0
  422. holado_value/common/tools/value.py +164 -0
  423. holado_value/common/tools/value_types.py +35 -0
  424. holado_value/tests/behave/steps/__init__.py +16 -0
  425. holado_value/tests/behave/steps/private/__init__.py +16 -0
  426. holado_ws/__init__.py +16 -0
  427. holado_ws/api/ws/TODO.txt +2 -0
  428. holado_ws/tests/behave/steps/__init__.py +16 -0
  429. holado_ws/tests/behave/steps/api/web_service_steps.py +189 -0
  430. holado_yaml/__init__.py +31 -0
  431. holado_yaml/tests/behave/steps/__init__.py +16 -0
  432. holado_yaml/tests/behave/steps/yaml_steps.py +64 -0
  433. holado_yaml/yaml/yaml_manager.py +86 -0
  434. test_holado/Dockerfile_test_holado +82 -0
  435. test_holado/__init__.py +4 -0
  436. test_holado/__main__.py +25 -0
  437. test_holado/build_docker_image_to_test_holado_in_docker.sh +7 -0
  438. test_holado/environment.py +42 -0
  439. test_holado/features/NonReg/api/REST.feature +21 -0
  440. test_holado/features/NonReg/api/gRPC.feature +122 -0
  441. test_holado/features/NonReg/common/multiprocessing/simple.feature +60 -0
  442. test_holado/features/NonReg/common/system/commands.feature +43 -0
  443. test_holado/features/NonReg/common/system/system.feature +20 -0
  444. test_holado/features/NonReg/common/tables/table.feature +239 -0
  445. test_holado/features/NonReg/common/tables/value_table_conversion.feature +29 -0
  446. test_holado/features/NonReg/common/tools/DateTime.feature +88 -0
  447. test_holado/features/NonReg/common/tools/UniqueValueManager.feature +43 -0
  448. test_holado/features/NonReg/holado_ais/ais_message-bitarray_to_nmea.feature +135 -0
  449. test_holado/features/NonReg/holado_protobuf/protobuf.feature +291 -0
  450. test_holado/features/NonReg/holado_python/convert.feature +20 -0
  451. test_holado/features/NonReg/holado_python/iterable.feature +61 -0
  452. test_holado/features/NonReg/holado_python/standard_library/socket.feature +101 -0
  453. test_holado/features/NonReg/holado_python/standard_library/socket_with_ssl.feature +180 -0
  454. test_holado/features/NonReg/holado_scripting/common/tools/dynamic_text_manager.feature +18 -0
  455. test_holado/features/NonReg/holado_scripting/common/tools/expression_evaluator.feature +185 -0
  456. test_holado/features/NonReg/holado_scripting/common/tools/variable_manager.feature +71 -0
  457. test_holado/features/NonReg/holado_scripting/text/interpreter/interpreter.error.feature +21 -0
  458. test_holado/features/NonReg/holado_scripting/text/interpreter/interpreter.feature +120 -0
  459. test_holado/features/NonReg/holado_yaml/yaml.feature +218 -0
  460. test_holado/features/NonReg/ipc/bit_series.error.feature +33 -0
  461. test_holado/features/NonReg/ipc/bit_series.feature +131 -0
  462. test_holado/features/NonReg/ipc/json.feature +20 -0
  463. test_holado/features/NonReg/scenario/scenario.feature +139 -0
  464. test_holado/features/NonReg/test_steps/behave.feature +275 -0
  465. test_holado/features/NonReg/test_steps/common.feature +100 -0
  466. test_holado/features/NonReg/tools/RabbitMQ.feature +445 -0
  467. test_holado/features/NonReg/tools/RabbitMQ_steps.feature +276 -0
  468. test_holado/features/NonReg/tools/S3/boto3_client.feature +73 -0
  469. test_holado/features/NonReg/tools/S3/minio_client.feature +75 -0
  470. test_holado/features/NonReg/tools/db_sqlite3.feature +41 -0
  471. test_holado/features/NonReg/tools/sFTP.feature +25 -0
  472. test_holado/features/Test/logger.feature +28 -0
  473. test_holado/features/__init__.py +0 -0
  474. test_holado/logging.conf +41 -0
  475. test_holado/resources/proto/definitions/protobuf/custom_types/field_types.proto +24 -0
  476. test_holado/resources/proto/definitions/protobuf/protobuf.dev/tutorial/addressbook.proto +56 -0
  477. test_holado/resources/proto/generated/protobuf/custom_types/field_types_pb2.py +34 -0
  478. test_holado/resources/proto/generated/protobuf/protobuf/dev/tutorial/addressbook_pb2.py +34 -0
  479. test_holado/resources/scripts/list_tags.sh +2 -0
  480. test_holado/resources/scripts/update_resources_proto_generated.py +70 -0
  481. test_holado/steps/__init__.py +0 -0
  482. test_holado/steps/private_steps.py +20 -0
  483. test_holado/steps/public_steps.py +23 -0
  484. test_holado/test_holado_session_context.py +43 -0
  485. test_holado/tools/django/README.txt +3 -0
  486. test_holado/tools/django/api_grpc/api_grpc/__init__.py +0 -0
  487. test_holado/tools/django/api_grpc/api_grpc/api1/__init__.py +0 -0
  488. test_holado/tools/django/api_grpc/api_grpc/api1/admin.py +3 -0
  489. test_holado/tools/django/api_grpc/api_grpc/api1/apps.py +6 -0
  490. test_holado/tools/django/api_grpc/api_grpc/api1/migrations/__init__.py +0 -0
  491. test_holado/tools/django/api_grpc/api_grpc/api1/models.py +3 -0
  492. test_holado/tools/django/api_grpc/api_grpc/api1/proto/__init__.py +0 -0
  493. test_holado/tools/django/api_grpc/api_grpc/api1/proto/account.proto +27 -0
  494. test_holado/tools/django/api_grpc/api_grpc/api1/proto/account_pb2.py +33 -0
  495. test_holado/tools/django/api_grpc/api_grpc/api1/proto/account_pb2_grpc.py +199 -0
  496. test_holado/tools/django/api_grpc/api_grpc/api1/serializers.py +12 -0
  497. test_holado/tools/django/api_grpc/api_grpc/api1/services.py +11 -0
  498. test_holado/tools/django/api_grpc/api_grpc/api1/tests.py +3 -0
  499. test_holado/tools/django/api_grpc/api_grpc/api1/views.py +3 -0
  500. test_holado/tools/django/api_grpc/api_grpc/asgi.py +16 -0
  501. test_holado/tools/django/api_grpc/api_grpc/settings.py +126 -0
  502. test_holado/tools/django/api_grpc/api_grpc/urls.py +27 -0
  503. test_holado/tools/django/api_grpc/api_grpc/wsgi.py +16 -0
  504. test_holado/tools/django/api_grpc/db.sqlite3 +0 -0
  505. test_holado/tools/django/api_grpc/manage.py +27 -0
  506. test_holado/tools/django/api_grpc/manual_test_commands.txt +25 -0
  507. test_holado/tools/django/api_rest/api_rest/__init__.py +0 -0
  508. test_holado/tools/django/api_rest/api_rest/api1/__init__.py +0 -0
  509. test_holado/tools/django/api_rest/api_rest/api1/admin.py +3 -0
  510. test_holado/tools/django/api_rest/api_rest/api1/apps.py +6 -0
  511. test_holado/tools/django/api_rest/api_rest/api1/migrations/__init__.py +0 -0
  512. test_holado/tools/django/api_rest/api_rest/api1/models.py +3 -0
  513. test_holado/tools/django/api_rest/api_rest/api1/serializers.py +15 -0
  514. test_holado/tools/django/api_rest/api_rest/api1/tests.py +3 -0
  515. test_holado/tools/django/api_rest/api_rest/api1/views.py +24 -0
  516. test_holado/tools/django/api_rest/api_rest/asgi.py +16 -0
  517. test_holado/tools/django/api_rest/api_rest/settings.py +133 -0
  518. test_holado/tools/django/api_rest/api_rest/urls.py +32 -0
  519. test_holado/tools/django/api_rest/api_rest/wsgi.py +16 -0
  520. test_holado/tools/django/api_rest/db.sqlite3 +0 -0
  521. test_holado/tools/django/api_rest/manage.py +22 -0
  522. holado-0.2.1.dist-info/RECORD +0 -17
  523. {holado-0.2.1.dist-info → holado-0.2.3.dist-info}/WHEEL +0 -0
  524. {holado-0.2.1.dist-info → holado-0.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,439 @@
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 logging
16
+ import os
17
+ from holado_core.common.exceptions.technical_exception import TechnicalException
18
+ from holado_system.system.global_system import OSTypes, GlobalSystem
19
+ from holado_multitask.multithreading.context.thread_context import ThreadContext
20
+ from holado_multitask.multiprocessing.context.process_context import ProcessContext
21
+ from holado_core.common.tools.tools import Tools
22
+ from holado_python.standard_library.typing import Typing
23
+ from holado.common.handlers.undefined import default_context
24
+ from holado.common.context.session_context import SessionContext
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ class MultitaskManager(object):
30
+ """
31
+ Manage resources used by threads/processes run by HolAdo.
32
+ It provides a ThreadContext/ProcessContext for each thread/process.
33
+ """
34
+
35
+ SESSION_SCOPE_NAME = "Session"
36
+ SCENARIO_SCOPE_NAME = "Scenario"
37
+
38
+ @classmethod
39
+ def get_scope_name(cls, scope=default_context):
40
+ if scope is default_context:
41
+ if SessionContext.instance().has_scenario_context():
42
+ return MultitaskManager.SCENARIO_SCOPE_NAME
43
+ else:
44
+ return MultitaskManager.SESSION_SCOPE_NAME
45
+ elif scope is not None:
46
+ return scope
47
+ else:
48
+ return MultitaskManager.SESSION_SCOPE_NAME
49
+
50
+
51
+ @classmethod
52
+ def get_process_id(cls, process=None):
53
+ if process is None:
54
+ return os.getpid()
55
+ else:
56
+ return process.pid
57
+
58
+ @classmethod
59
+ def get_parent_process_id(cls, pid=None):
60
+ if pid is None:
61
+ return os.getppid()
62
+ else:
63
+ if GlobalSystem.get_os_type() == OSTypes.Linux:
64
+ # Read /proc/<pid>/status and look for the line `PPid:\t120517\n`
65
+ with open(f"/proc/{pid}/status", encoding="ascii") as f:
66
+ for line in f.readlines():
67
+ if line.startswith("PPid:\t"):
68
+ return int(line[6:])
69
+ raise TechnicalException(f"No PPid line found in /proc/{pid}/status")
70
+ else:
71
+ raise TechnicalException(f"Unmanaged OS type {GlobalSystem.get_os_type().name}")
72
+
73
+ @classmethod
74
+ def has_thread_native_id(cls):
75
+ from holado_multitask.multithreading.threadsmanager import ThreadsManager
76
+ return ThreadsManager.has_native_id()
77
+
78
+ @classmethod
79
+ def get_thread_uid(cls, thread=None):
80
+ tid = cls.get_thread_id(thread=thread)
81
+ if cls.has_thread_native_id():
82
+ return tid
83
+ else:
84
+ return (cls.get_process_id(), tid)
85
+
86
+ @classmethod
87
+ def get_thread_id(cls, thread=None, native=None):
88
+ if thread is None:
89
+ thread = threading.current_thread()
90
+ if native is None:
91
+ native = cls.has_thread_native_id()
92
+ elif native and not cls.has_thread_native_id():
93
+ raise TechnicalException(f"System doesn't support thread native id")
94
+
95
+ if native:
96
+ return thread.native_id
97
+ else:
98
+ return thread.ident
99
+
100
+
101
+ def __init__(self):
102
+ self.__process_lock = threading.Lock()
103
+ self.__process_context_by_uname = {}
104
+ self.__parent_thread_uid_by_process_uname = {}
105
+ self.__process_id_by_uname = {}
106
+ self.__process_uname_by_id = {}
107
+ self.__thread_uid_by_process_uname = {}
108
+
109
+ self.__thread_lock = threading.Lock()
110
+ self.__main_thread_uid = self.get_thread_uid()
111
+ self.__thread_context_by_uname = {}
112
+ self.__parent_thread_uid_by_thread_uname = {}
113
+ self.__thread_uid_by_uname = {}
114
+ self.__thread_uname_by_uid = {}
115
+
116
+ self.__related_thread_uid_by_uid = {}
117
+
118
+ self.__feature_context_by_thread_uid = {}
119
+
120
+ @property
121
+ def is_main_thread(self):
122
+ thread_uid = self.get_thread_uid()
123
+ return thread_uid == self.__main_thread_uid
124
+
125
+ @property
126
+ def main_thread_uid(self):
127
+ return self.__main_thread_uid
128
+
129
+
130
+ ### Manage processes
131
+
132
+ def prepare_process(self, name, update_parent=True):
133
+ """
134
+ Create a process context and return a unique name based to given name
135
+ """
136
+ with self.__process_lock:
137
+ res = name
138
+ name_index = 0
139
+ while res in self.__process_context_by_uname:
140
+ name_index += 1
141
+ res = f"{name}_{name_index}"
142
+
143
+ self.__process_context_by_uname[res] = ProcessContext(name, res)
144
+
145
+ if update_parent:
146
+ uid = self.get_thread_uid()
147
+ self.__parent_thread_uid_by_process_uname[res] = uid
148
+
149
+ if Tools.do_log(logger, logging.DEBUG):
150
+ logger.debug(f"New process context: name='{name}' ; unique name='{res}'{{}}".format(f" ; parent thread UID={uid}" if update_parent else ''))
151
+ return res
152
+
153
+ def set_process_id(self, name, pid):
154
+ # logger.print(f"+++++++++ __parent_thread_uid_by_thread_uname: {self.__parent_thread_uid_by_thread_uname}")
155
+ # logger.print(f"+++++++++ __feature_context_by_thread_uid: {self.__feature_context_by_thread_uid}")
156
+ # logger.print(f"+++++++++ __thread_context_by_uname: {self.__thread_context_by_uname}")
157
+ self.__process_id_by_uname[name] = pid
158
+ self.__process_uname_by_id[pid] = name
159
+ if Tools.do_log(logger, logging.DEBUG):
160
+ logger.debug(f"Set process PID: name='{name}' ; PID={pid}")
161
+
162
+ def set_process_thread_uid(self, name, thread_uid):
163
+ # Set main thread UID of process
164
+ self.__thread_uid_by_process_uname[name] = thread_uid
165
+
166
+ # Set parent thread of process as parent thread of process main thread
167
+ parent_thread_uid = self.__parent_thread_uid_by_process_uname[name]
168
+ tuname = self._get_thread_unique_name_or_uid(thread_uid)
169
+ self.__parent_thread_uid_by_thread_uname[tuname] = parent_thread_uid
170
+ # logger.print(f"+++++++++ __parent_thread_uid_by_thread_uname: {self.__parent_thread_uid_by_thread_uname}")
171
+ # logger.print(f"+++++++++ __feature_context_by_thread_uid: {self.__feature_context_by_thread_uid}")
172
+ # logger.print(f"+++++++++ __thread_context_by_uname: {self.__thread_context_by_uname}")
173
+ if Tools.do_log(logger, logging.DEBUG):
174
+ logger.debug(f"Set process thread UID: process name='{name}' ; thread name='{tuname}' ; thread UID={thread_uid} ; parent thread UID={parent_thread_uid}")
175
+
176
+ def _get_process_unique_name_or_pid(self, pid=None):
177
+ if pid is None:
178
+ pid = self.get_process_id()
179
+ if pid in self.__process_uname_by_id:
180
+ return self.__process_uname_by_id[pid]
181
+ else:
182
+ # logger.debug(f"Using process PID {pid} as unique name")
183
+ return pid
184
+
185
+
186
+ ### Manage threads
187
+
188
+ def prepare_thread(self, name, update_parent=True):
189
+ """
190
+ Create a process context and return a unique name based to given name
191
+ """
192
+ with self.__thread_lock:
193
+ res = name
194
+ name_index = 0
195
+ while res in self.__thread_context_by_uname:
196
+ name_index += 1
197
+ res = f"{name}_{name_index}"
198
+
199
+ self.__thread_context_by_uname[res] = ThreadContext(name, res)
200
+
201
+ this_uid = self.get_thread_uid()
202
+ # In some cases (ex: on missing thread context), thread uid is used as name, and it can't be its own parent
203
+ if update_parent and res != this_uid:
204
+ # logger.print(f"+++++ Set parent thread UID: {res} -> {this_uid}")
205
+ self.__parent_thread_uid_by_thread_uname[res] = this_uid
206
+
207
+ if Tools.do_log(logger, logging.DEBUG):
208
+ logger.debug(f"New thread context: name='{name}' ; unique name='{res}'{{}}".format(f" ; parent thread UID={this_uid}" if update_parent and res != this_uid else ''))
209
+ return res
210
+
211
+ def set_thread_uid(self, name, uid=None):
212
+ if uid is None:
213
+ uid = self.get_thread_uid()
214
+ # logger.print(f"+++++ Set thread UID: {name} -> {uid}")
215
+ self.__thread_uid_by_uname[name] = uid
216
+ self.__thread_uname_by_uid[uid] = name
217
+ self.__thread_context_by_uname[name].thread_uid = uid
218
+ if Tools.do_log(logger, logging.DEBUG):
219
+ logger.debug(f"Set thread UID: name='{name}' ; UID={uid}")
220
+
221
+ def _get_thread_unique_name_or_uid(self, uid=None):
222
+ if uid is None:
223
+ uid = self.get_thread_uid()
224
+ if uid in self.__thread_uname_by_uid:
225
+ return self.__thread_uname_by_uid[uid]
226
+ else:
227
+ # logger.debug(f"Using thread UID {uid} as unique name")
228
+ return uid
229
+
230
+ def relate_thread_to(self, from_uid, to_uid):
231
+ self.__related_thread_uid_by_uid[from_uid] = to_uid
232
+
233
+
234
+
235
+ ### Manage process context
236
+
237
+ def get_process_context(self, pid=None):
238
+ if pid is None:
239
+ pid = self.get_process_id()
240
+ uname = self._get_process_unique_name_or_pid(pid=pid)
241
+ # logger.print(f"++++ get_process_context: uid={uid} ; uname={uname}", stack_info=True)
242
+
243
+ if uname not in self.__process_context_by_uname:
244
+ if Tools.do_log(logger, logging.DEBUG):
245
+ logger.debug("Creating missing process context for unique name {}".format(f"'{uname}'" if isinstance(uname, str) else f"{uname}"))
246
+ uname = self.prepare_process(uname, update_parent=False)
247
+ self.set_process_id(uname, pid)
248
+
249
+ return self.__process_context_by_uname[uname]
250
+
251
+
252
+
253
+
254
+ ### Manage thread context
255
+
256
+ def get_thread_context(self, uid=None):
257
+ if uid is None:
258
+ uid = self.get_thread_uid()
259
+ uname = self._get_thread_unique_name_or_uid(uid=uid)
260
+ # logger.print(f"++++ get_thread_context: uid={uid} ; uname={uname}", stack_info=True)
261
+
262
+ if uname not in self.__thread_context_by_uname:
263
+ if Tools.do_log(logger, logging.DEBUG):
264
+ logger.debug("Creating missing thread context for unique name {}".format(f"'{uname}'" if isinstance(uname, str) else f"{uname}"))
265
+ uname = self.prepare_thread(uname, update_parent=False)
266
+ self.set_thread_uid(uname, uid)
267
+
268
+ res = self.__thread_context_by_uname[uname]
269
+ if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
270
+ logger.trace(f"Thread context for tread UID '{uid}' (uname: '{uname}'): {res}")
271
+ return res
272
+
273
+ def get_parent_thread_context(self, uid=None):
274
+ if uid is None:
275
+ uid = self.get_thread_uid()
276
+ uname = self._get_thread_unique_name_or_uid(uid=uid)
277
+ if uname in self.__parent_thread_uid_by_thread_uname:
278
+ parent_uid = self.__parent_thread_uid_by_thread_uname[uname]
279
+ # logger.print(f"++++ get_parent_thread_context: {uid} -> {parent_uid}", stack_info=True)
280
+ return self.get_thread_context(uid=parent_uid)
281
+ else:
282
+ return None
283
+
284
+ def __find_thread_context_having(self, has_func, uid=None, do_log=False, _internal=None):
285
+ if uid is None:
286
+ uid = self.get_thread_uid()
287
+ if _internal is None:
288
+ _internal = []
289
+
290
+ res = None
291
+ while True:
292
+ if uid in _internal:
293
+ break
294
+ else:
295
+ _internal.append(uid)
296
+
297
+ res = self.__find_thread_context_having__throw_thread_parents(has_func, uid=uid, do_log=do_log, _internal=_internal)
298
+ if res is None:
299
+ if uid in self.__related_thread_uid_by_uid:
300
+ # Try with related thread
301
+ old_uid = uid
302
+ uid = self.__related_thread_uid_by_uid[uid]
303
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
304
+ logger.trace(f"[MultitaskManager.__find_thread_context_having] Not found in thread uid '{old_uid}', try in thread uid '{uid}'")
305
+ else:
306
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
307
+ logger.trace(f"[MultitaskManager.__find_thread_context_having] Not found in thread uid '{uid}', stop search")
308
+ return None
309
+ else:
310
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
311
+ logger.trace(f"[MultitaskManager.__find_thread_context_having] Found in thread uid '{uid}' => {res}")
312
+ break
313
+
314
+ return res
315
+
316
+ def __find_thread_context_having__throw_thread_parents(self, has_func, uid=None, do_log=False, _internal=None):
317
+ if uid is None:
318
+ uid = self.get_thread_uid()
319
+
320
+ # logger.print(f"+++++ Find thread context having feature context: uid={uid}")
321
+ while True:
322
+ uname = self._get_thread_unique_name_or_uid(uid=uid)
323
+ if uname in self.__thread_context_by_uname:
324
+ # logger.print(f"+++++ Find thread context having feature context: {uname} not in __thread_context_by_uname => None")
325
+ # return None
326
+
327
+ thread_context = self.__thread_context_by_uname[uname]
328
+ found = False
329
+ if isinstance(has_func, str):
330
+ if hasattr(thread_context, has_func):
331
+ found = getattr(thread_context, has_func)()
332
+ else:
333
+ found = has_func(thread_context)
334
+ if found:
335
+ # logger.print(f"+++++ Find thread context having feature context => found from uid={uid}")
336
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
337
+ logger.trace(f"[MultitaskManager.__find_thread_context_having__throw_thread_parents] Found in thread uid '{uid}' (uname: '{uname}') => {thread_context}")
338
+ return thread_context
339
+ else:
340
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
341
+ logger.trace(f"[MultitaskManager.__find_thread_context_having__throw_thread_parents] Thread uid '{uid}' (uname: '{uname}') has a context, but it doesn't verify {has_func}")
342
+
343
+ if uname in self.__parent_thread_uid_by_thread_uname:
344
+ # Retry with parent thread uid
345
+ uid = self.__parent_thread_uid_by_thread_uname[uname]
346
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
347
+ logger.trace(f"[MultitaskManager.__find_thread_context_having__throw_thread_parents] Try in parent thread uid '{uid}'")
348
+ # logger.print(f"+++++ Find thread context having feature context: in parent uid={uid}")
349
+ return self.__find_thread_context_having(has_func, uid=uid, do_log=do_log, _internal=_internal)
350
+ else:
351
+ # logger.print(f"+++++ Find thread context having feature context: {uname} not in __parent_thread_uid_by_thread_uname => None")
352
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
353
+ logger.trace(f"[MultitaskManager.__find_thread_context_having__throw_thread_parents] Not found in thread uid '{uid}' (uname: '{uname}'), and it has not parent thread")
354
+ return None
355
+
356
+
357
+
358
+ ### Manage feature context
359
+
360
+ def __update_feature_context_for_thread_uid(self, uid):
361
+ if uid not in self.__feature_context_by_thread_uid:
362
+ thread_context = self.__find_thread_context_having(ThreadContext.has_feature_context, uid)
363
+ if thread_context is None:
364
+ feature_context = None
365
+ else:
366
+ feature_context = thread_context.get_feature_context()
367
+ # logger.print(f"+++++ Set feature context for thread UID {uid}: {feature_context}")
368
+ is_reference = (thread_context.thread_uid == uid)
369
+ self.__feature_context_by_thread_uid[uid] = (feature_context, is_reference)
370
+ if Tools.do_log(logger, logging.DEBUG):
371
+ # logger.debug(f"Updated feature context for thread: UID='{uid}' ; feature context={feature_context}")
372
+ logger.debug(f"Updated feature context for thread: UID='{uid}' ; feature context={feature_context} (registered list: {self.__feature_context_by_thread_uid})")
373
+
374
+ def __remove_feature_context_for_any_thread_uid(self, feature_context):
375
+ list_uid = list(self.__feature_context_by_thread_uid.keys())
376
+ for uid in list_uid:
377
+ if self.__feature_context_by_thread_uid[uid][0] is feature_context:
378
+ del self.__feature_context_by_thread_uid[uid]
379
+ if Tools.do_log(logger, logging.DEBUG):
380
+ logger.debug(f"Removed feature context ({id(feature_context)}) association with thread UID {uid}")
381
+
382
+ def has_feature_context(self, is_reference=True, do_log=False):
383
+ uid = self.get_thread_uid()
384
+ # self.__update_feature_context_for_thread_uid(uid)
385
+ # return self.__feature_context_by_thread_uid[uid] is not None
386
+
387
+ if uid in self.__feature_context_by_thread_uid:
388
+ res = self.__feature_context_by_thread_uid[uid][0] is not None
389
+ if res and is_reference is not None:
390
+ res &= (is_reference == self.__feature_context_by_thread_uid[uid][1])
391
+ if do_log and Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
392
+ logger.trace(f"[MultitaskManager.has_feature_context] Thread uid '{uid}' is in __feature_context_by_thread_uid and is_reference == {is_reference} => {res}")
393
+ return res
394
+
395
+ thread_context = self.__find_thread_context_having(ThreadContext.has_feature_context, uid, do_log=do_log)
396
+ res = thread_context is not None
397
+ if res and is_reference is not None:
398
+ res &= (thread_context.thread_uid == uid)
399
+
400
+ return res
401
+
402
+ def get_feature_context(self):
403
+ uid = self.get_thread_uid()
404
+ self.__update_feature_context_for_thread_uid(uid)
405
+ res = self.__feature_context_by_thread_uid[uid][0]
406
+ if logger.isEnabledFor(logging.TRACE): # @UndefinedVariable
407
+ logger.trace(f"Feature context for tread UID '{uid}': {res}")
408
+ return res
409
+
410
+ def set_feature_context(self, feature_context, is_reference=True):
411
+ thread_context = self.get_thread_context()
412
+ thread_context.set_feature_context(feature_context)
413
+
414
+ self.__feature_context_by_thread_uid[thread_context.thread_uid] = (feature_context, is_reference)
415
+
416
+ if Tools.do_log(logger, logging.DEBUG):
417
+ tuname = thread_context.thread_unique_name
418
+ tuname_txt = f"'{tuname}'" if isinstance(tuname, str) else f"{tuname}"
419
+ tuid = thread_context.thread_uid
420
+ logger.debug(f"Set feature context: thread unique name={tuname_txt} ; thread uid={tuid} ; feature context={feature_context} ; is reference={is_reference}")
421
+
422
+ def delete_feature_context(self):
423
+ tuname = self._get_thread_unique_name_or_uid()
424
+ if tuname not in self.__thread_context_by_uname:
425
+ raise TechnicalException(f"No thread context for thread unique name '{tuname}' (type: {Typing.get_object_class_fullname(tuname)})")
426
+
427
+ # Remove any reference to feature context before delete it
428
+ feature_context = self.__thread_context_by_uname[tuname].get_feature_context()
429
+ if Tools.do_log(logger, logging.DEBUG):
430
+ tuname_txt = f"'{tuname}'" if isinstance(tuname, str) else f"{tuname}"
431
+ logger.debug(f"Deleting feature context: thread unique name={tuname_txt} ; feature context={feature_context}")
432
+ self.__remove_feature_context_for_any_thread_uid(feature_context)
433
+
434
+ # Delete feature context
435
+ self.__thread_context_by_uname[tuname].delete_feature_context()
436
+
437
+
438
+
439
+
File without changes
@@ -0,0 +1,84 @@
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
+ from holado.common.context.context import Context
16
+ import logging
17
+ from holado_scripting.common.tools.variable_manager import VariableManager
18
+ from holado.common.context.session_context import SessionContext
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class ThreadContext(Context):
24
+ def __init__(self, name, unique_name):
25
+ super().__init__(f"Thread[{name};{unique_name}]")
26
+
27
+ self.__thread_uid = None
28
+ self.__thread_name = name
29
+ self.__thread_unique_name = unique_name
30
+
31
+ def __str__(self):
32
+ return f"{{ThreadContext({id(self)}):{self.__thread_uid}:{self.__thread_name}:{self.__thread_unique_name}}}"
33
+
34
+ @property
35
+ def thread_name(self):
36
+ return self.__thread_name
37
+
38
+ @property
39
+ def thread_unique_name(self):
40
+ return self.__thread_unique_name
41
+
42
+ @property
43
+ def thread_uid(self):
44
+ return self.__thread_uid
45
+
46
+ @thread_uid.setter
47
+ def thread_uid(self, uid):
48
+ self.__thread_uid = uid
49
+
50
+
51
+ def has_variable_manager(self):
52
+ return self.has_object("variable_manager")
53
+
54
+ def get_variable_manager(self) -> VariableManager:
55
+ if not self.has_variable_manager():
56
+ parent_thread_context = SessionContext.instance().multitask_manager.get_parent_thread_context(uid=self.thread_uid)
57
+ if parent_thread_context is not None:
58
+ var_man = parent_thread_context.get_variable_manager()
59
+ else:
60
+ var_man = SessionContext.instance().variable_manager
61
+
62
+ manager = VariableManager(var_man)
63
+ self.set_object("variable_manager", manager)
64
+ manager.initialize(SessionContext.instance().dynamic_text_manager, SessionContext.instance().unique_value_manager)
65
+ return self.get_object("variable_manager")
66
+
67
+
68
+ ### Manage feature context
69
+
70
+ def has_feature_context(self):
71
+ return self.has_object("feature_context")
72
+
73
+ def get_feature_context(self):
74
+ return self.get_object("feature_context")
75
+
76
+ def set_feature_context(self, feature_context):
77
+ return self.set_object("feature_context", feature_context)
78
+
79
+ def delete_feature_context(self):
80
+ self.get_feature_context().delete_object()
81
+ self.remove_object("feature_context")
82
+
83
+
84
+
@@ -0,0 +1,129 @@
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_core.common.block.function import Function
17
+ from holado_core.common.exceptions.functional_exception import FunctionalException
18
+ import holado_multitask.multithreading.thread as ctt
19
+ from holado_core.common.tools.tools import Tools
20
+ import time
21
+ from holado_python.standard_library.typing import Typing
22
+ from holado.common.handlers.undefined import default_context
23
+
24
+ logger = logging.getLogger(__name__)
25
+
26
+
27
+ class FunctionThreaded(ctt.InterruptableThread):
28
+ '''
29
+ Execute in a thread given function with given arguments
30
+ '''
31
+
32
+ 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):
33
+ super().__init__(name if name is not None else f"FunctionThreaded({repr(target)})", default_wait_timeout=default_wait_timeout, register_thread=register_thread, register_scope=register_scope, delay_before_run_sec=delay_before_run_sec)
34
+
35
+ if args is None:
36
+ args = []
37
+ if kwargs is None:
38
+ kwargs = {}
39
+
40
+ self._function = Function(target, *args, **kwargs)
41
+ self.__error = None
42
+ self.__result = None
43
+
44
+ # Manage interrupt
45
+ self.__interrupt_needs_function = True
46
+ self.__interrupt_function = None
47
+
48
+ self.__callback_function = None
49
+
50
+ @property
51
+ def error(self):
52
+ return self.__error
53
+
54
+ @property
55
+ def result(self):
56
+ return self.__result
57
+
58
+ @property
59
+ def interrupt_function(self):
60
+ return self.__interrupt_function
61
+
62
+ @interrupt_function.setter
63
+ def interrupt_function(self, func):
64
+ """Set the Function to call on interrupt"""
65
+ self.__interrupt_function = func
66
+
67
+ @property
68
+ def interrupt_needs_function(self):
69
+ return self.__interrupt_needs_function
70
+
71
+ @interrupt_needs_function.setter
72
+ def interrupt_needs_function(self, need_func):
73
+ """Set if interrupt_function is needed by interrupt"""
74
+ self.__interrupt_needs_function = need_func
75
+
76
+ @property
77
+ def callback_function(self):
78
+ return self.__callback_function
79
+
80
+ @callback_function.setter
81
+ def callback_function(self, func):
82
+ """Set the callback function"""
83
+ self.__callback_function = func
84
+
85
+ def run(self):
86
+ if self.delay_before_run_seconds is not None:
87
+ try:
88
+ time.sleep(self.delay_before_run_seconds)
89
+ except Exception as exc:
90
+ 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)})")
91
+
92
+ if self.is_interrupted:
93
+ return
94
+
95
+ try:
96
+ # logging.debug("+++++++++ Launching function [{}({})]".format(repr(self._target), repr(self._args)))
97
+ self.__result = self._function.run()
98
+ except Exception as exc:
99
+ logger.exception(f"[Thread '{self.name}'] Exception catched during threaded function [{self._function.represent()}]")
100
+ self.__error = exc
101
+
102
+ if self.is_interrupted:
103
+ return
104
+
105
+ try:
106
+ if self.__callback_function:
107
+ self.__callback_function.run(self.result, self.error)
108
+ except Exception as exc:
109
+ msg = "Exception catched while calling callback function:\n callback_function: {}\n result: [{}]\n error: [{}]".format(repr(self.__callback_function), Tools.truncate_text(repr(self.result)), repr(self.error))
110
+ logger.exception(msg)
111
+ raise FunctionalException(msg) from exc
112
+
113
+ logger.info(f"[Thread '{self.name}'] Thread has finished")
114
+
115
+ def throw_if_error(self):
116
+ if self.error:
117
+ raise FunctionalException("Error during call of function [{}({})]".format(repr(self._target), repr(self._args))) from self.error
118
+
119
+ @property
120
+ def is_interruptable(self):
121
+ return not self.__interrupt_needs_function or self.__interrupt_function is not None
122
+
123
+ def interrupt(self):
124
+ if not self.is_interrupted and self.is_alive():
125
+ super().interrupt()
126
+ if self.interrupt_function is not None:
127
+ self.interrupt_function.run()
128
+
129
+