From ce5b798558796684588f50735083c07009d3be67 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Thu, 20 Jul 2023 19:58:29 +0700 Subject: [PATCH 01/11] Improve nested parameter substitution --- JsonPreprocessor/CJsonPreprocessor.py | 62 ++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index 227760ce..3aeb2cb4 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -176,6 +176,10 @@ def __init__(self, syntax: CSyntaxType = CSyntaxType.json , currentCfg : dict = Internally used to aggregate imported json files. """ + import builtins + import keyword + self.lDataTypes = [name for name, value in vars(builtins).items() if isinstance(value, type)] + self.lDataTypes.append(keyword.kwlist) self.lImportedFiles = [] self.recursive_level = 0 self.syntax = syntax @@ -334,6 +338,31 @@ def replacer(match): return sContentCleaned + def __checkParamName(self, sInput: str) -> str: + """ + Checks a parameter name, in case the name is conflict with Python keywords, the temporary prefix + will be added to avoid any potential issues. This temporary prefix is removed when updating returned + Json object. + +**Args:** + + **sInput** (*string*) + +**Returns:** + + **sInput** (*string*) + """ + + pattern = "\${\s*([0-9A-Za-z_]+[0-9A-Za-z\.\-_]*)\s*}" + lParams = re.findall(pattern, sInput) + for param in lParams: + if "." not in param and param in self.lDataTypes: + sInput = re.sub(param, "JPavoidDataType_" + param, sInput, count=1) + if "." in param and "JPavoidDataType_" + param.split('.')[0] in globals(): + sInput = re.sub(param, "JPavoidDataType_" + param, sInput, count=1) + return sInput + + def __nestedParamHandler(self, sInputStr : str, bKey = False) -> list: ''' This method handles nested variables in parameter names or values. Variable syntax is ${Variable_Name}. @@ -493,6 +522,8 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): except: raise Exception(f"Could not set variable '{k}' with value '{v}'!") + if "JPavoidDataType_" in k: + k = re.sub("JPavoidDataType_", "", k) if isinstance(v, str): sExec = "oJson['" + k.split('[', 1)[0] + "'][" + k.split('[', 1)[1] + " = \"" + v + "\"" else: @@ -502,15 +533,20 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): except: pass else: + if "JPavoidDataType_" in k: + k = re.sub("JPavoidDataType_", "", k) oJson[k] = v else: if bNested: + if "JPavoidDataType_" in k: + k = re.sub("JPavoidDataType_", "", k) oJson[k] = v - if bool(self.currentCfg) and not recursive: for k, v in self.currentCfg.items(): + if k in self.lDataTypes: + k = "JPavoidDataType_" + k globals().update({k:v}) tmpJson = copy.deepcopy(oJson) @@ -518,8 +554,13 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): keyNested = '' if re.match('.*\${\s*', k.lower()): keyNested = k + pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" if re.match("str\(\s*\${.+", k.lower()): - k = re.sub("str\(\s*(\${.+)\s*\)", "\\1", k) + k = re.sub("str\(\s*(" + pattern + ")\s*\)", "\\1", k) + if len(re.findall(pattern, k.lower())) > 1 or k.count('{') != k.count('}'): + raise Exception(f"Could not overwrite parameter {k} due to wrong format.\n \ + Please check key '{k}' in config file!!!") + k = self.__checkParamName(k) keyAfterProcessed = self.__nestedParamHandler(k, bKey=True) k = re.sub('^\s*\${\s*(.*?)\s*}', '\\1', keyAfterProcessed[0]) @@ -535,6 +576,7 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): if re.match("str\(\s*\${.+", item.lower()): item = re.sub("str\(\s*(\${.+)\s*\)", "\\1", item) bStringValue = True + item = self.__checkParamName(item) itemAfterProcessed = self.__nestedParamHandler(item) tmpItemAfterProcessed = re.sub('\${\s*(.*?)\s*}', '\\1', itemAfterProcessed[0]) sExec = "value = " + tmpItemAfterProcessed if isinstance(tmpItemAfterProcessed, str) else \ @@ -560,6 +602,7 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): if re.search("(str\(\s*" + pattern + "\))", v.lower()): v = re.sub("str\(\s*(" + pattern + ")\s*\)", "\\1", v) bStringValue = True + v = self.__checkParamName(v) valueAfterProcessed = self.__nestedParamHandler(v) for valueProcessed in valueAfterProcessed: tmpValueAfterProcessed = re.sub('\\${\s*(.*?)\s*}', '\\1', valueProcessed) @@ -607,10 +650,14 @@ def __checkAndUpdateKeyValue(self, sInputStr: str) -> str: for nestedParam in lNestedParam: self.lNestedParams.append(nestedParam[0]) sInputStr = re.sub("(" + pattern + ")", "str(\\1)", sInputStr) - elif re.search(pattern, sInputStr.lower()): + elif re.search("^\s*" + pattern + "\s*\]*\}*,*\s*$", sInputStr.lower()): sInputStr = re.sub("(" + pattern + ")", "\"\\1\"", sInputStr) nestedParam = re.sub("^\s*\"(.+)\"\s*.*$", "\\1", sInputStr) self.lNestedParams.append(nestedParam) + else: + if len(re.findall(pattern, sInputStr.lower()))>1: + raise Exception(f"Key name or value is a mix of nested parameters and hard coded parts. \n \ + The entire expression {sInputStr.strip()} must be enclosed in quotes") sOutput = sInputStr return sOutput @@ -699,15 +746,15 @@ def __handleStrNoneTrueFalse(objJson): for item in items: i+=1 newSubItem = "" - if re.search("\s*\[[^\[\]]*\]\s*,*\s*", item): + if re.search("^\s*\[[^\[\]]*\]\s*,*\s*", item): subItems = re.split("\s*,\s*", item) - j=0 + j=0 for subItem in subItems: j+=1 if j Date: Tue, 25 Jul 2023 19:21:57 +0700 Subject: [PATCH 02/11] Updates quotes around string value --- JsonPreprocessor/CJsonPreprocessor.py | 16 ---------------- atest/jsonpreprocessor/test_jsonpreprocessor.py | 16 ++++++++-------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index 227760ce..ee99221b 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -574,9 +574,6 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): v = ldict['value'] except: raise Exception(f"The variable '{valueProcessed}' is not available!") - - if isinstance(v, str) and re.match('^\s*none|true|false\s*$', v.lower()): - v = '\"' + v + '\"' __jsonUpdated(k, v, oJson, bNested, keyNested) if keyNested != '': @@ -652,18 +649,6 @@ def jsonLoad(self, jFile : str, masterFile : bool = True): Preprocessed json file(s) as dictionary data structure ''' - def __handleStrNoneTrueFalse(objJson): - oJson = {} - for k, v in objJson.items(): - if isinstance(v, dict): - v = __handleStrNoneTrueFalse(v) - oJson[k] = v - elif isinstance(v, str) and re.match('^\s*none|true|false\s*$', v.lower()): - v = '\"' + v + '\"' - oJson[k] = v - else: - oJson[k] = v - return oJson jFile=jFile.strip() @@ -742,7 +727,6 @@ def __handleStrNoneTrueFalse(objJson): except Exception as error: raise Exception(f"json file '{jFile}': '{error}'") - oJson = __handleStrNoneTrueFalse(oJson) os.chdir(currentDir) self.__checkDotInParamName(oJson) diff --git a/atest/jsonpreprocessor/test_jsonpreprocessor.py b/atest/jsonpreprocessor/test_jsonpreprocessor.py index 47b942ed..cf7cb6be 100644 --- a/atest/jsonpreprocessor/test_jsonpreprocessor.py +++ b/atest/jsonpreprocessor/test_jsonpreprocessor.py @@ -348,15 +348,15 @@ def test_none_true_false_datatype(self): sJsonfile = os.path.abspath("../testdata/config/06_override_params/project_config_04.json") oJsonPreprocessor = CJsonPreprocessor(syntax="python") oJsonData = oJsonPreprocessor.jsonLoad(sJsonfile) - assert oJsonData['string_null'] == "null" - assert oJsonData['string_none'] == '"None"' - assert oJsonData['string_true'] == '"True"' - assert oJsonData['string_false'] == '"False"' - assert oJsonData['convert_null_to_string'] == '"None"' - assert oJsonData['convert_none_to_string'] == '"None"' + assert oJsonData['string_null'] == 'null' + assert oJsonData['string_none'] == 'None' + assert oJsonData['string_true'] == 'True' + assert oJsonData['string_false'] == 'False' + assert oJsonData['convert_null_to_string'] == 'None' + assert oJsonData['convert_none_to_string'] == 'None' assert oJsonData['convert_float_to_string'] == "1.332" - assert oJsonData['convert_true_to_string'] == '"True"' - assert oJsonData['convert_false_to_string'] == '"False"' + assert oJsonData['convert_true_to_string'] == 'True' + assert oJsonData['convert_false_to_string'] == 'False' assert oJsonData['params']['global'] == JSONFORMAT_NONE_TRUE_FALSE['params']['global'] assert oJsonData['preprocessor']['definitions'] == JSONFORMAT_NONE_TRUE_FALSE['preprocessor']['definitions'] From ad754b9f4dbb9e5d780cb8b5931adc02a6fd19cc Mon Sep 17 00:00:00 2001 From: mas2hc Date: Wed, 2 Aug 2023 13:08:43 +0700 Subject: [PATCH 03/11] Improvement misleading error message when using nested parameter --- JsonPreprocessor/CJsonPreprocessor.py | 41 ++++++++++++++++++++------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index ca536060..a33e21e0 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -611,16 +611,37 @@ def __checkAndUpdateKeyValue(self, sInputStr: str) -> str: Nested param "${abc}['xyz']" -> "str(${abc}['xyz'])" ''' - pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" - if re.match("\s*\".+\"\s*", sInputStr.lower()) and re.search("(" + pattern + ")*", sInputStr.lower()): - lNestedParam = re.findall("(" + pattern + ")", sInputStr) - for nestedParam in lNestedParam: - self.lNestedParams.append(nestedParam[0]) - sInputStr = re.sub("(" + pattern + ")", "str(\\1)", sInputStr) - elif re.search(pattern, sInputStr.lower()): - sInputStr = re.sub("(" + pattern + ")", "\"\\1\"", sInputStr) - nestedParam = re.sub("^\s*\"(.+)\"\s*.*$", "\\1", sInputStr) - self.lNestedParams.append(nestedParam) + nestedPattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" + valueStrPattern = "[\"|\']\s*[0-9A-Za-z_\-\s*]+[\"|\']" + valueNumberPattern = "[0-9\.]+" + + if "${" in sInputStr: + if re.match("\s*\".+\"\s*", sInputStr.lower()) and sInputStr.count("\"")==2 \ + and re.search("(" + nestedPattern + ")*", sInputStr.lower()): + lNestedParam = re.findall("(" + nestedPattern + ")", sInputStr) + for nestedParam in lNestedParam: + self.lNestedParams.append(nestedParam[0]) + sInputStr = re.sub("(" + nestedPattern + ")", "str(\\1)", sInputStr) + elif re.match("^\s*" + nestedPattern + "\s*,*\]*}*\s*$", sInputStr.lower()): + sInputStr = re.sub("(" + nestedPattern + ")", "\"\\1\"", sInputStr) + nestedParam = re.sub("^\s*\"(.+)\"\s*.*$", "\\1", sInputStr) + self.lNestedParams.append(nestedParam) + elif "," in sInputStr: + listPattern = "^\s*(\"*" + nestedPattern + "\"*\s*,+\s*|" + valueStrPattern + "\s*,+\s*|" + valueNumberPattern + "\s*,+\s*)+" + \ + "(\"*" + nestedPattern + "\"*\s*,*\s*|" + valueStrPattern + "\s*,*\s*|" + valueNumberPattern + "\s*,*\s*)*\]*}*\s*$" + if re.match(listPattern, sInputStr.lower()): + items = sInputStr.split(",") + for item in items: + if "${" in item and not re.match("^\s*" + nestedPattern + "\]*}*\s*$", item): + raise Exception(f"Invalid nested parameter format: {item}") + + lNestedParam = re.findall("(" + nestedPattern + ")", sInputStr) + for nestedParam in lNestedParam: + self.lNestedParams.append(nestedParam[0]) + sInputStr = re.sub("(\"\s*" + nestedPattern + "\s*\")", "str(\\1)", sInputStr) + sInputStr = re.sub("[^\(](" + nestedPattern + ")", "\"\\1\"", sInputStr) + else: + raise Exception(f"Invalid nested parameter format: {sInputStr}") sOutput = sInputStr return sOutput From ed355b2b390d07c6b43437c6a9da6e05d5340e7d Mon Sep 17 00:00:00 2001 From: mas2hc Date: Wed, 2 Aug 2023 14:36:00 +0700 Subject: [PATCH 04/11] Add additional syntax precheck. --- JsonPreprocessor/CJsonPreprocessor.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index ca536060..fd7b1f7d 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -51,6 +51,7 @@ import sys import platform import copy +import shlex class CSyntaxType(): python = "python" @@ -707,6 +708,11 @@ def __handleListElements(sInput : str) -> str: for line in sJsonData.splitlines(): if line == '' or line.isspace(): continue + try: + listDummy = shlex.split(line) + except Exception as error: + raise Exception(f"\n[shlex exception]\n {str(error)} \nin line: '{line}'") + if re.search("\${.+}", line): items = re.split("\s*:\s*", line) newLine = "" From 047d0bb4eda8e1fdbe794559cde23fb5e9f3309a Mon Sep 17 00:00:00 2001 From: mas2hc Date: Wed, 2 Aug 2023 16:21:07 +0700 Subject: [PATCH 05/11] Update a reason in error message when handling nested parameter --- JsonPreprocessor/CJsonPreprocessor.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index ca536060..50b6ea64 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -500,8 +500,9 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): sExec = k + " = \"" + v + "\"" if isinstance(v, str) else k + " = " + str(v) try: exec(sExec, globals()) - except: - raise Exception(f"Could not set variable '{k}' with value '{v}'!") + except Exception as error: + errorMsg = f"Could not set variable '{k}' with value '{v}'! Reason: {error}" + raise Exception(errorMsg) if isinstance(v, str): sExec = "oJson['" + k.split('[', 1)[0] + "'][" + k.split('[', 1)[1] + " = \"" + v + "\"" From 83c1652bc10a1e8c0b4018ee9ddcb3d465cabe15 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Wed, 2 Aug 2023 16:45:30 +0700 Subject: [PATCH 06/11] Update an exception message of syntax precheck method. --- JsonPreprocessor/CJsonPreprocessor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index fd7b1f7d..82ac96ae 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -711,7 +711,7 @@ def __handleListElements(sInput : str) -> str: try: listDummy = shlex.split(line) except Exception as error: - raise Exception(f"\n[shlex exception]\n {str(error)} \nin line: '{line}'") + raise Exception(f"\n{str(error)} in line: '{line}'") if re.search("\${.+}", line): items = re.split("\s*:\s*", line) From da9f2a354a305a756360b27314cc21385c229584 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Thu, 3 Aug 2023 17:55:05 +0700 Subject: [PATCH 07/11] Fix the issue cyclic imported JSON file --- JsonPreprocessor/CJsonPreprocessor.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index ca536060..60eec3f3 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -701,6 +701,8 @@ def __handleListElements(sInput : str) -> str: try: sJsonData= self.__load_and_removeComments(os.path.abspath(jFile)) except Exception as reason: + if masterFile: + self.__reset() raise Exception(f"Could not read json file '{jFile}' due to: '{reason}'!") sJsonDataUpdated = "" @@ -775,6 +777,8 @@ def __handleListElements(sInput : str) -> str: cls=CJSONDecoder, object_pairs_hook=self.__processImportFiles) except Exception as error: + if masterFile: + self.__reset() raise Exception(f"json file '{jFile}': '{error}'") oJson = __handleStrNoneTrueFalse(oJson) @@ -812,6 +816,7 @@ def __handleListElements(sInput : str) -> str: ldict = {} exec(sExec, globals(), ldict) except: + self.__reset() raise Exception(f"The variable '{parseNestedParam[0]}' is not available!") self.__reset() From e4df9eab300020a540810ca2ff9587ce36b3e313 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Tue, 8 Aug 2023 15:00:40 +0700 Subject: [PATCH 08/11] Improvement nested parameters handling: - Involving the fixes for issues: 57, 69, 76, 78, 80, 84, 87, 91, 93, 94, 98, 106 --- JsonPreprocessor/CJsonPreprocessor.py | 165 ++++++++++-------- .../05_sub_datastructure/json_update_02.json | 2 +- .../05_sub_datastructure/json_update_05.json | 2 +- .../05_sub_datastructure/json_update_06.json | 4 +- .../06_override_params/project_config_02.json | 2 +- 5 files changed, 96 insertions(+), 79 deletions(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index f5c0dd0d..2461a89a 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -392,16 +392,17 @@ def __nestedParamHandler(self, sInputStr : str, bKey = False) -> list: ''' def __referVarHandle(referVar : str, sInputStr : str) -> str: if "." in referVar: - dotdictVariable = re.sub('\${\s*(.*?)\s*}', '\\1', referVar) + dotdictVariable = re.sub('\$\${\s*(.*?)\s*}', '\\1', referVar) lDotdictVariable = dotdictVariable.split(".") lParams = self.__handleDotdictFormat(lDotdictVariable, []) - sParam = '${' + lParams[0] + '}' + sParam = '$${' + lParams[0] + '}' lParams.pop(0) for item in lParams: sParam = sParam + "['" + item + "']" - sInputStr = re.sub('\${\s*([^\}]*)\s*}', sParam, sInputStr) - referVar = re.findall('(\${\s*.*?\s*})', sInputStr)[0] - pattern = '(\\' + referVar + '\s*\[\s*.*?\s*\])' + sInputStr = re.sub('\$\${\s*([^\}]*)\s*}', sParam, sInputStr) + referVar = re.findall('(\$\${\s*.*?\s*})', sInputStr)[0] + tmpReferVar = re.sub("\$", "\\$", referVar) + pattern = '(' + tmpReferVar + '\s*\[\s*.*?\s*\])' variable = re.findall(pattern, sInputStr) if variable == []: return referVar @@ -416,31 +417,33 @@ def __referVarHandle(referVar : str, sInputStr : str) -> str: return referVar - pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}" + pattern = "\$\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}" referVars = re.findall("(" + pattern + ")", sInputStr) lNestedParam = [] if len(referVars) > 1: if not bKey: for referVar in referVars: - lNestedParam.append(__referVarHandle(referVar, sInputStr)) + lNestedParam.append(re.sub("\$\$", "$", __referVarHandle(referVar, sInputStr))) return lNestedParam else: sUpdateVar = referVars[0] referVars = referVars[1:] - sInputStr = re.sub('\\' + sUpdateVar, '', sInputStr, count=1) + tmpPattern = re.sub("\$", "\\$", sUpdateVar) + sInputStr = re.sub(tmpPattern, '', sInputStr, count=1) for var in referVars[::-1]: - pattern = '(\\' + var + '\s*\[\s*.*?\s*\])' + tmpVar = re.sub("\$", "\\$", var) + pattern = '(' + tmpVar + '\s*\[\s*.*?\s*\])' variable = re.findall(pattern, sInputStr) if variable == []: - sExec = "value = " + re.search('^\s*\${(\s*.*?)}', var).group(1) + sExec = "value = " + re.search('^\s*\$\${(\s*.*?)}', var).group(1) try: ldict = {} exec(sExec, globals(), ldict) tmpValue = ldict['value'] except: raise Exception(f"The variable '{var}' is not available!") - sInputStr = re.sub('\\' + var, tmpValue, sInputStr) if isinstance(tmpValue, str) else \ - re.sub('\\' + var, str(tmpValue), sInputStr) + sInputStr = re.sub(tmpVar, tmpValue, sInputStr) if isinstance(tmpValue, str) else \ + re.sub(tmpVar, str(tmpValue), sInputStr) continue while variable != []: fullVariable = variable[0] @@ -448,7 +451,7 @@ def __referVarHandle(referVar : str, sInputStr : str) -> str: variable = re.findall(pattern, sInputStr) if variable != []: fullVariable = variable[0] - sExec = "value = " + re.sub('\${\s*(.*?)\s*}', '\\1', fullVariable) + sExec = "value = " + re.sub('\$\${\s*(.*?)\s*}', '\\1', fullVariable) try: ldict = {} exec(sExec, globals(), ldict) @@ -457,13 +460,14 @@ def __referVarHandle(referVar : str, sInputStr : str) -> str: raise Exception(f"The variable '{fullVariable}' is not available!") pattern = re.sub('\[', '\\[', fullVariable) pattern = re.sub('\]', '\\]', pattern) - sInputStr = re.sub('\\' + pattern, '\'' + tmpValue + '\'', sInputStr) if isinstance(tmpValue, str) else \ - re.sub('\\' + pattern, '\'' + str(tmpValue) + '\'', sInputStr) + pattern = re.sub("\$", "\\$", pattern) + sInputStr = re.sub(pattern, '\'' + tmpValue + '\'', sInputStr) if isinstance(tmpValue, str) else \ + re.sub(pattern, '\'' + str(tmpValue) + '\'', sInputStr) sKeyHandled = sUpdateVar + sInputStr - lNestedParam.append(sKeyHandled) + lNestedParam.append(re.sub("\$\$", "$", sKeyHandled)) return lNestedParam else: - lNestedParam.append(__referVarHandle(referVars[0], sInputStr)) + lNestedParam.append(re.sub("\$\$", "$", __referVarHandle(referVars[0], sInputStr))) return lNestedParam def __handleDotdictFormat(self, lInputListParams : list, lParams: list = []) -> list: @@ -555,6 +559,31 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): k = re.sub("JPavoidDataType_", "", k) oJson[k] = v + def __loadNestedValue(sInputStr: str): + bStringValue = False + if re.search("(str\(\s*" + pattern + "\))", sInputStr.lower()): + sInputStr = re.sub("str\(\s*(" + pattern + ")\s*\)", "$\\1", sInputStr) + bStringValue = True + else: + sInputStr = re.sub("\$", "$$", sInputStr) + sInputStr = self.__checkParamName(sInputStr) + valueAfterProcessed = self.__nestedParamHandler(sInputStr) + for valueProcessed in valueAfterProcessed: + tmpValueAfterProcessed = re.sub('\\${\s*(.*?)\s*}', '\\1', valueProcessed) + sExec = "value = " + tmpValueAfterProcessed if isinstance(tmpValueAfterProcessed, str) else \ + "value = " + str(tmpValueAfterProcessed) + try: + ldict = {} + exec(sExec, globals(), ldict) + if bStringValue: + sInputStr = re.sub("(\$" + pattern + ")", str(ldict['value']), sInputStr) + else: + sInputStr = re.sub("\$\$", "$", sInputStr) + sInputStr = ldict['value'] + except: + raise Exception(f"The variable '{valueProcessed}' is not available!") + return sInputStr + if bool(self.currentCfg) and not recursive: for k, v in self.currentCfg.items(): if k in self.lDataTypes: @@ -562,19 +591,24 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): globals().update({k:v}) tmpJson = copy.deepcopy(oJson) + pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" for k, v in tmpJson.items(): keyNested = '' - if re.match('.*\${\s*', k.lower()): + if re.search("(str\(" + pattern + "\))", k.lower()): keyNested = k - pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" - if re.match("str\(\s*\${.+", k.lower()): - k = re.sub("str\(\s*(" + pattern + ")\s*\)", "\\1", k) - if len(re.findall(pattern, k.lower())) > 1 or k.count('{') != k.count('}'): - raise Exception(f"Could not overwrite parameter {k} due to wrong format.\n \ - Please check key '{k}' in config file!!!") + bNested = True + while "${" in k: + k = __loadNestedValue(k) + elif re.match("^\s*" + pattern + "\s*$", k.lower()): + keyNested = k + k = re.sub("\$", "$$", k) k = self.__checkParamName(k) keyAfterProcessed = self.__nestedParamHandler(k, bKey=True) + k = re.sub("\$\$", "$", k) k = re.sub('^\s*\${\s*(.*?)\s*}', '\\1', keyAfterProcessed[0]) + elif len(re.findall(pattern, k.lower())) > 1 or k.count('{') != k.count('}'): + raise Exception(f"Could not overwrite parameter {k} due to wrong format.\n \ + Please check key '{k}' in config file!!!") if isinstance(v, dict): v, bNested = self.__updateAndReplaceNestedParam(v, bNested, recursive=True) @@ -582,53 +616,19 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): elif isinstance(v, list): tmpValue = [] for item in v: - if isinstance(item, str) and re.match('^.*\s*\${\s*', item.lower()): - bStringValue = False + if isinstance(item, str) and re.search(pattern, item.lower()): bNested = True - if re.match("str\(\s*\${.+", item.lower()): - item = re.sub("str\(\s*(\${.+)\s*\)", "\\1", item) - bStringValue = True - item = self.__checkParamName(item) - itemAfterProcessed = self.__nestedParamHandler(item) - tmpItemAfterProcessed = re.sub('\${\s*(.*?)\s*}', '\\1', itemAfterProcessed[0]) - sExec = "value = " + tmpItemAfterProcessed if isinstance(tmpItemAfterProcessed, str) else \ - "value = " + str(tmpItemAfterProcessed) - try: - ldict = {} - exec(sExec, globals(), ldict) - if bStringValue: - item = str(ldict['value']) - else: - item = ldict['value'] - except: - raise Exception(f"The variable '{itemAfterProcessed[0]}' is not available!") + while isinstance(item, str) and "${" in item: + item = __loadNestedValue(item) tmpValue.append(item) v = tmpValue elif isinstance(v, str): - if re.match('^.*\s*\${\s*', v.lower()): - bStringValue = False + if re.search(pattern, v.lower()): bNested = True - pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" - if re.search("(str\(\s*" + pattern + "\))", v.lower()): - v = re.sub("str\(\s*(" + pattern + ")\s*\)", "\\1", v) - bStringValue = True - v = self.__checkParamName(v) - valueAfterProcessed = self.__nestedParamHandler(v) - for valueProcessed in valueAfterProcessed: - tmpValueAfterProcessed = re.sub('\\${\s*(.*?)\s*}', '\\1', valueProcessed) - sExec = "value = " + tmpValueAfterProcessed if isinstance(tmpValueAfterProcessed, str) else \ - "value = " + str(tmpValueAfterProcessed) - try: - ldict = {} - exec(sExec, globals(), ldict) - if bStringValue: - v = re.sub("(\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*)", str(ldict['value']), v, count=1) - else: - v = ldict['value'] - except: - raise Exception(f"The variable '{valueProcessed}' is not available!") + while isinstance(v, str) and "${" in v: + v = __loadNestedValue(v) __jsonUpdated(k, v, oJson, bNested, keyNested) if keyNested != '': @@ -653,17 +653,39 @@ def __checkAndUpdateKeyValue(self, sInputStr: str) -> str: Nested param "${abc}['xyz']" -> "str(${abc}['xyz'])" ''' + def __recursiveNestedHandling(sInputStr: str, lNestedParam: list) -> str: + ''' + This method handles nested parameters are called recursively in a string value. + ''' + tmpList = [] + for item in lNestedParam: + item = re.sub(r'([$()])', r'\\\1', item) + pattern = "(\${\s*[0-9A-Za-z\-_]*" + item + "[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*)" + if re.search(pattern, sInputStr): + sInputStr = re.sub("(" + pattern + ")", "str(\\1)", sInputStr) + tmpResults = re.findall("(str\(" + pattern + "\))", sInputStr) + for result in tmpResults: + tmpList.append(result[0]) + if tmpList != []: + sInputStr = __recursiveNestedHandling(sInputStr, tmpList) + + return sInputStr + nestedPattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" valueStrPattern = "[\"|\']\s*[0-9A-Za-z_\-\s*]+[\"|\']" valueNumberPattern = "[0-9\.]+" if "${" in sInputStr: - if re.match("\s*\".+\"\s*", sInputStr.lower()) and sInputStr.count("\"")==2 \ + if re.match("\s*{*\[*\".+\"\s*", sInputStr.lower()) and sInputStr.count("\"")==2 \ and re.search("(" + nestedPattern + ")*", sInputStr.lower()): lNestedParam = re.findall("(" + nestedPattern + ")", sInputStr) for nestedParam in lNestedParam: self.lNestedParams.append(nestedParam[0]) sInputStr = re.sub("(" + nestedPattern + ")", "str(\\1)", sInputStr) + tmpList = [] + for item in re.findall("(str\(" + nestedPattern + "\))", sInputStr): + tmpList.append(item[0]) + sInputStr = __recursiveNestedHandling(sInputStr, tmpList) elif re.match("^\s*" + nestedPattern + "\s*,*\]*}*\s*$", sInputStr.lower()): sInputStr = re.sub("(" + nestedPattern + ")", "\"\\1\"", sInputStr) nestedParam = re.sub("^\s*\"(.+)\"\s*.*$", "\\1", sInputStr) @@ -756,6 +778,7 @@ def __handleListElements(sInput : str) -> str: self.__reset() raise Exception(f"Could not read json file '{jFile}' due to: '{reason}'!") + pattern = "\${\s*[0-9A-Za-z_]+[0-9A-Za-z\.\-_]*\s*}(\[\s*.+\s*\])*" sJsonDataUpdated = "" for line in sJsonData.splitlines(): if line == '' or line.isspace(): @@ -765,16 +788,9 @@ def __handleListElements(sInput : str) -> str: except Exception as error: raise Exception(f"\n{str(error)} in line: '{line}'") - if re.search("\${.+}", line): + if re.search(pattern, line): items = re.split("\s*:\s*", line) newLine = "" - if len(items) > 1: - if re.match("^\s*\${.+", items[0]): - items[0] = '"' + items[0].strip() + '"' - newLine = items[0] + ": " - items.pop(0) - else: - items[0] = items[0].strip() i=0 for item in items: i+=1 @@ -866,8 +882,9 @@ def __handleListElements(sInput : str) -> str: # Checking availability of nested parameters before updating and replacing. for param in self.lNestedParams: param = self.__checkParamName(param) + param = re.sub("\${", "$${", param) parseNestedParam = self.__nestedParamHandler(param) - tmpParseNestedParam = re.sub('\\${\s*(.*?)\s*}', '\\1', parseNestedParam[0]) + tmpParseNestedParam = re.sub('\${\s*(.*?)\s*}', '\\1', parseNestedParam[0]) sExec = "value = " + tmpParseNestedParam if isinstance(tmpParseNestedParam, str) else \ "value = " + str(tmpParseNestedParam) try: diff --git a/atest/testdata/config/05_sub_datastructure/json_update_02.json b/atest/testdata/config/05_sub_datastructure/json_update_02.json index 41df781f..b8e373c5 100644 --- a/atest/testdata/config/05_sub_datastructure/json_update_02.json +++ b/atest/testdata/config/05_sub_datastructure/json_update_02.json @@ -15,6 +15,6 @@ { ${params}['glo']['globalString']: "Welcome to Jsonpreprocessor Acceptance Test", - "${preprocessor}['definitions']['preproStructure']['variable_01']": 0.192, + ${preprocessor}['definitions']['preproStructure']['variable_01']: 0.192, ${Project}: "Acceptance Testing" } diff --git a/atest/testdata/config/05_sub_datastructure/json_update_05.json b/atest/testdata/config/05_sub_datastructure/json_update_05.json index ee97bd29..c4fe7484 100644 --- a/atest/testdata/config/05_sub_datastructure/json_update_05.json +++ b/atest/testdata/config/05_sub_datastructure/json_update_05.json @@ -14,5 +14,5 @@ //************************************************************************** { - "${preprocessor}['definitions']['preproTest'][${preprocessor}['definitions']['preproStructure']['variable_02']]": ${params}['glo']['globalString'] + ${preprocessor}['definitions']['preproTest'][${preprocessor}['definitions']['preproStructure']['variable_02']]: ${params}['glo']['globalString'] } diff --git a/atest/testdata/config/05_sub_datastructure/json_update_06.json b/atest/testdata/config/05_sub_datastructure/json_update_06.json index d8955d98..39435ae4 100644 --- a/atest/testdata/config/05_sub_datastructure/json_update_06.json +++ b/atest/testdata/config/05_sub_datastructure/json_update_06.json @@ -16,7 +16,6 @@ { ${sWelcome}: ${Project}, ${params}['glo']['globalIntParam']: 69, - ${preprocessor}['definitions']['preproStructure']['variable_01']: ${preprocessor}['definitions']['preproStructure']['newStruct']['check1'], "params": { "glo": { "globalFloatParam": 97, @@ -37,5 +36,6 @@ "param_01": "Updated new value" } } - } + }, + ${preprocessor}['definitions']['preproStructure']['variable_01']: ${preprocessor}['definitions']['preproStructure']['newStruct']['check1'] } diff --git a/atest/testdata/config/06_override_params/project_config_02.json b/atest/testdata/config/06_override_params/project_config_02.json index 95d17194..9287eda7 100644 --- a/atest/testdata/config/06_override_params/project_config_02.json +++ b/atest/testdata/config/06_override_params/project_config_02.json @@ -23,7 +23,7 @@ "Project":"JsonPreprocessor", "Descriptioin":"Json Preprocessor Acceptance Test", "[import]": "./common/definitions_common.json", - "${gPreproString}": "Override string param in imported file.", + ${gPreproString}: "Override string param in imported file.", "params":{ "global":{ "dSUT":{ From 9528206b0994eacd6fb78e0ed6a8e4b9f05c4f69 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Tue, 8 Aug 2023 16:55:46 +0700 Subject: [PATCH 09/11] Add tiny change to fix the issue parse nested param --- JsonPreprocessor/CJsonPreprocessor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index 2461a89a..2b9b993f 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -576,7 +576,7 @@ def __loadNestedValue(sInputStr: str): ldict = {} exec(sExec, globals(), ldict) if bStringValue: - sInputStr = re.sub("(\$" + pattern + ")", str(ldict['value']), sInputStr) + sInputStr = re.sub("(\$" + pattern + ")", str(ldict['value']), sInputStr, count=1) else: sInputStr = re.sub("\$\$", "$", sInputStr) sInputStr = ldict['value'] From fb7c372c110da62fcf5edcd26c2c71b6057305d3 Mon Sep 17 00:00:00 2001 From: qth2hi Date: Wed, 9 Aug 2023 17:31:35 +0200 Subject: [PATCH 10/11] Initial start of new workflow (no concrete changes, output files recreated only) Reference: https://github.com/test-fullautomation/python-jsonpreprocessor/tree/namsonx/task/stabi_branch https://github.com/test-fullautomation/python-jsonpreprocessor/commit/0f7808446e7d456352f9c8b5bf9beec31cde09aa --- test/JPP_TestUsecases.html | 2 +- test/JPP_TestUsecases.rst | 2 +- test/JPP_TestUsecases.txt | 2 +- test/pytest/pytestfiles/test_01_DATA_TYPES_GOODCASE.py | 2 +- test/pytest/pytestfiles/test_02_DATA_INTEGRITY_GOODCASE.py | 2 +- .../pytestfiles/test_03_PARAMETER_SUBSTITUTION_GOODCASE.py | 2 +- .../pytestfiles/test_04_PARAMETER_SUBSTITUTION_BADCASE.py | 2 +- test/pytest/pytestfiles/test_05_VALUE_DETECTION_GOODCASE.py | 2 +- test/pytest/pytestfiles/test_06_VALUE_DETECTION_BADCASE.py | 2 +- .../pytestfiles/test_07_COMPOSITE_EXPRESSIONS_GOODCASE.py | 2 +- .../pytestfiles/test_08_COMMON_SYNTAX_VIOLATIONS_GOODCASE.py | 2 +- .../pytestfiles/test_09_COMMON_SYNTAX_VIOLATIONS_BADCASE.py | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/JPP_TestUsecases.html b/test/JPP_TestUsecases.html index 89bae9ae..2569e069 100644 --- a/test/JPP_TestUsecases.html +++ b/test/JPP_TestUsecases.html @@ -860,7 +860,7 @@
 

-
Generated: 09.08.2023 - 11:47:23
+
Generated: 09.08.2023 - 17:28:15
 
diff --git a/test/JPP_TestUsecases.rst b/test/JPP_TestUsecases.rst index 75bbe18f..6b55b4fe 100644 --- a/test/JPP_TestUsecases.rst +++ b/test/JPP_TestUsecases.rst @@ -273,5 +273,5 @@ Test Use Cases ---- -Generated: 09.08.2023 - 11:47:23 +Generated: 09.08.2023 - 17:28:15 diff --git a/test/JPP_TestUsecases.txt b/test/JPP_TestUsecases.txt index 0ede77ee..9c0829f4 100644 --- a/test/JPP_TestUsecases.txt +++ b/test/JPP_TestUsecases.txt @@ -119,5 +119,5 @@ Test JPP_0954 / COMMON_SYNTAX_VIOLATIONS / BADCASE Description: JSON file with syntax error (5): file is empty (multiple pairs of brackets only) Expectation: No values are returned, and JsonPreprocessor throws an exception ------------------------------------------------------------------------------------------------------------------------ -Generated: 09.08.2023 - 11:47:23 +Generated: 09.08.2023 - 17:28:15 diff --git a/test/pytest/pytestfiles/test_01_DATA_TYPES_GOODCASE.py b/test/pytest/pytestfiles/test_01_DATA_TYPES_GOODCASE.py index dc79b7f6..28f210e9 100644 --- a/test/pytest/pytestfiles/test_01_DATA_TYPES_GOODCASE.py +++ b/test/pytest/pytestfiles/test_01_DATA_TYPES_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_02_DATA_INTEGRITY_GOODCASE.py b/test/pytest/pytestfiles/test_02_DATA_INTEGRITY_GOODCASE.py index c1bba20e..5158e546 100644 --- a/test/pytest/pytestfiles/test_02_DATA_INTEGRITY_GOODCASE.py +++ b/test/pytest/pytestfiles/test_02_DATA_INTEGRITY_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_03_PARAMETER_SUBSTITUTION_GOODCASE.py b/test/pytest/pytestfiles/test_03_PARAMETER_SUBSTITUTION_GOODCASE.py index 7b14f10e..949b1ec0 100644 --- a/test/pytest/pytestfiles/test_03_PARAMETER_SUBSTITUTION_GOODCASE.py +++ b/test/pytest/pytestfiles/test_03_PARAMETER_SUBSTITUTION_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_04_PARAMETER_SUBSTITUTION_BADCASE.py b/test/pytest/pytestfiles/test_04_PARAMETER_SUBSTITUTION_BADCASE.py index 11ce7b41..d59f28fd 100644 --- a/test/pytest/pytestfiles/test_04_PARAMETER_SUBSTITUTION_BADCASE.py +++ b/test/pytest/pytestfiles/test_04_PARAMETER_SUBSTITUTION_BADCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_05_VALUE_DETECTION_GOODCASE.py b/test/pytest/pytestfiles/test_05_VALUE_DETECTION_GOODCASE.py index ca126b6c..2028652e 100644 --- a/test/pytest/pytestfiles/test_05_VALUE_DETECTION_GOODCASE.py +++ b/test/pytest/pytestfiles/test_05_VALUE_DETECTION_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_06_VALUE_DETECTION_BADCASE.py b/test/pytest/pytestfiles/test_06_VALUE_DETECTION_BADCASE.py index dd7f77c4..da398118 100644 --- a/test/pytest/pytestfiles/test_06_VALUE_DETECTION_BADCASE.py +++ b/test/pytest/pytestfiles/test_06_VALUE_DETECTION_BADCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_07_COMPOSITE_EXPRESSIONS_GOODCASE.py b/test/pytest/pytestfiles/test_07_COMPOSITE_EXPRESSIONS_GOODCASE.py index ecab0ff4..87b5a53e 100644 --- a/test/pytest/pytestfiles/test_07_COMPOSITE_EXPRESSIONS_GOODCASE.py +++ b/test/pytest/pytestfiles/test_07_COMPOSITE_EXPRESSIONS_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_08_COMMON_SYNTAX_VIOLATIONS_GOODCASE.py b/test/pytest/pytestfiles/test_08_COMMON_SYNTAX_VIOLATIONS_GOODCASE.py index 55b1d2df..334fddc2 100644 --- a/test/pytest/pytestfiles/test_08_COMMON_SYNTAX_VIOLATIONS_GOODCASE.py +++ b/test/pytest/pytestfiles/test_08_COMMON_SYNTAX_VIOLATIONS_GOODCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- diff --git a/test/pytest/pytestfiles/test_09_COMMON_SYNTAX_VIOLATIONS_BADCASE.py b/test/pytest/pytestfiles/test_09_COMMON_SYNTAX_VIOLATIONS_BADCASE.py index bc6c6241..1e972078 100644 --- a/test/pytest/pytestfiles/test_09_COMMON_SYNTAX_VIOLATIONS_BADCASE.py +++ b/test/pytest/pytestfiles/test_09_COMMON_SYNTAX_VIOLATIONS_BADCASE.py @@ -18,7 +18,7 @@ # # XC-CT/ECA3-Queckenstedt # -# 09.08.2023 - 11:47:23 +# 09.08.2023 - 17:28:15 # # -------------------------------------------------------------------------------------------------------------- From ec47da7bee41c1d671b0dba49d665bc263f001c8 Mon Sep 17 00:00:00 2001 From: mas2hc Date: Thu, 10 Aug 2023 18:19:27 +0700 Subject: [PATCH 11/11] Tiny change to fix issue for test cases JPP_0300 JPP_0500 JPP_0502 JPP_0300 JPP_0600 --- JsonPreprocessor/CJsonPreprocessor.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/JsonPreprocessor/CJsonPreprocessor.py b/JsonPreprocessor/CJsonPreprocessor.py index 2b9b993f..5b45a105 100644 --- a/JsonPreprocessor/CJsonPreprocessor.py +++ b/JsonPreprocessor/CJsonPreprocessor.py @@ -195,7 +195,7 @@ def __reset(self) -> None: ''' self.lImportedFiles = [] self.recursive_level = 0 - self.lUpdatedParams = {} + self.dUpdatedParams = {} self.lNestedParams = [] self.lDotInParamName = [] @@ -535,6 +535,7 @@ def __jsonUpdated(k, v, oJson, bNested, keyNested = ''): try: exec(sExec, globals()) except Exception as error: + self.__reset() errorMsg = f"Could not set variable '{k}' with value '{v}'! Reason: {error}" raise Exception(errorMsg) @@ -581,6 +582,7 @@ def __loadNestedValue(sInputStr: str): sInputStr = re.sub("\$\$", "$", sInputStr) sInputStr = ldict['value'] except: + self.__reset() raise Exception(f"The variable '{valueProcessed}' is not available!") return sInputStr