From cdbc98baf633adbb2702e574b652f59dff65bd4f Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Wed, 4 Dec 2024 16:56:09 +0100 Subject: [PATCH 01/11] fix: save latest changes --- src/pyconverter/xml2py/ast_tree.py | 52 ++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 14 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index a256314da..f046ba37a 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -135,7 +135,12 @@ def get_quant_iter_pos(name: str) -> tuple: def to_py_arg_name(name: str) -> str: """Python-compatible term""" arg = str(name).lower().strip() - p = engine() + if arg == "": + return arg + elif arg.isdigit(): + return "" + if arg[0].isdigit(): + p = engine() if arg[0].isdigit(): if arg[1].isdigit(): raise ValueError(f"The code needs to be expanded to handle numbers") @@ -146,8 +151,11 @@ def to_py_arg_name(name: str) -> str: num_value = p.number_to_words(arg[:3]) arg = f"{num_value}{arg[3:]}" - if ("," in arg and "--" in arg) or arg == "–": - return "" + if "--" in arg or arg == "–": + arg = arg.replace("--", "") + arg = arg.replace("–", "") + arg = arg.replace(" ", "") + return arg for key, value in PY_ARG_CLEANUP.items(): arg = arg.replace(key, value) @@ -204,7 +212,7 @@ def str_types(types, join_str: str) -> str: def to_py_signature(py_arg_name, types) -> str: """Return the Python signature of the argument.""" - if py_arg_name not in ["--", "–", ""]: + if "," not in py_arg_name and py_arg_name != "": kwarg = f'{py_arg_name}: {str_types(types, " | ")} = ""' else: kwarg = None @@ -2119,16 +2127,17 @@ def _parse_list_entry(self): additional_args = argument_obj.multiple_args if len(additional_args) > 0: for arg in additional_args: - if arg.py_arg_name != "" and arg.py_arg_name not in self.py_arg_names: + arg_name = arg.py_arg_name + if ("," in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): self._arguments.append(arg) else: - if argument_obj.py_arg_name != "": - self._arguments.append(argument_obj) + self._arguments.append(argument_obj) def __iadd__(self, argument_list): for arg in argument_list.arguments: - if arg.py_arg_name not in self.py_arg_names: + arg_name = arg.py_arg_name + if ("," not in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): self._arguments.append(arg) return self @@ -2350,7 +2359,7 @@ def to_py_docstring( self, max_length=100, indent="", links=None, base_url=None, fcache=None ) -> List[str]: """Return a list of string to enable converting the element to an RST format.""" - if self.py_arg_name not in ["--", "–", ""]: + if "," not in self.py_arg_name and self.py_arg_name != "": docstring = [f'{indent}{self.py_arg_name} : {str_types(self.types, " or ")}'] if isinstance(self._description, str): rst_description = self._description @@ -2373,6 +2382,7 @@ def to_py_docstring( docstring = [f'{indent}{self.py_arg_name} : {str_types(self.types, " or ")}'] docstring.extend(list_description) + else: docstring = [] return docstring @@ -2442,6 +2452,8 @@ def arg_desc(self) -> List[Argument]: arguments = ArgumentList(child, self.args) else: arguments += ArgumentList(child, self.args) + if self.py_name == "secmodif": + print(arguments.py_arg_names) else: for elem in refsyn: @@ -2450,14 +2462,20 @@ def arg_desc(self) -> List[Argument]: arguments = ArgumentList(elem, self.args) else: arguments += ArgumentList(elem, self.args) + if self.py_name == "secmodif": + print("HERE") + print(arguments.py_arg_names) + + # if self.py_name in ["secmodif", "dmat"]: + # print(arguments.initial_args) + # print(arguments.py_arg_names) if arguments is not None: if len(arguments.py_arg_names) < len(arguments.initial_args): for arg in arguments.initial_args: if arg not in arguments.py_arg_names: new_arg = Argument(arg, arguments.initial_args, "") - if new_arg.py_arg_name != "": - arguments.arguments.append(new_arg) + arguments.arguments.append(new_arg) return arguments.arguments @@ -2899,9 +2917,15 @@ def py_source(self, custom_functions=None, indent=""): if len(self.arg_desc) > 0: command = 'command = f"' + self.name for arg in self.arg_desc: - command += ",{" - command += arg.py_arg_name - command += "}" + name = arg.py_arg_name + if "," in name: + command += f",{name}" + elif name == "": + command += "," + else: + command += ",{" + command += arg.py_arg_name + command += "}" command += '"\n' # ",{" + "},{".join(self.arg_desc.py_arg_name) + '}"\n' else: From c34cf9cbc07fda66f1ae98574fd418f7166ce165 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:22:17 +0100 Subject: [PATCH 02/11] fix: double args --- src/pyconverter/xml2py/ast_tree.py | 54 ++++++++++++++++++------------ 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index f046ba37a..13f93d369 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -24,6 +24,7 @@ import textwrap from typing import List import warnings +from pathlib import Path from inflect import engine from lxml.etree import tostring @@ -2113,8 +2114,9 @@ class ProductName(Element): class ArgumentList: - def __init__(self, list_entry: VarlistEntry, args: List) -> None: + def __init__(self, py_name: str, list_entry: VarlistEntry, args: List) -> None: + self._py_name = py_name self._list_entry = list_entry self._arguments = [] self._initial_args = args @@ -2137,7 +2139,7 @@ def _parse_list_entry(self): def __iadd__(self, argument_list): for arg in argument_list.arguments: arg_name = arg.py_arg_name - if ("," not in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): + if ("," in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): self._arguments.append(arg) return self @@ -2148,6 +2150,10 @@ def arguments(self): @arguments.setter def arguments(self, argument): self._arguments.append(argument) + + @property + def py_name(self): + return self._py_name @property def initial_args(self): @@ -2449,33 +2455,39 @@ def arg_desc(self) -> List[Argument]: for child in elem: if isinstance(child, Variablelist): if arguments is None: - arguments = ArgumentList(child, self.args) + arguments = ArgumentList(self.py_name, child, self.args) else: - arguments += ArgumentList(child, self.args) - if self.py_name == "secmodif": - print(arguments.py_arg_names) + arguments += ArgumentList(self.py_name, child, self.args) else: for elem in refsyn: if isinstance(elem, Variablelist): if arguments is None: - arguments = ArgumentList(elem, self.args) + arguments = ArgumentList(self.py_name, elem, self.args) else: - arguments += ArgumentList(elem, self.args) - if self.py_name == "secmodif": - print("HERE") - print(arguments.py_arg_names) - - - # if self.py_name in ["secmodif", "dmat"]: - # print(arguments.initial_args) - # print(arguments.py_arg_names) + arguments += ArgumentList(self.py_name, elem, self.args) + if arguments is not None: - if len(arguments.py_arg_names) < len(arguments.initial_args): - for arg in arguments.initial_args: - if arg not in arguments.py_arg_names: - new_arg = Argument(arg, arguments.initial_args, "") - arguments.arguments.append(new_arg) + if len(arguments.py_arg_names) != len(arguments.initial_args): + # This function needs a special treatment + if Path("args.txt").exists(): + with open("args.txt", "r") as f: + for line in f: + pass + last_line = line + else: + last_line = "" + with open("args.txt", "a") as f: + if last_line != f"{arguments.py_arg_names}\n": + f.write("--------------------------------------------------\n") + f.write(f"{self.py_name}: {self.group}\n") + f.write(f"{arguments.initial_args}\n") + f.write(f"{arguments.py_arg_names}\n") + + # for arg in arguments.initial_args: + # if arg not in arguments.py_arg_names: + # new_arg = Argument(arg, arguments.initial_args, "") + # arguments.arguments.append(new_arg) return arguments.arguments From ec99972a339894e4808df841a57fce2ce5db5d0c Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:09:28 +0100 Subject: [PATCH 03/11] fix: latest changes --- src/pyconverter/xml2py/ast_tree.py | 90 +++++++++++------------------- src/pyconverter/xml2py/cli.py | 4 ++ 2 files changed, 36 insertions(+), 58 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index 13f93d369..02bdb7ca2 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -21,10 +21,10 @@ # SOFTWARE. import logging +from pathlib import Path import textwrap from typing import List import warnings -from pathlib import Path from inflect import engine from lxml.etree import tostring @@ -135,14 +135,14 @@ def get_quant_iter_pos(name: str) -> tuple: def to_py_arg_name(name: str) -> str: """Python-compatible term""" - arg = str(name).lower().strip() - if arg == "": + initial_arg = str(name).lower().strip() + arg = initial_arg + if arg in ["--", "–", ""]: return arg elif arg.isdigit(): return "" if arg[0].isdigit(): p = engine() - if arg[0].isdigit(): if arg[1].isdigit(): raise ValueError(f"The code needs to be expanded to handle numbers") elif arg[1:3] not in superlatif: @@ -152,12 +152,6 @@ def to_py_arg_name(name: str) -> str: num_value = p.number_to_words(arg[:3]) arg = f"{num_value}{arg[3:]}" - if "--" in arg or arg == "–": - arg = arg.replace("--", "") - arg = arg.replace("–", "") - arg = arg.replace(" ", "") - return arg - for key, value in PY_ARG_CLEANUP.items(): arg = arg.replace(key, value) arg = arg.strip() @@ -213,7 +207,7 @@ def str_types(types, join_str: str) -> str: def to_py_signature(py_arg_name, types) -> str: """Return the Python signature of the argument.""" - if "," not in py_arg_name and py_arg_name != "": + if py_arg_name not in ["--", "–", ""]: kwarg = f'{py_arg_name}: {str_types(types, " | ")} = ""' else: kwarg = None @@ -999,9 +993,9 @@ def py_term(self, links=None, base_url=None): return f"{arg}" if self.term.tag in item_needing_links_base_url: - arg = self.term.to_rst(links=links, base_url=base_url).replace("--", "").strip() + arg = self.term.to_rst(links=links, base_url=base_url).strip() else: - arg = self.term.to_rst().replace("--", "").strip() + arg = self.term.to_rst().strip() # sanity check if "blank" in arg.lower(): @@ -1605,6 +1599,7 @@ def raw_args(self): cmd = cmd.replace("&fname2_arg;", self._terms["fname2_arg"]) cmd = cmd.replace("&pn006p;", self._terms["pn006p"]) cmd = cmd.replace("&ansysBrand;", self._terms["ansysBrand"]) + cmd = cmd.replace("``", "") split_args = cmd.split(",")[1:] return split_args @@ -1613,36 +1608,29 @@ def args(self): """Command arguments.""" args = [] for item in self.raw_args: - orig_arg = str(item).replace(",", "") - arg = orig_arg.lower().replace("--", "").replace("–", "").replace("-", "_").strip() - if arg == "": - continue - - if arg == "class": - arg = "class_" - elif arg == "type": - arg = "type_" + arg = to_py_arg_name(str(item)) # simply check if we can use this as a valid Python kwarg try: exec(f"{arg} = 1.0") except SyntaxError: - continue + arg = "" if "blank" in arg: - continue + arg = "" args.append(arg) # rename duplicate arguments if len(args) != len(set(args)): for arg in args: - i = 0 - if args.count(arg) > 1: - for j in range(len(args)): - if args[j] == arg: - args[j] = f"{arg}{i:d}" - i += 1 + if arg not in ["", "--", "–"]: + i = 0 + if args.count(arg) > 1: + for j in range(len(args)): + if args[j] == arg: + args[j] = f"{arg}{i:d}" + i += 1 return args @@ -2130,7 +2118,7 @@ def _parse_list_entry(self): if len(additional_args) > 0: for arg in additional_args: arg_name = arg.py_arg_name - if ("," in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): + if (arg_name in self._initial_args) and (arg_name not in self.py_arg_names): self._arguments.append(arg) else: @@ -2139,7 +2127,7 @@ def _parse_list_entry(self): def __iadd__(self, argument_list): for arg in argument_list.arguments: arg_name = arg.py_arg_name - if ("," in arg_name or arg_name == "") or (arg_name not in self.py_arg_names): + if (arg_name in self._initial_args) and (arg_name not in self.py_arg_names): self._arguments.append(arg) return self @@ -2150,7 +2138,7 @@ def arguments(self): @arguments.setter def arguments(self, argument): self._arguments.append(argument) - + @property def py_name(self): return self._py_name @@ -2216,10 +2204,9 @@ def multiple_args(self): if not self.is_arg_elipsis: for item_name in split_name: arg_name = item_name.strip() - if arg_name not in ["--", ""]: - new_arg = Argument(arg_name, self._initial_argument, self._description) - if new_arg.py_arg_name != "": - additional_args.append(new_arg) + new_arg = Argument(arg_name, self._initial_argument, self._description) + if new_arg.py_arg_name != "": + additional_args.append(new_arg) else: complete_args = get_complete_args_from_initial_arg( @@ -2304,19 +2291,6 @@ def multiple_args(self): return additional_args - def rec_find(self, _type: str, terms=None) -> Element | None: - """Find the first type matching a given type string recursively.""" - for item in self: - if type(item).__name__ == _type: - if _type == "Refname" or _type == "Refnamediv": - item.terms = terms - return item - if isinstance(item, Element): - subitem = item.rec_find(_type) - if subitem is not None: - return subitem - return None - @property def types(self) -> List[type]: """One or more parameter types. @@ -2466,24 +2440,26 @@ def arg_desc(self) -> List[Argument]: arguments = ArgumentList(self.py_name, elem, self.args) else: arguments += ArgumentList(self.py_name, elem, self.args) - + + arg_file = Path("args.txt") + if arguments is not None: if len(arguments.py_arg_names) != len(arguments.initial_args): # This function needs a special treatment - if Path("args.txt").exists(): - with open("args.txt", "r") as f: + if arg_file.exists(): + with open(arg_file, "r") as f: for line in f: pass last_line = line else: last_line = "" - with open("args.txt", "a") as f: + with open(arg_file, "a") as f: if last_line != f"{arguments.py_arg_names}\n": f.write("--------------------------------------------------\n") f.write(f"{self.py_name}: {self.group}\n") f.write(f"{arguments.initial_args}\n") f.write(f"{arguments.py_arg_names}\n") - + # for arg in arguments.initial_args: # if arg not in arguments.py_arg_names: # new_arg = Argument(arg, arguments.initial_args, "") @@ -2930,9 +2906,7 @@ def py_source(self, custom_functions=None, indent=""): command = 'command = f"' + self.name for arg in self.arg_desc: name = arg.py_arg_name - if "," in name: - command += f",{name}" - elif name == "": + if name in ["--", "–", ""]: command += "," else: command += ",{" diff --git a/src/pyconverter/xml2py/cli.py b/src/pyconverter/xml2py/cli.py index 5f5ca5dd6..84ef760a2 100644 --- a/src/pyconverter/xml2py/cli.py +++ b/src/pyconverter/xml2py/cli.py @@ -105,6 +105,10 @@ def create_package( download.download_template() command_map, name_map = wr.convert(xml_path) + arg_file = Path("args.txt") + if arg_file.exists(): + # Delete the file if it exists + arg_file.unlink() package_structure = wr.write_source( command_map, name_map, xml_path, target_path, custom_functions_path ) From 2e8c57b3439e648dd94cf9ccc93983c6970ee12f Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:05:53 +0100 Subject: [PATCH 04/11] fix: issues related to duplicated args --- .gitignore | 1 + src/pyconverter/xml2py/ast_tree.py | 218 +++++++++++++++++++---------- 2 files changed, 143 insertions(+), 76 deletions(-) diff --git a/.gitignore b/.gitignore index f37b84302..edc3b696a 100644 --- a/.gitignore +++ b/.gitignore @@ -165,3 +165,4 @@ cython_debug/ helper/ package/ _autosummary/ +args.txt diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index 02bdb7ca2..5b44abb68 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -83,6 +83,12 @@ NO_RESIZE_LIST = ["Variablelist"] +MISSING_ARGUMENT_DESCRIPTION = """The description of the argument is missing in the Python function. +Please, refer to the product documentation for further information.""" + +ADDITIONAL_ARGUMENT_DESCRIPTION = """Additional arguments can be passed to the intial command. +Please, refer to the product documentation for further information.""" + class NameMap: def __init__(self, name_map): @@ -138,6 +144,9 @@ def to_py_arg_name(name: str) -> str: initial_arg = str(name).lower().strip() arg = initial_arg if arg in ["--", "–", ""]: + return "" + elif "--" in arg: + arg = arg.replace("--", "") return arg elif arg.isdigit(): return "" @@ -207,7 +216,7 @@ def str_types(types, join_str: str) -> str: def to_py_signature(py_arg_name, types) -> str: """Return the Python signature of the argument.""" - if py_arg_name not in ["--", "–", ""]: + if py_arg_name != "": kwarg = f'{py_arg_name}: {str_types(types, " | ")} = ""' else: kwarg = None @@ -1624,7 +1633,7 @@ def args(self): # rename duplicate arguments if len(args) != len(set(args)): for arg in args: - if arg not in ["", "--", "–"]: + if arg != "": i = 0 if args.count(arg) > 1: for j in range(len(args)): @@ -2101,64 +2110,13 @@ class ProductName(Element): pass -class ArgumentList: - def __init__(self, py_name: str, list_entry: VarlistEntry, args: List) -> None: - - self._py_name = py_name - self._list_entry = list_entry - self._arguments = [] - self._initial_args = args - self._parse_list_entry() - - def _parse_list_entry(self): - for item in self._list_entry: - if isinstance(item, VarlistEntry): - argument_obj = Argument(item, self._initial_args) - additional_args = argument_obj.multiple_args - if len(additional_args) > 0: - for arg in additional_args: - arg_name = arg.py_arg_name - if (arg_name in self._initial_args) and (arg_name not in self.py_arg_names): - self._arguments.append(arg) - - else: - self._arguments.append(argument_obj) - - def __iadd__(self, argument_list): - for arg in argument_list.arguments: - arg_name = arg.py_arg_name - if (arg_name in self._initial_args) and (arg_name not in self.py_arg_names): - self._arguments.append(arg) - return self - - @property - def arguments(self): - return self._arguments - - @arguments.setter - def arguments(self, argument): - self._arguments.append(argument) - - @property - def py_name(self): - return self._py_name - - @property - def initial_args(self): - return self._initial_args - - @property - def py_arg_names(self): - return [arg.py_arg_name for arg in self._arguments] - - class Argument: """Argument object.""" def __init__( self, element: str | Element, - initial_argument: List, + initial_arguments: List, description: Element | str | None = None, ) -> None: if description is None: @@ -2177,7 +2135,7 @@ def __init__( name = element self._name = name self._description = description - self._initial_argument = initial_argument + self._initial_arguments = initial_arguments @property def py_arg_name(self) -> str: @@ -2204,27 +2162,26 @@ def multiple_args(self): if not self.is_arg_elipsis: for item_name in split_name: arg_name = item_name.strip() - new_arg = Argument(arg_name, self._initial_argument, self._description) - if new_arg.py_arg_name != "": - additional_args.append(new_arg) + new_arg = Argument(arg_name, self._initial_arguments, self._description) + additional_args.append(new_arg) else: complete_args = get_complete_args_from_initial_arg( - elipsis_args=split_name, initial_args=self._initial_argument + elipsis_args=split_name, initial_args=self._initial_arguments ) if len(complete_args) > 0: for item in complete_args: - new_arg = Argument(item, self._initial_argument, self._description) - if new_arg.py_arg_name != "": - additional_args.append(new_arg) + new_arg = Argument(item, self._initial_arguments, self._description) + additional_args.append(new_arg) else: for i, item_name in enumerate(split_name): item_name = item_name.strip() if item_name == "": - continue + new_arg = Argument(arg_name, self._initial_arguments, self._description) + additional_args.append(new_arg) elif is_elipsis(item_name): if "+" in split_name[i + 1]: @@ -2244,7 +2201,7 @@ def multiple_args(self): arg_name = split_name[i + 1].strip() arg_name = f"{arg_name[:initial_pos_final]}{j}{arg_name[end_pos_final:]}" # noqa : E501 new_arg = Argument( - arg_name, self._initial_argument, self._description + arg_name, self._initial_arguments, self._description ) if new_arg.py_arg_name != "": additional_args.append(new_arg) @@ -2276,15 +2233,14 @@ def multiple_args(self): for j in range(number_iter_prev + 1, number_iter_next): arg_name = f"{name_iter_prev}{j}" new_arg = Argument( - arg_name, self._initial_argument, self._description + arg_name, self._initial_arguments, self._description ) - if new_arg.py_arg_name != "": - additional_args.append(new_arg) + additional_args.append(new_arg) else: additional_args.append( Argument( name_iter_next, - self._initial_argument, + self._initial_arguments, self._description, ) ) @@ -2339,7 +2295,7 @@ def to_py_docstring( self, max_length=100, indent="", links=None, base_url=None, fcache=None ) -> List[str]: """Return a list of string to enable converting the element to an RST format.""" - if "," not in self.py_arg_name and self.py_arg_name != "": + if self.py_arg_name != "": docstring = [f'{indent}{self.py_arg_name} : {str_types(self.types, " or ")}'] if isinstance(self._description, str): rst_description = self._description @@ -2368,6 +2324,119 @@ def to_py_docstring( return docstring +class ArgumentList: + def __init__(self, py_name: str, list_entry: VarlistEntry, args: List) -> None: + + self._py_name = py_name + self._list_entry = list_entry + self._arguments = [] + self._additional_args = [] + self._initial_args = args + self._parse_list_entry() + + def _parse_list_entry(self): + "Parse the list entry to get the main arguments and the additional ones." + temp_args = {} + for item in self._list_entry: + if isinstance(item, VarlistEntry): + argument_obj = Argument(item, self._initial_args) + additional_args = argument_obj.multiple_args + if len(additional_args) > 0: + for arg in additional_args: + arg_name = arg.py_arg_name + if (arg_name in self._initial_args) and ( + arg_name == "" or arg_name not in self.py_arg_names + ): + temp_args[arg_name] = arg + + else: + temp_args[argument_obj.py_arg_name] = argument_obj + + for initial_arg in self._initial_args: + if initial_arg in temp_args.keys(): + self._arguments.append(temp_args[initial_arg]) + else: + self._arguments.append( + Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION) + ) # description is missing + + is_additional_arg = False + if len(temp_args) != len(self._initial_args): + for arg in temp_args: + if arg not in self.py_arg_names: + self._additional_args.append(temp_args[arg]) + is_additional_arg = True + + if is_additional_arg and "addional_command_arg" not in self.py_arg_names: + self._arguments.append( + Argument( + "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION + ) + ) + + def __iadd__(self, argument_list): + temp_args = {} + for arg in argument_list.arguments: + arg_name = arg.py_arg_name + if (arg_name in self._initial_args) and ( + arg_name == "" or arg_name not in self.py_arg_names + ): + temp_args[arg_name] = arg + + for initial_arg in self._initial_args: + if initial_arg in temp_args.keys(): + if initial_arg not in self.py_arg_names: + self._arguments.append(temp_args[initial_arg]) + else: + self._arguments[self.py_arg_names.index(initial_arg)] = temp_args[initial_arg] + else: + if initial_arg not in self.py_arg_names: + self._arguments.append( + Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION) + ) + + is_additional_arg = False + if len(temp_args) != len(self._initial_args): + for arg in temp_args: + if arg not in self.py_arg_names: + self._additional_args.append(temp_args[arg]) + is_additional_arg = True + + if is_additional_arg and "addional_command_arg" not in self.py_arg_names: + self._arguments.append( + Argument( + "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION + ) + ) + + return self + + @property + def arguments(self) -> List[Argument]: + "Return a list of Argument objects." + return self._arguments + + @arguments.setter + def arguments(self, argument): + self._arguments.append(argument) + + @property + def py_name(self): + return self._py_name + + @property + def initial_args(self): + return self._initial_args + + @property + def py_arg_names(self): + return [arg.py_arg_name for arg in self._arguments] + + @property + def additional_args(self): + return self._additional_args + + class XMLCommand(Element): """Provides the XML command from the documentation.""" @@ -2454,17 +2523,14 @@ def arg_desc(self) -> List[Argument]: else: last_line = "" with open(arg_file, "a") as f: - if last_line != f"{arguments.py_arg_names}\n": + if last_line != f"py_arg_name : {arguments.py_arg_names}\n": f.write("--------------------------------------------------\n") f.write(f"{self.py_name}: {self.group}\n") + f.write("initial_args : ") f.write(f"{arguments.initial_args}\n") + f.write("py_arg_name : ") f.write(f"{arguments.py_arg_names}\n") - # for arg in arguments.initial_args: - # if arg not in arguments.py_arg_names: - # new_arg = Argument(arg, arguments.initial_args, "") - # arguments.arguments.append(new_arg) - return arguments.arguments else: @@ -2906,7 +2972,7 @@ def py_source(self, custom_functions=None, indent=""): command = 'command = f"' + self.name for arg in self.arg_desc: name = arg.py_arg_name - if name in ["--", "–", ""]: + if name == "": command += "," else: command += ",{" From c55ef28f58c4687b8cfa083ceb2a294ea12b5ade Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Wed, 11 Dec 2024 15:48:43 +0100 Subject: [PATCH 05/11] fix: revert change in ``py_term`` --- src/pyconverter/xml2py/ast_tree.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index 5b44abb68..7a153892e 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -1002,9 +1002,9 @@ def py_term(self, links=None, base_url=None): return f"{arg}" if self.term.tag in item_needing_links_base_url: - arg = self.term.to_rst(links=links, base_url=base_url).strip() + arg = self.term.to_rst(links=links, base_url=base_url).replace("--", "").strip() else: - arg = self.term.to_rst().strip() + arg = self.term.to_rst().replace("--", "").strip() # sanity check if "blank" in arg.lower(): From 09d0ebe6e56a1439847608fab2b39ee4cee0bc97 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Wed, 11 Dec 2024 16:51:49 +0100 Subject: [PATCH 06/11] fix: removing extra comas at the end of the command --- src/pyconverter/xml2py/ast_tree.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index 7a153892e..fee95c948 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -2979,6 +2979,8 @@ def py_source(self, custom_functions=None, indent=""): command += arg.py_arg_name command += "}" command += '"\n' + while command != command.replace(',"', '"'): # remove extra commas at the end of the command + command = command.replace(',"', '"') # ",{" + "},{".join(self.arg_desc.py_arg_name) + '}"\n' else: command = 'command = f"' + self.name + '"\n' From 371003a09d7b0e81fe7e207c7d0e99438e4969d9 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Thu, 12 Dec 2024 10:42:36 +0100 Subject: [PATCH 07/11] fix: removing extra argument instead of extra coma --- src/pyconverter/xml2py/ast_tree.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index fee95c948..e0201d910 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -2435,6 +2435,9 @@ def py_arg_names(self): @property def additional_args(self): return self._additional_args + + def remove_last_arg(self): + self._arguments.pop() class XMLCommand(Element): @@ -2513,6 +2516,10 @@ def arg_desc(self) -> List[Argument]: arg_file = Path("args.txt") if arguments is not None: + # Remove last argument if it's empty + while arguments.py_arg_names[-1] == "": + arguments.remove_last_arg() + if len(arguments.py_arg_names) != len(arguments.initial_args): # This function needs a special treatment if arg_file.exists(): @@ -2979,9 +2986,6 @@ def py_source(self, custom_functions=None, indent=""): command += arg.py_arg_name command += "}" command += '"\n' - while command != command.replace(',"', '"'): # remove extra commas at the end of the command - command = command.replace(',"', '"') - # ",{" + "},{".join(self.arg_desc.py_arg_name) + '}"\n' else: command = 'command = f"' + self.name + '"\n' return_command = "return self.run(command, **kwargs)\n" From fbc0c7ad8fffd96799c09eff5208df3080cae18e Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:16:47 +0100 Subject: [PATCH 08/11] feat: adding link in missing/ additional argument description --- config.yaml | 2 +- src/pyconverter/xml2py/ast_tree.py | 25 +++++++++++++------------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/config.yaml b/config.yaml index f788f5df2..fb14ebaad 100644 --- a/config.yaml +++ b/config.yaml @@ -2,7 +2,7 @@ library_name_structured: # Future name of the library - pyconverter - generatedcommands -subfolder: +subfolders: - subfolder - subsubfolder diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index e0201d910..cd8a0f29a 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -84,10 +84,10 @@ NO_RESIZE_LIST = ["Variablelist"] MISSING_ARGUMENT_DESCRIPTION = """The description of the argument is missing in the Python function. -Please, refer to the product documentation for further information.""" +Please, refer to the `command documentation `_ for further information.""" -ADDITIONAL_ARGUMENT_DESCRIPTION = """Additional arguments can be passed to the intial command. -Please, refer to the product documentation for further information.""" +ADDITIONAL_ARGUMENT_DESCRIPTION = """Additional arguments can be passed to the initial command. +Please, refer to the `command documentation `_ for further information.""" class NameMap: @@ -2325,9 +2325,10 @@ def to_py_docstring( class ArgumentList: - def __init__(self, py_name: str, list_entry: VarlistEntry, args: List) -> None: + def __init__(self, py_name: str, url: str, list_entry: VarlistEntry, args: List) -> None: self._py_name = py_name + self._url = url self._list_entry = list_entry self._arguments = [] self._additional_args = [] @@ -2357,7 +2358,7 @@ def _parse_list_entry(self): self._arguments.append(temp_args[initial_arg]) else: self._arguments.append( - Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION) + Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}")) ) # description is missing is_additional_arg = False @@ -2370,7 +2371,7 @@ def _parse_list_entry(self): if is_additional_arg and "addional_command_arg" not in self.py_arg_names: self._arguments.append( Argument( - "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION + "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}") ) ) @@ -2392,7 +2393,7 @@ def __iadd__(self, argument_list): else: if initial_arg not in self.py_arg_names: self._arguments.append( - Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION) + Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}")) ) is_additional_arg = False @@ -2405,7 +2406,7 @@ def __iadd__(self, argument_list): if is_additional_arg and "addional_command_arg" not in self.py_arg_names: self._arguments.append( Argument( - "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION + "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}") ) ) @@ -2501,17 +2502,17 @@ def arg_desc(self) -> List[Argument]: for child in elem: if isinstance(child, Variablelist): if arguments is None: - arguments = ArgumentList(self.py_name, child, self.args) + arguments = ArgumentList(self.py_name, self.url, child, self.args) else: - arguments += ArgumentList(self.py_name, child, self.args) + arguments += ArgumentList(self.py_name, self.url, child, self.args) else: for elem in refsyn: if isinstance(elem, Variablelist): if arguments is None: - arguments = ArgumentList(self.py_name, elem, self.args) + arguments = ArgumentList(self.py_name, self.url, elem, self.args) else: - arguments += ArgumentList(self.py_name, elem, self.args) + arguments += ArgumentList(self.py_name, self.url, elem, self.args) arg_file = Path("args.txt") From abc9a1d5d78c7529e7be22c708f8c7888dfa73ee Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:20:31 +0100 Subject: [PATCH 09/11] fix: pre-commit --- src/pyconverter/xml2py/ast_tree.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index cd8a0f29a..80a1c38f6 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -2358,7 +2358,11 @@ def _parse_list_entry(self): self._arguments.append(temp_args[initial_arg]) else: self._arguments.append( - Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}")) + Argument( + initial_arg, + self._initial_args, + MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}"), + ) ) # description is missing is_additional_arg = False @@ -2371,7 +2375,9 @@ def _parse_list_entry(self): if is_additional_arg and "addional_command_arg" not in self.py_arg_names: self._arguments.append( Argument( - "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}") + "addional_command_arg", + self._initial_args, + ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}"), ) ) @@ -2393,7 +2399,11 @@ def __iadd__(self, argument_list): else: if initial_arg not in self.py_arg_names: self._arguments.append( - Argument(initial_arg, self._initial_args, MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}")) + Argument( + initial_arg, + self._initial_args, + MISSING_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}"), + ) ) is_additional_arg = False @@ -2406,7 +2416,9 @@ def __iadd__(self, argument_list): if is_additional_arg and "addional_command_arg" not in self.py_arg_names: self._arguments.append( Argument( - "addional_command_arg", self._initial_args, ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}") + "addional_command_arg", + self._initial_args, + ADDITIONAL_ARGUMENT_DESCRIPTION.replace("url", f"{self._url}"), ) ) @@ -2436,7 +2448,7 @@ def py_arg_names(self): @property def additional_args(self): return self._additional_args - + def remove_last_arg(self): self._arguments.pop() From 28787e89396b7a890d0fffd57502ea8132d40c00 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Thu, 12 Dec 2024 17:56:11 +0100 Subject: [PATCH 10/11] feat: add ``project_name`` configuration --- config.yaml | 2 ++ src/pyconverter/xml2py/writer.py | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/config.yaml b/config.yaml index fb14ebaad..02dab56b1 100644 --- a/config.yaml +++ b/config.yaml @@ -1,3 +1,5 @@ +project_name: PyConverter-GeneratedCommands # Name of the project + library_name_structured: # Future name of the library - pyconverter - generatedcommands diff --git a/src/pyconverter/xml2py/writer.py b/src/pyconverter/xml2py/writer.py index f95a00405..24123974d 100644 --- a/src/pyconverter/xml2py/writer.py +++ b/src/pyconverter/xml2py/writer.py @@ -220,6 +220,7 @@ def write_global__init__file(library_path: Path, config_path: Path) -> None: Path object of the directory containing the generated package. """ + project_name = get_config_data_value(config_path, "project_name") subfolder_values = get_config_data_value(config_path, "subfolders") if subfolder_values: @@ -244,7 +245,7 @@ def write_global__init__file(library_path: Path, config_path: Path) -> None: fid.write("except ModuleNotFoundError:\n") fid.write(" import importlib_metadata\n\n") fid.write("__version__ = importlib_metadata.version(__name__.replace('.', '-'))\n") - fid.write('"""PyConverter-GeneratedCommands version."""\n') + fid.write(f'"""{project_name} version."""\n') fid.close() From 5ece50c25e453634d7da08fec1f4bd439b073ab7 Mon Sep 17 00:00:00 2001 From: Camille <78221213+clatapie@users.noreply.github.com> Date: Fri, 13 Dec 2024 16:57:17 +0100 Subject: [PATCH 11/11] fix: missing ``mkdir`` command raised by @germa89 --- src/pyconverter/xml2py/ast_tree.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/pyconverter/xml2py/ast_tree.py b/src/pyconverter/xml2py/ast_tree.py index 80a1c38f6..ccb159d8a 100644 --- a/src/pyconverter/xml2py/ast_tree.py +++ b/src/pyconverter/xml2py/ast_tree.py @@ -2510,13 +2510,12 @@ def arg_desc(self) -> List[Argument]: if refsyn is None: refsections = self.find_all("RefSection") for elem in refsections: - if elem.id is not None and "argdescript" in elem.id: - for child in elem: - if isinstance(child, Variablelist): - if arguments is None: - arguments = ArgumentList(self.py_name, self.url, child, self.args) - else: - arguments += ArgumentList(self.py_name, self.url, child, self.args) + for child in elem: + if isinstance(child, Variablelist): + if arguments is None: + arguments = ArgumentList(self.py_name, self.url, child, self.args) + else: + arguments += ArgumentList(self.py_name, self.url, child, self.args) else: for elem in refsyn: