holado 0.6.5__py3-none-any.whl → 0.7.0__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.
- holado/holado_config.py +5 -0
- {holado-0.6.5.dist-info → holado-0.7.0.dist-info}/METADATA +1 -1
- {holado-0.6.5.dist-info → holado-0.7.0.dist-info}/RECORD +15 -15
- holado_core/common/tables/converters/table_converter.py +14 -13
- holado_core/common/tools/tools.py +9 -8
- holado_db/tools/db/clients/base/db_client.py +4 -6
- holado_db/tools/db/clients/sqlite/sqlite_client.py +1 -1
- holado_grpc/api/rpc/grpc_client.py +43 -18
- holado_json/ipc/json.py +24 -3
- holado_rest/api/rest/rest_client.py +34 -14
- holado_rest/api/rest/rest_manager.py +2 -2
- holado_test/scenario/step_tools.py +1 -1
- holado_value/common/tables/converters/value_table_converter.py +35 -29
- {holado-0.6.5.dist-info → holado-0.7.0.dist-info}/WHEEL +0 -0
- {holado-0.6.5.dist-info → holado-0.7.0.dist-info}/licenses/LICENSE +0 -0
holado/holado_config.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
|
|
2
3
|
#################################################
|
|
3
4
|
# HolAdo (Holistic Automation do)
|
|
@@ -39,4 +40,8 @@ class Config(object):
|
|
|
39
40
|
UNIQUE_SYMBOL = u"#"
|
|
40
41
|
NOT_APPLICABLE_SYMBOL = u"N/A"
|
|
41
42
|
NONE_SYMBOL = u"None"
|
|
43
|
+
|
|
44
|
+
# Default log levels
|
|
45
|
+
log_level_grpc_request = logging.INFO
|
|
46
|
+
log_level_rest_request = logging.INFO
|
|
42
47
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
holado/__init__.py,sha256=ibxjS0XIck0rguf8FT_3HftofWmJqyfWraxjczMzzrw,14895
|
|
2
|
-
holado/holado_config.py,sha256
|
|
2
|
+
holado/holado_config.py,sha256=H1Wgndhz133nm0OcqS5hD6oDxZbDD_DeHJsKOuenQrI,2588
|
|
3
3
|
holado/common/__init__.py,sha256=ZjXM-FRQgnfzRNXqcvJOGewDHVRR-U5-ugStSs8U2Xs,1525
|
|
4
4
|
holado/common/context/__init__.py,sha256=3jJBLm8myrYF9jbdV1EhIA6BtnlmjX33eeoDpTzwmLA,1604
|
|
5
5
|
holado/common/context/context.py,sha256=XPrdZw_9j096AI9EZwMT4xVd58c1ZH6VGxT5Yb-qYYU,6660
|
|
@@ -123,11 +123,11 @@ holado_core/common/tables/comparators/table_comparator_manager.py,sha256=A5a1xQK
|
|
|
123
123
|
holado_core/common/tables/comparators/table_row_comparator.py,sha256=1_3N2E-PD6QyFwO9a-D3VpNVX8R7lSj0imyVTLajciI,6842
|
|
124
124
|
holado_core/common/tables/comparators/table_with_header_comparator.py,sha256=j7BcT8thQtz5fCYZik78tdMbhrQqB5lC8g_zFwRgFnM,4642
|
|
125
125
|
holado_core/common/tables/converters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
126
|
-
holado_core/common/tables/converters/table_converter.py,sha256=
|
|
126
|
+
holado_core/common/tables/converters/table_converter.py,sha256=PD7NJoxtejpr4aS1l3YKcXW1aEn1xBxdi4Ljs5G7R4g,10251
|
|
127
127
|
holado_core/common/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
128
128
|
holado_core/common/tools/path_manager.py,sha256=dgdm8wAaVubh-krpquCXXeGUTtGqRKDpuEKmvhA9dKA,8899
|
|
129
129
|
holado_core/common/tools/string_tools.py,sha256=bQuMlI_yS7OoSPFL7qyfyXkrnjC8xHVpIsfmEC6JxhI,5590
|
|
130
|
-
holado_core/common/tools/tools.py,sha256=
|
|
130
|
+
holado_core/common/tools/tools.py,sha256=zkDz7u8S_02bfyN6K-p7-Ey_SkDxzu9DJljnczY0OAo,9683
|
|
131
131
|
holado_core/common/tools/comparators/comparator.py,sha256=K4LcXIRORHX5vkmDibI6P6Bu1L-6Xezb63ZzzOMKrWY,6812
|
|
132
132
|
holado_core/common/tools/comparators/object_comparator.py,sha256=RPI319h_tij6z75UVbZII3gBggQolRFMNMD4cN6z37Y,1399
|
|
133
133
|
holado_core/common/tools/converters/converter.py,sha256=a77OzLC_bp6-jRVNVYcSXyixOrk_lg4hhs-jj9pYqaA,4136
|
|
@@ -159,11 +159,11 @@ holado_db/tests/behave/steps/tools/db/postgresql_client_steps.py,sha256=HtO-NSlT
|
|
|
159
159
|
holado_db/tests/behave/steps/tools/db/sqlite_client_steps.py,sha256=6B8GGBJxxG6Z49cGCPykm8BP7nQQZWUrWpw0XgaYGaE,2930
|
|
160
160
|
holado_db/tools/db/db_manager.py,sha256=0llXc6YhXfLr6oNfncPNjh4_ZInIm8XYywutQYvvLso,5400
|
|
161
161
|
holado_db/tools/db/clients/base/db_audit.py,sha256=eJ1r_0YUhvq50JngpWAdyEeVHWjAD4YCvWCJsLc1zmc,4368
|
|
162
|
-
holado_db/tools/db/clients/base/db_client.py,sha256=
|
|
162
|
+
holado_db/tools/db/clients/base/db_client.py,sha256=Uj1S-dOVmx-gHRj7x7VpYbyeE0Vde6fKTAlHOJX7p4E,15294
|
|
163
163
|
holado_db/tools/db/clients/postgresql/postgresql_audit.py,sha256=yoy4-Yt4lZHJw7xAcuTj2Thg4aTDCYJBt-6HzQeEE80,3939
|
|
164
164
|
holado_db/tools/db/clients/postgresql/postgresql_client.py,sha256=FW9t4kGh3ClDr1NfOymSMAYSrguPcKeqbwE6BM4ognI,4746
|
|
165
165
|
holado_db/tools/db/clients/sqlite/sqlite_audit.py,sha256=cK7hBE7aKCFOX5xnT-QnYD_1loQPgPP9Gf6qTT1XuI4,3966
|
|
166
|
-
holado_db/tools/db/clients/sqlite/sqlite_client.py,sha256
|
|
166
|
+
holado_db/tools/db/clients/sqlite/sqlite_client.py,sha256=x1ZiS_6AvDGrCz2a1FzP-IkYC7JHThE5daDZebbhDvE,2913
|
|
167
167
|
holado_db/tools/db/query/query_manager.py,sha256=7n-d_Q373hlsKQshY3accIH8XfqaLScqnhMdTT2oWC4,3642
|
|
168
168
|
holado_db/tools/db/query/base/query_builder.py,sha256=-nCyBe8zsRhOX39uCV0P7OY_YKobQJVIpJDL2sUA_H8,5926
|
|
169
169
|
holado_db/tools/db/query/pypika/pypika_query_builder.py,sha256=9x2-7B4p3eXSq3vLWWLscoFWJZakhcPxmNrpGR2ysdw,10964
|
|
@@ -255,7 +255,7 @@ holado_examples/tests/behave/testing_solution/steps/public_steps.py,sha256=nnxgB
|
|
|
255
255
|
holado_grpc/TODO,sha256=ESjES2-J6-3AJYdt6olcz_YGt4YTxw80CjIt-tjJ0z4,206
|
|
256
256
|
holado_grpc/__init__.py,sha256=SaAz66iSTqMw7oIDrj94rGcO8W7BgS15B78p--OogHc,2266
|
|
257
257
|
holado_grpc/api/rpc/TODO.txt,sha256=uWZT-WtrGuWbiOVU8-6xNiNyx_kKx-htM691zprLjh0,130
|
|
258
|
-
holado_grpc/api/rpc/grpc_client.py,sha256=
|
|
258
|
+
holado_grpc/api/rpc/grpc_client.py,sha256=7j6DOdrkAXZpas2hsIOSr-kkOEZNhw9hAAluHY8m3BE,10433
|
|
259
259
|
holado_grpc/api/rpc/grpc_manager.py,sha256=v3e7b1JCNlUoCnWUPgB9aWKde-AbseRCZAxFwz5gPN8,4115
|
|
260
260
|
holado_grpc/ipc/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
261
261
|
holado_grpc/ipc/rpc/grpc_compiler.py,sha256=f_v1Rj6gDpLSCpkN8a6Jn4w9d826JqNRII16HSPPrWA,2477
|
|
@@ -287,7 +287,7 @@ holado_helper/script/job.py,sha256=hb7WenhQP1qFMsxWGMsgbA-Z-zixynjRWjmZdx9wHEI,4
|
|
|
287
287
|
holado_helper/script/json_action_script.py,sha256=angdSt6e385lKwYSGJBqytVb4sp3-HjMKziVEFSz6ro,5147
|
|
288
288
|
holado_helper/script/script.py,sha256=77LRYUWiNwiXRDGiwlKqZJ40-lKD40dtR31w1bQW178,4494
|
|
289
289
|
holado_json/__init__.py,sha256=z0SNFOdBBWUouC12WKDmL18T_OH3TdmfcgIbnNQzbjU,1247
|
|
290
|
-
holado_json/ipc/json.py,sha256=
|
|
290
|
+
holado_json/ipc/json.py,sha256=Q8b4HtrQGCAcT3i5CHtKADZfjilK29UwuFpclZ5JNa0,7178
|
|
291
291
|
holado_json/ipc/json_converter.py,sha256=i4sPg9jZ2EziW8L6K-Rlm5-ubweFIWHq2R19avmsjkM,3433
|
|
292
292
|
holado_json/ipc/json_types.py,sha256=MP72SmSUqFnoNC_YFMLUmU4prJv4uzO1VUoUBVLYwD8,7883
|
|
293
293
|
holado_json/tests/behave/steps/__init__.py,sha256=FVGM5by0yswjfo8yC58x3onJKjKcQx919TOcYEUOWEw,1276
|
|
@@ -408,8 +408,8 @@ holado_report/report/reports/feature_report.py,sha256=i0wpk3LQLArVjWDsP9UcNSJzAU
|
|
|
408
408
|
holado_report/report/reports/scenario_report.py,sha256=eMyqw9EzaKMmX3pGFJN1rqAOQ5eqO2ISZdxAfK3XQR4,2945
|
|
409
409
|
holado_rest/__init__.py,sha256=BOeE6t6ejeqRYd44SE4vYJVTNz01BwcVCIWfwRQ5axg,1526
|
|
410
410
|
holado_rest/api/rest/TODO.txt,sha256=Oz8BYPkBEs9OAEgyYLLm7i5tJ1bRE5POBpT3SRFWTi4,29
|
|
411
|
-
holado_rest/api/rest/rest_client.py,sha256=
|
|
412
|
-
holado_rest/api/rest/rest_manager.py,sha256=
|
|
411
|
+
holado_rest/api/rest/rest_client.py,sha256=_Ck9CZxAF01kZMz8anIhSK_rH57poa7fNm-t0SSFu_I,8099
|
|
412
|
+
holado_rest/api/rest/rest_manager.py,sha256=XldPjNgj73GlzAmlsEcQYaHiDRk7SGU6VEFOLBnHjQM,4010
|
|
413
413
|
holado_rest/tests/behave/steps/__init__.py,sha256=lEH5NYkKtpgDV2ZAO1qAGNN4ipwILWMpgvQgnamgYKk,1283
|
|
414
414
|
holado_rest/tests/behave/steps/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
415
415
|
holado_rest/tests/behave/steps/api/rest_client_steps.py,sha256=naN0YcRVQyM--RhV0jPhnlsjZS6luijwGvVC5lM0XCY,9749
|
|
@@ -498,7 +498,7 @@ holado_test/common/context/feature_context.py,sha256=GhC0lihnvTBhv5tE4JzPt39eP7g
|
|
|
498
498
|
holado_test/common/context/scenario_context.py,sha256=pmo-xGtn6oHtbTmcH6Vtp8Dj2iGrYVdHd0b6smtlhbY,10527
|
|
499
499
|
holado_test/common/context/step_context.py,sha256=j6S4ozTPrdlpV9Slopc998fYOV8KfMLAUSW4mcEFUI8,2383
|
|
500
500
|
holado_test/common/exceptions/undefined_step_exception.py,sha256=SHHX22iz4Ip-V4Y3aM2EJFDt30CCS5EaauN6KB-JORo,1461
|
|
501
|
-
holado_test/scenario/step_tools.py,sha256=
|
|
501
|
+
holado_test/scenario/step_tools.py,sha256=Sqm7M0vVA9O2lRnv3pK5ryrSPOCGr5P7xD7C3esTpGg,25482
|
|
502
502
|
holado_test/scenario/tester_tools.py,sha256=Tv035FyXPjQ46Ep8KuPOjOvzJFvxnbv9EsrSihUzAwg,2479
|
|
503
503
|
holado_test/tests/behave/steps/__init__.py,sha256=rdqrp-UN7vRplIqORx4sXyKwMUkptRizyLWudsmYehM,1362
|
|
504
504
|
holado_test/tests/behave/steps/scenario/exception_steps.py,sha256=ZIE92Dz7a6O_c0jAP_0dj6Hc0tnW6YRgNKd4_aBpeR0,4054
|
|
@@ -514,7 +514,7 @@ holado_value/common/tables/comparators/table_2_value_table_cell_comparator.py,sh
|
|
|
514
514
|
holado_value/common/tables/comparators/table_2_value_table_comparator.py,sha256=rITxTgXami05plxk1qaCVqDcwZaKWoXpKAzur4ingTE,1807
|
|
515
515
|
holado_value/common/tables/comparators/table_2_value_table_row_comparator.py,sha256=_VglWUQWspG1Fo2iAo41auCwWYR24q0TniFck99BF_E,1752
|
|
516
516
|
holado_value/common/tables/comparators/table_2_value_table_with_header_comparator.py,sha256=VKwA7PbXnE-gFSKWlDCsJv0tkWVuNY-C4aWt2tyIybE,1911
|
|
517
|
-
holado_value/common/tables/converters/value_table_converter.py,sha256=
|
|
517
|
+
holado_value/common/tables/converters/value_table_converter.py,sha256=o8r2VZytUAwBlT9yORL4i5gyPvgZNFhvjuPqv32cqgM,12397
|
|
518
518
|
holado_value/common/tools/unique_value_manager.py,sha256=UXKdDKWznp4auYKQeWB7zYEzfm_0GxAiGfyoFM5ZM3s,5223
|
|
519
519
|
holado_value/common/tools/value.py,sha256=BwAx9L_xHA-v4K55osnXjI9z9bQn_MKQ8Cvk3mhqBjA,9108
|
|
520
520
|
holado_value/common/tools/value_types.py,sha256=7nJp5D7xdoT9jMeeOxHIuPRykDyI9fXpve37ndK32gs,1801
|
|
@@ -650,7 +650,7 @@ test_holado/tools/django/api_rest/api_rest/api1/serializers.py,sha256=o_YxFr-tgC
|
|
|
650
650
|
test_holado/tools/django/api_rest/api_rest/api1/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
|
|
651
651
|
test_holado/tools/django/api_rest/api_rest/api1/views.py,sha256=kOt2xT6bxO47_z__5yYR9kcYIWWv4qYzpX0K8Tqonik,758
|
|
652
652
|
test_holado/tools/django/api_rest/api_rest/api1/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
653
|
-
holado-0.
|
|
654
|
-
holado-0.
|
|
655
|
-
holado-0.
|
|
656
|
-
holado-0.
|
|
653
|
+
holado-0.7.0.dist-info/METADATA,sha256=54tIA8nZfmiafWGDsusb9S0W1hQX8PmNylQS870V4wk,7885
|
|
654
|
+
holado-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
655
|
+
holado-0.7.0.dist-info/licenses/LICENSE,sha256=IgGmNlcFHnbp7UWrLJqAFvs_HIgjJDTmjCNRircJLsk,1070
|
|
656
|
+
holado-0.7.0.dist-info/RECORD,,
|
|
@@ -113,21 +113,22 @@ class TableConverter(object):
|
|
|
113
113
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
114
114
|
logger.trace(f"Converting Name/Value table to dict (table = {table})")
|
|
115
115
|
|
|
116
|
-
# Verify table structure
|
|
117
|
-
TableManager.verify_table_is_name_value_table(table)
|
|
118
|
-
|
|
119
116
|
res = {}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
if table is not None:
|
|
118
|
+
# Verify table structure
|
|
119
|
+
TableManager.verify_table_is_name_value_table(table)
|
|
123
120
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
121
|
+
for row in table.rows:
|
|
122
|
+
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
123
|
+
logger.trace("Converting row (%s)", row)
|
|
124
|
+
|
|
125
|
+
name = row.get_cell(0).content
|
|
126
|
+
value = row.get_cell(1).content
|
|
127
|
+
|
|
128
|
+
if name in res:
|
|
129
|
+
raise FunctionalException("Name '{}' appears several times in table".format(name))
|
|
130
|
+
else:
|
|
131
|
+
res[name] = value
|
|
131
132
|
|
|
132
133
|
if Tools.do_log(logger, logging.DEBUG):
|
|
133
134
|
logger.debug(f"Converting Name/Value table to dict (table = {table}) => {res}")
|
|
@@ -78,11 +78,11 @@ class Tools(object):
|
|
|
78
78
|
return Tools.indent_string(indent, "".join(list_format))
|
|
79
79
|
|
|
80
80
|
@classmethod
|
|
81
|
-
def represent_object(cls, obj, indent=0, *, do_indent_first_line=True, full_details=False, access_type=AccessType.Public):
|
|
82
|
-
return cls.__represent_object(obj, indent, do_indent_first_line, full_details, access_type, [])
|
|
81
|
+
def represent_object(cls, obj, indent=0, *, do_indent_first_line=True, full_details=False, access_type=AccessType.Public, max_level=3):
|
|
82
|
+
return cls.__represent_object(obj, indent, do_indent_first_line, full_details, access_type, max_level, [])
|
|
83
83
|
|
|
84
84
|
@classmethod
|
|
85
|
-
def __represent_object(cls, obj, indent, do_indent_first_line, full_details, access_type, _internal):
|
|
85
|
+
def __represent_object(cls, obj, indent, do_indent_first_line, full_details, access_type, max_level, _internal):
|
|
86
86
|
from holado_core.common.tools.converters.converter import Converter
|
|
87
87
|
|
|
88
88
|
if Converter.is_primitive(obj) and not Converter.is_dict(obj) and not Converter.is_list(obj):
|
|
@@ -102,7 +102,7 @@ class Tools(object):
|
|
|
102
102
|
keys = list(obj.keys())
|
|
103
103
|
for key in keys:
|
|
104
104
|
# logger.print(f"+++++ Tools.__represent_object: key: {key}")
|
|
105
|
-
val_str = cls.__represent_object(obj[key], 0, True, full_details, access_type, _internal)
|
|
105
|
+
val_str = cls.__represent_object(obj[key], 0, True, full_details, access_type, max_level-1, _internal)
|
|
106
106
|
if '\n' in val_str:
|
|
107
107
|
res_list.append(f" {key}:")
|
|
108
108
|
res_list.append(Tools.indent_string(4, val_str))
|
|
@@ -116,7 +116,7 @@ class Tools(object):
|
|
|
116
116
|
for el in obj:
|
|
117
117
|
# for index, el in enumerate(obj):
|
|
118
118
|
# logger.print(f"+++++ Tools.__represent_object: index: {index}")
|
|
119
|
-
el_str = cls.__represent_object(el, 0, True, full_details, access_type, _internal)
|
|
119
|
+
el_str = cls.__represent_object(el, 0, True, full_details, access_type, max_level-1, _internal)
|
|
120
120
|
if '\n' in el_str:
|
|
121
121
|
res_list.append(" {")
|
|
122
122
|
res_list.append(Tools.indent_string(4, el_str))
|
|
@@ -133,9 +133,10 @@ class Tools(object):
|
|
|
133
133
|
# logger.print(f"+++++ Tools.__represent_object: {str(type(obj))} is object with {attributes=}")
|
|
134
134
|
if attributes:
|
|
135
135
|
res_list = [f"{str(type(obj))}({id_obj})"] if full_details else [f"{str(type(obj))}"]
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
136
|
+
if max_level > 0:
|
|
137
|
+
for name, value in attributes:
|
|
138
|
+
# logger.print(f"+++++ Tools.__represent_object: attribute '{name}'")
|
|
139
|
+
res_list.append(f" {name}: {cls.__represent_object(value, 4, False, full_details, access_type, max_level-1, _internal)}")
|
|
139
140
|
res = "\n".join(res_list)
|
|
140
141
|
else:
|
|
141
142
|
res = f"{obj} [{str(type(obj))}({id_obj})]" if full_details else f"{obj}"
|
|
@@ -23,15 +23,17 @@ from holado_core.common.tables.table import Table
|
|
|
23
23
|
from holado_db.tools.db.query.base.query_builder import QueryBuilder
|
|
24
24
|
from holado_data.data.generator.base import BaseGenerator
|
|
25
25
|
from holado_python.standard_library.typing import Typing
|
|
26
|
+
from holado.common.handlers.object import Object
|
|
26
27
|
|
|
27
28
|
logger = logging.getLogger(__name__)
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
class DBClient(
|
|
31
|
+
class DBClient(Object):
|
|
31
32
|
__metaclass__ = abc.ABCMeta
|
|
32
33
|
|
|
33
34
|
def __init__(self, name, connect_kwargs, with_cursor=True, auto_commit=True):
|
|
34
|
-
|
|
35
|
+
super().__init__(name)
|
|
36
|
+
|
|
35
37
|
self.__connect_kwargs = connect_kwargs
|
|
36
38
|
self.__with_cursor = with_cursor
|
|
37
39
|
self.__auto_commit = auto_commit
|
|
@@ -41,10 +43,6 @@ class DBClient(object):
|
|
|
41
43
|
self.__audit_manager = None
|
|
42
44
|
self.__column_names_by_table = {}
|
|
43
45
|
|
|
44
|
-
@property
|
|
45
|
-
def name(self):
|
|
46
|
-
return self.__name
|
|
47
|
-
|
|
48
46
|
@property
|
|
49
47
|
def query_builder(self) -> QueryBuilder:
|
|
50
48
|
return self.__query_builder
|
|
@@ -48,7 +48,7 @@ class SQLite3Client(DBClient):
|
|
|
48
48
|
database = connect_kwargs.pop("database")
|
|
49
49
|
return sqlite3.connect(database, **connect_kwargs)
|
|
50
50
|
except Exception as exc:
|
|
51
|
-
raise FunctionalException(f"Failed to connect with kwargs={kwargs}.\nUsage:\n{Tools.indent_string(4, sqlite3.connect.__doc__)}") from exc
|
|
51
|
+
raise FunctionalException(f"Failed to connect with kwargs={kwargs}.\nUsage:\n{Tools.indent_string(4, sqlite3.connect.__doc__)}") from exc # @UndefinedVariable
|
|
52
52
|
|
|
53
53
|
def _get_sql_placeholder(self):
|
|
54
54
|
return "?"
|
|
@@ -18,6 +18,8 @@ from holado_value.common.tables.converters.value_table_converter import ValueTab
|
|
|
18
18
|
from holado_core.common.tools.tools import Tools
|
|
19
19
|
import time
|
|
20
20
|
from holado.holado_config import Config
|
|
21
|
+
from holado.common.handlers.object import Object
|
|
22
|
+
from holado.common.handlers.undefined import undefined_argument, undefined_value
|
|
21
23
|
|
|
22
24
|
logger = logging.getLogger(__name__)
|
|
23
25
|
|
|
@@ -36,7 +38,7 @@ except Exception as exc:
|
|
|
36
38
|
# os.environ["GRPC_TRACE"] = "all"
|
|
37
39
|
|
|
38
40
|
|
|
39
|
-
class GRpcClient(
|
|
41
|
+
class GRpcClient(Object):
|
|
40
42
|
"""
|
|
41
43
|
gRPC client
|
|
42
44
|
|
|
@@ -49,7 +51,7 @@ class GRpcClient(object):
|
|
|
49
51
|
|
|
50
52
|
if with_grpc_requests:
|
|
51
53
|
def __init__(self, name, endpoint, **kwargs):
|
|
52
|
-
|
|
54
|
+
super().__init__(name)
|
|
53
55
|
self.__endpoint = endpoint
|
|
54
56
|
self.__kwargs = kwargs
|
|
55
57
|
self.__client = grpc_requests.client.get_by_endpoint(endpoint, **kwargs)
|
|
@@ -57,6 +59,8 @@ class GRpcClient(object):
|
|
|
57
59
|
self.__func_grpc_services = None
|
|
58
60
|
self.__func_protobuf_converter = None
|
|
59
61
|
self.__func_protobuf_messages = None
|
|
62
|
+
|
|
63
|
+
self.__request_log_level = Config.log_level_grpc_request
|
|
60
64
|
|
|
61
65
|
def initialize(self, func_grpc_services, func_protobuf_converter, func_protobuf_messages):
|
|
62
66
|
self.__func_grpc_services = func_grpc_services
|
|
@@ -75,22 +79,28 @@ class GRpcClient(object):
|
|
|
75
79
|
def __protobuf_messages(self):
|
|
76
80
|
return self.__func_protobuf_messages()
|
|
77
81
|
|
|
78
|
-
@property
|
|
79
|
-
def name(self):
|
|
80
|
-
return self.__name
|
|
81
|
-
|
|
82
82
|
@property
|
|
83
83
|
def internal_client(self) -> grpc_requests.client.Client:
|
|
84
84
|
return self.__client
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
@property
|
|
87
|
+
def request_log_level(self):
|
|
88
|
+
return self.__request_log_level
|
|
89
|
+
|
|
90
|
+
@request_log_level.setter
|
|
91
|
+
def request_log_level(self, log_level):
|
|
92
|
+
self.__request_log_level = log_level
|
|
93
|
+
|
|
94
|
+
def request(self, service, method, request, raw_output=False, result_on_statuses=undefined_argument, **kwargs):
|
|
87
95
|
"""
|
|
88
96
|
:param request: request data in json or proto format
|
|
89
97
|
:param raw_output: if method should return a proto object or a json oject (default: False)
|
|
90
98
|
:param kwargs: other arguments for underlying grpc_requests method, or further underlying grpc method (ex: 'timeout')
|
|
91
99
|
:returns: if raw_output==True, returns a proto object, else returns a json object with proto data
|
|
92
100
|
"""
|
|
93
|
-
|
|
101
|
+
if Tools.do_log(logger, logging.DEBUG):
|
|
102
|
+
logger.debug(f"Requesting {service}.{method} with data [{request}] (raw_output: {raw_output} ; kwargs:{kwargs})")
|
|
103
|
+
res = undefined_value
|
|
94
104
|
|
|
95
105
|
# Set a default timeout
|
|
96
106
|
raise_on_timeout = False
|
|
@@ -110,6 +120,17 @@ class GRpcClient(object):
|
|
|
110
120
|
except Exception as exc:
|
|
111
121
|
last_exc = exc
|
|
112
122
|
exc_str = str(exc)
|
|
123
|
+
|
|
124
|
+
# Manage result on statuses
|
|
125
|
+
if result_on_statuses is not undefined_argument:
|
|
126
|
+
for status, status_result in result_on_statuses.items():
|
|
127
|
+
if f"status = StatusCode.{status.name}" in exc_str:
|
|
128
|
+
res = status_result
|
|
129
|
+
break
|
|
130
|
+
if res is not undefined_value:
|
|
131
|
+
success = True
|
|
132
|
+
break
|
|
133
|
+
|
|
113
134
|
msg_list = [
|
|
114
135
|
f"Request failed (try {try_nb}):",
|
|
115
136
|
f" method: {service}.{method}",
|
|
@@ -139,6 +160,7 @@ class GRpcClient(object):
|
|
|
139
160
|
success = True
|
|
140
161
|
break
|
|
141
162
|
|
|
163
|
+
# If still in error after all tries, raise an exception with last exception message
|
|
142
164
|
if not success:
|
|
143
165
|
if "status = " in exc_msg:
|
|
144
166
|
raise FunctionalException(exc_msg) from last_exc
|
|
@@ -149,17 +171,20 @@ class GRpcClient(object):
|
|
|
149
171
|
# Note: this step is done manually since grpc_requests has some limitations when raw_output=False:
|
|
150
172
|
# - Field with default values are not set in json result
|
|
151
173
|
# - Some field types are badly managed (ex: uint64 fields appear as string in json)
|
|
152
|
-
if
|
|
153
|
-
if
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
if isinstance(res_proto, grpc._channel._MultiThreadedRendezvous):
|
|
159
|
-
res = [self.__protobuf_converter.convert_protobuf_object_to_json_object(cur_res) for cur_res in res_proto]
|
|
174
|
+
if res is undefined_value:
|
|
175
|
+
if raw_output == True:
|
|
176
|
+
if isinstance(res_proto, grpc._channel._MultiThreadedRendezvous):
|
|
177
|
+
res = list(res_proto)
|
|
178
|
+
else:
|
|
179
|
+
res = res_proto
|
|
160
180
|
else:
|
|
161
|
-
|
|
162
|
-
|
|
181
|
+
if isinstance(res_proto, grpc._channel._MultiThreadedRendezvous):
|
|
182
|
+
res = [self.__protobuf_converter.convert_protobuf_object_to_json_object(cur_res) for cur_res in res_proto]
|
|
183
|
+
else:
|
|
184
|
+
res = self.__protobuf_converter.convert_protobuf_object_to_json_object(res_proto)
|
|
185
|
+
if Tools.do_log(logger, self.request_log_level):
|
|
186
|
+
logger.log(self.request_log_level, f"Request {service}.{method} with data [{request}] (raw_output: {raw_output} ; kwargs:{kwargs}) => {res}")
|
|
187
|
+
return res
|
|
163
188
|
|
|
164
189
|
def get_request_data_type_fullname(self, service, method):
|
|
165
190
|
method_descriptor = self.__grpc_services.get_method_descriptor(service, method)
|
holado_json/ipc/json.py
CHANGED
|
@@ -29,7 +29,7 @@ def create_name_value_table_from_json(json_value, recursive=False, uncollapse_li
|
|
|
29
29
|
converter = JsonConverter()
|
|
30
30
|
json_value = converter.to_json(json_value)
|
|
31
31
|
|
|
32
|
-
name_values =
|
|
32
|
+
name_values = convert_json_value_2_name_values(json_value, recursive=recursive, uncollapse_list=uncollapse_list)
|
|
33
33
|
for name, value in name_values:
|
|
34
34
|
res.add_row(cells_content=(name, value))
|
|
35
35
|
|
|
@@ -51,7 +51,7 @@ def create_table_with_header_from_json(json_value, recursive=False, uncollapse_l
|
|
|
51
51
|
for json_val in json_list:
|
|
52
52
|
json_val = converter.to_json(json_val)
|
|
53
53
|
|
|
54
|
-
name_values =
|
|
54
|
+
name_values = convert_json_value_2_name_values(json_val, recursive=recursive, uncollapse_list=uncollapse_list)
|
|
55
55
|
|
|
56
56
|
# Add new columns if needed
|
|
57
57
|
for name, value in name_values:
|
|
@@ -68,9 +68,17 @@ def create_table_with_header_from_json(json_value, recursive=False, uncollapse_l
|
|
|
68
68
|
|
|
69
69
|
return res
|
|
70
70
|
|
|
71
|
-
def
|
|
71
|
+
def convert_json_value_2_name_values(json_value, recursive=False, uncollapse_list=False, as_dict=False, sorted_=False):
|
|
72
|
+
"""Convert json object as a list of (name, value).
|
|
73
|
+
If as_dict is True, the result is a dict of {name:value}
|
|
74
|
+
"""
|
|
72
75
|
res = []
|
|
73
76
|
__fill_name_values_with_json_value(res, None, json_value, recursive=recursive, uncollapse_list=uncollapse_list)
|
|
77
|
+
|
|
78
|
+
if sorted_:
|
|
79
|
+
res = sorted(res)
|
|
80
|
+
if as_dict:
|
|
81
|
+
res = {e[0]:e[1] for e in res}
|
|
74
82
|
return res
|
|
75
83
|
|
|
76
84
|
def __fill_name_values_with_json_value(res, name_prefix, json_value, recursive=False, uncollapse_list=False):
|
|
@@ -123,3 +131,16 @@ def set_object_attributes_with_json_dict(obj, json_value):
|
|
|
123
131
|
else:
|
|
124
132
|
raise FunctionalException(f"Object doesn't have attribute '{attr_name}' (object type: {Typing.get_object_class_fullname(obj)})")
|
|
125
133
|
|
|
134
|
+
|
|
135
|
+
def update_json_object_with_missing_attributes(json_obj, json_ref, recursive=False):
|
|
136
|
+
if not isinstance(json_obj, dict):
|
|
137
|
+
raise TechnicalException(f"json object is expected to be a dict (obtained: {Typing.get_object_class_fullname(json_obj)}")
|
|
138
|
+
if not isinstance(json_ref, dict):
|
|
139
|
+
raise TechnicalException(f"json reference is expected to be a dict (obtained: {Typing.get_object_class_fullname(json_ref)}")
|
|
140
|
+
|
|
141
|
+
for key, value in json_ref.items():
|
|
142
|
+
if key not in json_obj:
|
|
143
|
+
json_obj[key] = value
|
|
144
|
+
elif recursive and isinstance(json_obj[key], dict) and isinstance(value, dict):
|
|
145
|
+
update_json_object_with_missing_attributes(json_obj[key], value, recursive=recursive)
|
|
146
|
+
|
|
@@ -18,6 +18,8 @@ from holado_core.common.tools.tools import Tools
|
|
|
18
18
|
import json
|
|
19
19
|
from holado_core.common.tools.converters.converter import Converter
|
|
20
20
|
from holado_json.ipc.json_converter import JsonConverter
|
|
21
|
+
from holado.common.handlers.object import Object
|
|
22
|
+
from holado.holado_config import Config
|
|
21
23
|
|
|
22
24
|
logger = logging.getLogger(__name__)
|
|
23
25
|
|
|
@@ -31,7 +33,7 @@ except Exception as exc:
|
|
|
31
33
|
with_requests = False
|
|
32
34
|
|
|
33
35
|
|
|
34
|
-
class RestClient(
|
|
36
|
+
class RestClient(Object):
|
|
35
37
|
"""
|
|
36
38
|
REST client
|
|
37
39
|
"""
|
|
@@ -41,14 +43,20 @@ class RestClient(object):
|
|
|
41
43
|
return with_requests
|
|
42
44
|
|
|
43
45
|
def __init__(self, name, url, headers=None):
|
|
44
|
-
|
|
46
|
+
super().__init__(name)
|
|
45
47
|
self.__url = url.rstrip('/')
|
|
46
48
|
self.__headers = headers if headers is not None else {}
|
|
47
49
|
self.__kwargs = {}
|
|
48
|
-
|
|
50
|
+
|
|
51
|
+
self.__request_log_level = Config.log_level_rest_request
|
|
52
|
+
|
|
49
53
|
@property
|
|
50
|
-
def
|
|
51
|
-
return self.
|
|
54
|
+
def request_log_level(self):
|
|
55
|
+
return self.__request_log_level
|
|
56
|
+
|
|
57
|
+
@request_log_level.setter
|
|
58
|
+
def request_log_level(self, log_level):
|
|
59
|
+
self.__request_log_level = log_level
|
|
52
60
|
|
|
53
61
|
def authenticate_by_user(self, user, pwd):
|
|
54
62
|
if Tools.do_log(logger, logging.DEBUG):
|
|
@@ -66,7 +74,14 @@ class RestClient(object):
|
|
|
66
74
|
raise TechnicalException(f"Unmanaged SSL arguments: {unexpected_keys}")
|
|
67
75
|
|
|
68
76
|
self.__kwargs.update(ssl_kwargs)
|
|
69
|
-
|
|
77
|
+
|
|
78
|
+
def add_parameters_to_path(self, path, parameters:dict):
|
|
79
|
+
res = path
|
|
80
|
+
if parameters:
|
|
81
|
+
res += "&" if '?' in res else "?"
|
|
82
|
+
res += "&".join([f"{k}={v}" for k,v in parameters.items()])
|
|
83
|
+
return res
|
|
84
|
+
|
|
70
85
|
def response_result(self, response, status_ok=200):
|
|
71
86
|
# Get result
|
|
72
87
|
if response.status_code == 204:
|
|
@@ -98,27 +113,32 @@ class RestClient(object):
|
|
|
98
113
|
except Exception as exc:
|
|
99
114
|
raise TechnicalException(f"[{self.name}] Failed to process {method} '{url}' with arguments {r_kwargs}") from exc
|
|
100
115
|
|
|
101
|
-
if Tools.do_log(logger, logging.DEBUG):
|
|
102
|
-
logger.debug(f"[{self.name}] {method} on url '{url}' => {res}")
|
|
103
116
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
104
117
|
logger.trace(f"[{self.name}] {method} on url '{url}' => {Tools.represent_object(res, 4)}")
|
|
118
|
+
elif Tools.do_log(logger, self.request_log_level):
|
|
119
|
+
logger.log(self.request_log_level, f"[{self.name}] {method} on url '{url}' => {Tools.represent_object(res, 4, max_level=1)}")
|
|
105
120
|
return res
|
|
106
121
|
|
|
107
|
-
def delete(self, path, data=None, **kwargs):
|
|
122
|
+
def delete(self, path, data=None, path_parameters=None, **kwargs):
|
|
123
|
+
path = self.add_parameters_to_path(path, path_parameters)
|
|
108
124
|
return self.request("DELETE", path, data=data, **kwargs)
|
|
109
125
|
|
|
110
|
-
def get(self, path, data=None, **kwargs):
|
|
126
|
+
def get(self, path, data=None, path_parameters=None, **kwargs):
|
|
127
|
+
path = self.add_parameters_to_path(path, path_parameters)
|
|
111
128
|
return self.request("GET", path, data=data, **kwargs)
|
|
112
129
|
|
|
113
|
-
def patch(self, path, data=None, **kwargs):
|
|
130
|
+
def patch(self, path, data=None, path_parameters=None, **kwargs):
|
|
131
|
+
path = self.add_parameters_to_path(path, path_parameters)
|
|
114
132
|
return self.request("PATCH", path, data=data, **kwargs)
|
|
115
133
|
|
|
116
|
-
def post(self, path, data=None, json=None, **kwargs):
|
|
134
|
+
def post(self, path, data=None, json=None, path_parameters=None, **kwargs):
|
|
135
|
+
path = self.add_parameters_to_path(path, path_parameters)
|
|
117
136
|
return self.request("POST", path, data=data, json=json, **kwargs)
|
|
118
137
|
|
|
119
|
-
def put(self, path, data=None, **kwargs):
|
|
138
|
+
def put(self, path, data=None, path_parameters=None, **kwargs):
|
|
139
|
+
path = self.add_parameters_to_path(path, path_parameters)
|
|
120
140
|
return self.request("PUT", path, data=data, **kwargs)
|
|
121
|
-
|
|
141
|
+
|
|
122
142
|
def __build_url(self, path):
|
|
123
143
|
return f"{self.__url}/{path.lstrip('/')}"
|
|
124
144
|
|
|
@@ -32,9 +32,9 @@ class RestManager(object):
|
|
|
32
32
|
self.__default_client_class = default_client_class
|
|
33
33
|
|
|
34
34
|
def new_client(self, name, **kwargs):
|
|
35
|
-
if name is None:
|
|
36
|
-
name = f"RestClient({kwargs})"
|
|
37
35
|
url = kwargs.pop("url")
|
|
36
|
+
if name is None:
|
|
37
|
+
name = f"RestClient({url})"
|
|
38
38
|
headers = Tools.pop_sub_kwargs(kwargs, "headers.")
|
|
39
39
|
authentication = Tools.pop_sub_kwargs(kwargs, "authentication.")
|
|
40
40
|
ssl_kwargs = Tools.pop_sub_kwargs(kwargs, "ssl.")
|
|
@@ -241,7 +241,7 @@ class StepTools(object):
|
|
|
241
241
|
if ValueTableManager.is_value_table(value):
|
|
242
242
|
res = value
|
|
243
243
|
elif isinstance(value, TableWithHeader):
|
|
244
|
-
res = ValueTableConverter.
|
|
244
|
+
res = ValueTableConverter.convert_table_2_value_table(value, do_eval_once=do_eval_once)
|
|
245
245
|
elif isinstance(value, Table):
|
|
246
246
|
raise FunctionalException(f"The table in variable '{cell_content}' is expected to be with header")
|
|
247
247
|
elif isinstance(table, Table):
|
|
@@ -48,6 +48,8 @@ class ValueTableConverter(TableConverter):
|
|
|
48
48
|
|
|
49
49
|
@classmethod
|
|
50
50
|
def convert_value_table_2_table(cls, table):
|
|
51
|
+
ValueTableManager.verify_is_value_table(table)
|
|
52
|
+
|
|
51
53
|
if isinstance(table, ValueTableWithHeader):
|
|
52
54
|
res = TableWithHeader()
|
|
53
55
|
res.header = copy.copy(table.header)
|
|
@@ -58,15 +60,6 @@ class ValueTableConverter(TableConverter):
|
|
|
58
60
|
res.add_row(cells_content=cells_content)
|
|
59
61
|
return res
|
|
60
62
|
|
|
61
|
-
@classmethod
|
|
62
|
-
def convert_table_with_header_2_value_table_with_header(cls, table, do_eval_once=True):
|
|
63
|
-
res = ValueTableWithHeader()
|
|
64
|
-
res.header = TableRow(cells_content=table.header.cells_content)
|
|
65
|
-
for row in table:
|
|
66
|
-
cells_content = [f"'{cc}'" if isinstance(cc, str) else f"{cc}" for cc in row.cells_content]
|
|
67
|
-
res.add_row(cells_content=cells_content, do_eval_once=do_eval_once)
|
|
68
|
-
return res
|
|
69
|
-
|
|
70
63
|
@classmethod
|
|
71
64
|
def convert_table_with_header_to_dict_list(cls, table, as_generator=False):
|
|
72
65
|
if not ValueTableManager.is_value_table(table):
|
|
@@ -123,36 +116,43 @@ class ValueTableConverter(TableConverter):
|
|
|
123
116
|
|
|
124
117
|
@classmethod
|
|
125
118
|
def convert_name_value_table_2_dict(cls, table, with_original_value_content = False):
|
|
119
|
+
if not ValueTableManager.is_value_table(table):
|
|
120
|
+
return TableConverter.convert_name_value_table_2_dict(table)
|
|
121
|
+
|
|
126
122
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
127
123
|
logger.trace(f"Converting Name/Value table to dict (table = {table})")
|
|
128
|
-
|
|
129
|
-
# Verify table structure
|
|
130
|
-
ValueTableManager.verify_table_is_name_value_table(table)
|
|
131
|
-
ValueTableManager.verify_is_value_table(table)
|
|
132
124
|
|
|
133
125
|
res = {}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
126
|
+
if table is not None:
|
|
127
|
+
# Verify table structure
|
|
128
|
+
ValueTableManager.verify_table_is_name_value_table(table)
|
|
129
|
+
ValueTableManager.verify_is_value_table(table)
|
|
130
|
+
|
|
131
|
+
for row in table.rows:
|
|
132
|
+
if row.get_cell(1).value_type not in [ValueTypes.NotApplicable]:
|
|
133
|
+
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
134
|
+
logger.trace("Converting row (%s)", row)
|
|
135
|
+
|
|
136
|
+
name = row.get_cell(0).value
|
|
137
|
+
if with_original_value_content:
|
|
138
|
+
value = row.get_cell(1).content
|
|
139
|
+
else:
|
|
140
|
+
value = row.get_cell(1).value
|
|
141
|
+
|
|
142
|
+
if name in res:
|
|
143
|
+
raise FunctionalException("Name '{}' appears several times in table".format(name))
|
|
144
|
+
else:
|
|
145
|
+
res[name] = value
|
|
146
|
+
|
|
150
147
|
if Tools.do_log(logger, logging.DEBUG):
|
|
151
148
|
logger.debug(f"Converting Name/Value table to dict (table = {table}) => {res}")
|
|
152
149
|
return res
|
|
153
150
|
|
|
154
151
|
@classmethod
|
|
155
152
|
def convert_name_value_table_2_list_and_dict(cls, table, with_original_value_content = False):
|
|
153
|
+
# if not ValueTableManager.is_value_table(table):
|
|
154
|
+
# return TableConverter.convert_name_value_table_2_list_and_dict(table)
|
|
155
|
+
|
|
156
156
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
157
157
|
logger.trace(f"Converting Name/Value table to list and dict (table = {table})")
|
|
158
158
|
|
|
@@ -186,6 +186,9 @@ class ValueTableConverter(TableConverter):
|
|
|
186
186
|
|
|
187
187
|
@classmethod
|
|
188
188
|
def convert_name_value_table_2_json_object(cls, table, converter=None):
|
|
189
|
+
if not ValueTableManager.is_value_table(table):
|
|
190
|
+
return TableConverter.convert_name_value_table_2_json_object(table, converter=converter)
|
|
191
|
+
|
|
189
192
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
190
193
|
logger.trace(f"Converting Name/Value table to json object (table = {table})")
|
|
191
194
|
if converter is None:
|
|
@@ -226,6 +229,9 @@ class ValueTableConverter(TableConverter):
|
|
|
226
229
|
|
|
227
230
|
@classmethod
|
|
228
231
|
def convert_x_name_value_table_2_list_x_values(cls, table, x_name, with_original_value_content = False):
|
|
232
|
+
# if not ValueTableManager.is_value_table(table):
|
|
233
|
+
# return TableConverter.convert_x_name_value_table_2_list_x_values(table, x_name)
|
|
234
|
+
|
|
229
235
|
if Tools.do_log(logger, logging.TRACE): # @UndefinedVariable
|
|
230
236
|
logger.trace(f"Converting {x_name}/Name/Value table to list of {x_name} and values dict (table = {table})")
|
|
231
237
|
|
|
File without changes
|
|
File without changes
|