diff --git a/gui/wxpython/gmodeler/model.py b/gui/wxpython/gmodeler/model.py index 0c2d62e006c..9d0f58ec7d4 100644 --- a/gui/wxpython/gmodeler/model.py +++ b/gui/wxpython/gmodeler/model.py @@ -3333,6 +3333,12 @@ def __init__(self, fd, model, grassAPI="script"): self._writePython() def _getStandardizedOption(self, string): + """Return GRASS standardized option based on specified string. + + :param string: input string to be converted + + :return: GRASS standardized option as a string or None if not converted + """ if string == "raster": return "G_OPT_R_MAP" elif string == "vector": @@ -3346,7 +3352,7 @@ def _getStandardizedOption(self, string): elif string == "region": return "G_OPT_M_REGION" - return "" + return None def _writePython(self): """Write model to file""" @@ -3390,7 +3396,8 @@ def _writePython(self): modelItems = self.model.GetItems(ModelAction) for item in modelItems: - for flag in item.GetParameterizedParams()["flags"]: + parametrizedParams = item.GetParameterizedParams() + for flag in parametrizedParams["flags"]: if flag["label"]: desc = flag["label"] else: @@ -3414,7 +3421,7 @@ def _writePython(self): self.fd.write("# % answer: False\n") self.fd.write("# %end\n") - for param in item.GetParameterizedParams()["params"]: + for param in parametrizedParams["params"]: if param["label"]: desc = param["label"] else: @@ -3441,6 +3448,29 @@ def _writePython(self): self.fd.write("# % answer: {}\n".format(param["value"])) self.fd.write("# %end\n") + # variables + for vname, vdesc in self.model.GetVariables().items(): + self.fd.write("# %option") + optionType = self._getStandardizedOption(vdesc["type"]) + if optionType: + self.fd.write(" {}".format(optionType)) + self.fd.write("\n") + self.fd.write( + r"""# % key: {param_name} +# % description: {description} +# % required: yes +""".format( + param_name=vname, + description=vdesc.get("description", ""), + ) + ) + if optionType is None and vdesc["type"]: + self.fd.write("# % type: {}\n".format(vdesc["type"])) + + if vdesc["value"]: + self.fd.write("# % answer: {}\n".format(vdesc["value"])) + self.fd.write("# %end\n") + # import modules self.fd.write( r""" @@ -3489,8 +3519,11 @@ def cleanup(): self.fd.write(" pass\n") self.fd.write("\ndef main(options, flags):\n") + modelVars = self.model.GetVariables() for item in self.model.GetItems(ModelAction): - self._writeItem(item, variables=item.GetParameterizedParams()) + modelParams = item.GetParameterizedParams() + modelParams["vars"] = modelVars + self._writeItem(item, variables=modelParams) self.fd.write(" return 0\n") @@ -3533,6 +3566,45 @@ def _writePythonAction(self, item, variables={}, intermediates=None): strcmd + self._getPythonActionCmd(item, task, len(strcmd), variables) + "\n" ) + def _substitutePythonParamValue( + self, value, name, parameterizedParams, variables, item + ): + """Substitute parameterized options or variables. + + :param value: parameter value to be substituted + :param name: parameter name + :param parameterizedParams: list of parameterized options + :param variables: list of user-defined variables + :param item: item object + + :return: substituted value + """ + foundVar = False + parameterizedValue = value + + if name in parameterizedParams: + foundVar = True + parameterizedValue = 'options["{}"]'.format(self._getParamName(name, item)) + else: + # check for variables + formattedVar = False + for var in variables["vars"]: + pattern = re.compile("%" + var) + found = pattern.search(value) + if found: + foundVar = True + if found.end() != len(value): + formattedVar = True + parameterizedValue = pattern.sub( + "{options['" + var + "']}", value + ) + else: + parameterizedValue = f'options["{var}"]' + if formattedVar: + parameterizedValue = 'f"' + parameterizedValue + '"' + + return foundVar, parameterizedValue + def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): opts = task.get_options() @@ -3560,11 +3632,18 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): value = list(map(float, value)) if (name and value) or (name in parameterizedParams): - foundVar = False - - if name in parameterizedParams: - foundVar = True - value = 'options["{}"]'.format(self._getParamName(name, item)) + if isinstance(value, list): + foundVar = False + for idx in range(len(value)): + foundVar_, value[idx] = self._substitutePythonParamValue( + value[idx], name, parameterizedParams, variables, item + ) + if foundVar_ is True: + foundVar = True + else: + foundVar, value = self._substitutePythonParamValue( + value, name, parameterizedParams, variables, item + ) if ( foundVar @@ -3577,7 +3656,7 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): ret += '"%s"' % task.get_name() if flags: - ret += ",\n{indent}flags='{fl}'".format(indent=" " * cmdIndent, fl=flags) + ret += ',\n{indent}flags="{fl}"'.format(indent=" " * cmdIndent, fl=flags) if itemParameterizedFlags: ret += " + getParameterizedFlags(options, [{}])".format( itemParameterizedFlags @@ -3597,40 +3676,6 @@ def _getPythonActionCmd(self, item, task, cmdIndent, variables={}): return ret - def _substituteVariable(self, string, variable, data): - """Substitute variable in the string - - :param string: string to be modified - :param variable: variable to be substituted - :param data: data related to the variable - - :return: modified string - """ - result = "" - ss = re.split(r"\w*(%" + variable + ")w*", string) - - if not ss[0] and not ss[-1]: - if data: - return "options['%s']" % variable - else: - return variable - - for s in ss: - if not s or s == '"': - continue - - if s == "%" + variable: - if data: - result += "+options['%s']+" % variable - else: - result += "+%s+" % variable - else: - result += '"' + s - if not s.endswith("]"): # options - result += '"' - - return result.strip("+") - class ModelParamDialog(wx.Dialog): def __init__(