def generate_class(gen_dict, class_name, path_to_gen): """generate the corresponding class file (erase the previous code) Parameters ---------- gen_dict : dict Dict with key = class name and value = class dict (name, package, properties, methods...) class_name : str name of the class to generate path_to_gen : str path to the file to save the class code Returns ------- None """ class_dict = gen_dict[class_name] class_pack = class_dict["package"] # Start of file generation # Create or Erase the file by opening it class_file = open_co(join(path_to_gen, class_name + ".py"), "w", "utf-8") # List of non python type to import import_type_list = list(find_import_type(gen_dict, class_dict, [])) # Encoding class_file.write("# -*- coding: utf-8 -*-\n") # Warning class_file.write('"""Warning : this file has been generated, ' 'you shouldn\'t edit it"""\n\n') # Import class_file.write("from os import linesep\n") if "ndarray" in import_type_list: class_file.write("from pyleecan.Classes.check import set_array, " + "check_init_dict, check_var\n") else: class_file.write( "from pyleecan.Classes.check import check_init_dict, " + "check_var\n") # Save function class_file.write("from pyleecan.Functions.save import save\n") # Import of the mother_class (FrozenClass by default) # All the classes file are in the Classes folder (regardless of their main package) if class_dict["mother"] != "": class_file.write("from pyleecan.Classes." + class_dict["mother"] + " import " + class_dict["mother"] + "\n\n") else: class_file.write("from pyleecan.Classes.frozen import FrozenClass\n\n") # Import all the methods of the class # The methods are in Methods.<Main package>.<class name>, one file per method for meth in class_dict["methods"]: class_file.write("from pyleecan.Methods." + class_pack + "." + class_name + "." + meth + " import " + meth.split(".")[-1] + "\n") if len(class_dict["methods"]) > 0: class_file.write("\n") # For Matrix and Vector (numpy) property if "ndarray" in import_type_list: class_file.write("from numpy import array, array_equal\n") import_type_list.remove("ndarray") # Import of all needed pyleecan type for property polymorphism class_file.write( "from pyleecan.Classes.check import InitUnKnowClassError\n") for pyleecan_type in import_type_list: type_dict = gen_dict[pyleecan_type] class_file.write("from pyleecan.Classes." + pyleecan_type + " import " + pyleecan_type + "\n") for daughter_name in type_dict["daughters"]: # Import of the inherited class (for init) class_file.write("from pyleecan.Classes." + daughter_name + " import " + daughter_name + "\n") if len(import_type_list) > 0: class_file.write("\n") # Class declaration if class_dict["mother"] != "": class_file.write("\n\nclass " + class_name + "(" + class_dict["mother"] + "):\n") else: class_file.write("\n\nclass " + class_name + "(FrozenClass):\n") # Class Docstring if class_dict["desc"] != "": class_file.write(TAB + '"""' + class_dict["desc"] + '"""\n') class_file.write("\n") # Declare all class Constante (VERSION should be a constante for every classes) for cst in class_dict["constants"]: class_file.write(TAB + cst["name"] + " = " + str(cst["value"]) + "\n") class_file.write("\n") # Asign all the Methods of the class for meth in class_dict["methods"]: class_file.write(TAB + "# cf Methods." + class_pack + "." + class_name + "." + meth + "\n") class_file.write(TAB + meth.split(".")[-1] + " = " + meth.split(".")[-1] + "\n") class_file.write(TAB + "# save method is available in all object\n") class_file.write(TAB + "save = save\n\n") # Add the __init__ method if len(class_dict["properties"]) == 0 and class_dict["mother"] == "": class_file.write(generate_init_void() + "\n") else: class_file.write(generate_init(gen_dict, class_dict) + "\n") # Add the __str__ method class_file.write(generate_str(gen_dict, class_dict) + "\n") # Add the __eq__ method class_file.write(generate_eq(gen_dict, class_dict) + "\n") # Add the as_dict method class_file.write(generate_as_dict(gen_dict, class_dict) + "\n") # Add the _set_None method class_file.write(generate_set_None(gen_dict, class_dict) + "\n") # Add all the properties getter and setter class_file.write(generate_properties(gen_dict, class_dict) + "\n") # End of class generation class_file.close()
def gen_gui_class_file(path, class_name, gen_dict, gen_list): """Generate the Main class file according to the gen_list (should be run only once) Parameters ---------- path : str Path to the class folder class_name : str Name of the class to generate gen_dict : dict Dict with key = class name and value = class_dict gen_list : list List of widget to edit Returns ------- """ gen_str = "# -*- coding: utf-8 -*-\n\n" # Generate the import path # from "C:\\Users...\\GUI\\Dialog..." to ["C:", "Users",..., "GUI", # "Dialog",...] split_path = path.split("\\") # Split the path arount the \\ # The import path start at "GUI", we remove everything before GUI in # split_path list # from ["C:", "Users",..., "GUI", "Dialog",...] to ["GUI", "Dialog"...] split_path.reverse() split_path = split_path[:split_path.index("pyleecan") + 1] split_path.reverse() # from ["GUI", "Dialog", ...] to GUI.Dialog... import_path = ".".join(split_path) gen_str += "from PyQt5.QtGui import QDialog\n" gen_str += "from PyQt5.QtCore import SIGNAL, Qt\n\n" gen_str += ("from " + import_path + ".Gen_" + class_name + " import Gen_" + class_name + "\n\n") gen_str += "class " + class_name + " (Gen_" + class_name + ", QDialog):\n" gen_str += TAB + "def __init__ (self,in_obj):\n" gen_str += TAB2 + "#Build the interface according to the .ui file\n" gen_str += TAB2 + "QDialog.__init__(self)\n" gen_str += TAB2 + "self.setupUi(self)\n\n" gen_str += TAB2 + "#Copy to set the modification only if validated\n" gen_str += TAB2 + "#self.fault = Fault(init_dict=fault.as_dict())\n\n" init_str = "" # For loading the value from input connect_str = "" # Connect slot and signal slot_str = "" # Slot for edit in gen_list: data = find_prop(gen_dict[edit["xls"]][edit["cls"]]["properties"], edit["name"]) if data["type"] == "int" and "type" in edit["name"]: init_str += (TAB2 + "self.c_" + edit["name"] + ".setCurrentIndex(in_obj." + edit["name"] + ")\n") connect_str += (TAB2 + "self.connect(self.c_" + edit["name"] + ', SIGNAL("currentIndexChanged(int)"),self.set_' + edit["name"] + ")\n") slot_str += TAB + "def set_" + edit["name"] + " (self,index):\n" slot_str += (TAB2 + '"""Signal to update the value of ' + edit["name"] + " according to the combobox\n") slot_str += TAB2 + "@param[in] self A " + class_name + " object\n" slot_str += (TAB2 + "@param[in] index Current index of the combobox\n" + TAB2 + '"""\n') slot_str += TAB2 + "self.obj." + edit["name"] + " = index\n\n" elif data["type"] == "int": init_str += (TAB2 + "self.si_" + edit["name"] + ".setValue(in_obj." + edit["name"] + ")\n") connect_str += (TAB2 + "self.connect(self.si_" + edit["name"] + ', SIGNAL("editingFinished()"),self.set_' + edit["name"] + ")\n") slot_str += TAB + "def set_" + edit["name"] + " (self):\n" slot_str += (TAB2 + '"""Signal to update the value of ' + edit["name"] + " according to the line edit\n") slot_str += (TAB2 + "@param[in] self A " + class_name + " object\n" + TAB2 + '"""\n') slot_str += (TAB2 + "self.obj." + edit["name"] + " = self.si_" + edit["name"] + ".value()\n\n") elif data["type"] == "float": init_str += (TAB2 + "self.lf_" + edit["name"] + ".setValue(in_obj." + edit["name"] + ")\n") connect_str += (TAB2 + "self.connect(self.lf_" + edit["name"] + ', SIGNAL("editingFinished()"),self.set_' + edit["name"] + ")\n") slot_str += TAB + "def set_" + edit["name"] + " (self):\n" slot_str += (TAB2 + '"""Signal to update the value of ' + edit["name"] + " according to the line edit\n") slot_str += (TAB2 + "@param[in] self A " + class_name + " object\n" + TAB2 + '"""\n') slot_str += (TAB2 + "self.obj." + edit["name"] + " = self.lf_" + edit["name"] + ".value()\n\n") elif data["type"] == "bool": init_str += TAB2 + "if in_obj." + edit["name"] + " :\n" init_str += TAB3 + "self." + edit[ "name"] + ".setCheckState(Qt.Checked)\n" init_str += TAB2 + "else :\n" init_str += TAB3 + "self." + edit[ "name"] + ".setCheckState(Qt.Unchecked)\n" connect_str += (TAB2 + "self.connect(self." + edit["name"] + ', SIGNAL("toggled(bool)"),self.set_' + edit["name"] + ")\n") slot_str += TAB + "def set_" + edit[ "name"] + " (self, is_checked):\n" slot_str += (TAB2 + '"""Signal to update the value of ' + edit["name"] + " according to the checkbox\n") slot_str += TAB2 + "@param[in] self A " + class_name + " object\n" slot_str += (TAB2 + "@param[in] is_checked State of the checkbox\n" + TAB2 + '"""\n') slot_str += TAB2 + "self.obj." + edit["name"] + " = is_checked\n\n" elif data["type"] == "str": init_str += (TAB2 + "self.le_" + edit["name"] + ".setText(in_obj." + edit["name"] + ")\n") connect_str += (TAB2 + "self.connect(self.le_" + edit["name"] + ', SIGNAL("editingFinished()"),self.set_' + edit["name"] + ")\n") slot_str += TAB + "def set_" + edit["name"] + " (self):\n" slot_str += (TAB2 + '"""Signal to update the value of ' + edit["name"] + " according to the line edit\n") slot_str += (TAB2 + "@param[in] self A " + class_name + " object\n" + TAB2 + '"""\n') slot_str += (TAB2 + "self.obj." + edit["name"] + " = str(self.le_" + edit["name"] + ".text())\n\n") # Concatenate all (and remove last \n) gen_str += init_str + "\n" + connect_str + "\n" + slot_str[:-1] # Write the file with the generated code lines gen_file = open_co(join(path, class_name + ".py"), "w", "utf-8") gen_file.write(gen_str) gen_file.close()
def gen_gui_edit_file(path, class_name, gen_dict, gen_list): """Generate the "Gen_" class for editing the gui according to gen_list Parameters ---------- path : str Path to the class folder class_name : str Name of the class to generate gen_dict : dict Dict with key = class name and value = class_dict gen_list : list List of widget to edit Returns ------- """ # gen_str contains the code that will be written in the generated file gen_str = "# -*- coding: utf-8 -*-\n" gen_str += '"""File generated according to ' + class_name + "/gen_list.json\n" gen_str += 'WARNING! All changes made in this file will be lost!\n"""\n\n' # Generate the import path # from "C:\\Users...\\GUI\\Dialog..." to ["C:", "Users",..., "GUI", # "Dialog",...] split_path = path.split("\\") # Split the path arount the \\ # The import path start at "GUI", we remove everything before GUI in # split_path list # from ["C:", "Users",..., "GUI", "Dialog",...] to ["GUI", "Dialog"...] split_path.reverse() split_path = split_path[:split_path.index("pyleecan") + 1] split_path.reverse() # from ["GUI", "Dialog", ...] to GUI.Dialog... import_path = ".".join(split_path) gen_str += ("from " + import_path + ".Ui_" + class_name + " import Ui_" + class_name + "\n\n\n") gen_str += "class Gen_" + class_name + "(Ui_" + class_name + "):\n" # We use polymorphism to add some code lines to setupUi gen_str += TAB + "def setupUi(self, " + class_name + "):\n" gen_str += ( TAB2 + '"""Abstract class to update the widget according to the csv doc\n') gen_str += TAB2 + '"""\n' gen_str += TAB2 + "Ui_" + class_name + ".setupUi(self, " + class_name + ")\n" # We generate the corresponding lines for every needed widget for edit in gen_list: # data contains description, min, max of the variable according to Doc # excel files data = find_prop(gen_dict[edit["cls"]]["properties"], edit["name"]) # widget can contain either a list or a string if isinstance(edit["widget"], list): # generate the code lines for every widget in the list (label and # corresponding input most of the time) for widget in edit["widget"]: gen_str += gen_edit_widget_code(widget, data) else: # generate the code lines for the widget gen_str += gen_edit_widget_code(edit["widget"], data) # Write the file with the generated code lines gen_file = open_co(join(path, "Gen_" + class_name + ".py"), "w", "utf-8") gen_file.write(gen_str[:-1]) gen_file.close()
def generate_class(gen_dict, class_name, path_to_gen): """generate the corresponding class file (erase the previous code) Parameters ---------- gen_dict : dict Dict with key = class name and value = class dict (name, package, properties, methods...) class_name : str name of the class to generate path_to_gen : str path to the file to save the class code Returns ------- None """ class_dict = gen_dict[class_name] class_pack = class_dict["package"] # Start of file generation # Create or Erase the file by opening it class_file = open_co(join(path_to_gen, class_name + ".py"), "w", "utf-8") # List of non python type to import import_type_list = list(find_import_type(gen_dict, class_dict, [])) if class_name in import_type_list: # For recursive class import_type_list.remove(class_name) # Encoding class_file.write("# -*- coding: utf-8 -*-\n") # Warning class_file.write('"""File generated according to ' + class_dict["path"] + "\n") if class_dict["is_internal"]: class_file.write( "WARNING! Internal version of the class: DO NOT SHARE ON GITHUB !\n" ) class_file.write( 'WARNING! All changes made in this file will be lost!\n"""\n\n') # Import class_file.write("from os import linesep\n") if "ndarray" in import_type_list: class_file.write("from pyleecan.Classes.check import set_array, " + "check_init_dict, check_var, raise_\n") else: class_file.write( "from pyleecan.Classes.check import check_init_dict, check_var, raise_\n" ) # Save function class_file.write("from pyleecan.Functions.save import save\n") # Import of the mother_class (FrozenClass by default) # All the classes file are in the Classes folder (regardless of their main package) if class_dict["mother"] != "": class_file.write("from pyleecan.Classes." + class_dict["mother"] + " import " + class_dict["mother"] + "\n\n") else: class_file.write("from pyleecan.Classes.frozen import FrozenClass\n\n") # Import all the methods of the class # The methods are in Methods.<Main package>.<class name>, one file per method if len(class_dict["methods"]) > 0: class_file.write("# Import all class method\n") class_file.write( "# Try/catch to remove unnecessary dependencies in unused method\n" ) for meth in class_dict["methods"]: class_file.write(import_method(class_pack, class_name, meth)) if len(class_dict["methods"]) > 0: class_file.write("\n") # For Matrix and Vector (numpy) property if "ndarray" in import_type_list: class_file.write("from numpy import array, array_equal\n") import_type_list.remove("ndarray") # Import of all needed pyleecan type for empty init class_file.write( "from pyleecan.Classes.check import InitUnKnowClassError\n") for pyleecan_type in import_type_list: class_file.write("from pyleecan.Classes." + pyleecan_type + " import " + pyleecan_type + "\n") # Class declaration if class_dict["mother"] != "": class_file.write("\n\nclass " + class_name + "(" + class_dict["mother"] + "):\n") else: class_file.write("\n\nclass " + class_name + "(FrozenClass):\n") # Class Docstring if class_dict["desc"] != "": class_file.write(TAB + '"""' + class_dict["desc"] + '"""\n') class_file.write("\n") # Declare all class Constante (VERSION should be a constante for every classes) for cst in class_dict["constants"]: class_file.write(TAB + cst["name"] + " = " + str(cst["value"]) + "\n") class_file.write("\n") # Asign all the Methods of the class if len(class_dict["methods"]) > 1: class_file.write( TAB + "# Check ImportError to remove unnecessary dependencies in unused method\n" ) for meth in class_dict["methods"]: meth_name = meth.split(".")[-1] class_file.write(TAB + "# cf Methods." + class_pack + "." + class_name + "." + meth + "\n") class_file.write(TAB + "if isinstance(" + meth_name + ", ImportError):\n") class_file.write(TAB2 + meth_name + " = property(\n") class_file.write(TAB3 + "fget=lambda x: raise_(\n") # PEP8 formating if len(class_name) + 2 * len(meth_name) > 39: # 2 lines Import text class_file.write(TAB4 + "ImportError(\n") class_file.write(TAB5 + """"Can't use """ + class_name + " method " + meth_name + ': "\n') class_file.write(TAB5 + "+ str(" + meth_name + ")\n") class_file.write(TAB4 + ")\n") elif len(class_name) + 2 * len(meth_name) > 29: # Import text on line different line class_file.write(TAB4 + "ImportError(\n") class_file.write(TAB5 + """"Can't use """ + class_name + " method " + meth_name + ': "') class_file.write(" + str(" + meth_name + ")\n") class_file.write(TAB4 + ")\n") else: # On one line class_file.write(TAB4 + """ImportError("Can't use """ + class_name + " method " + meth_name + ': " + str(' + meth_name + "))\n") class_file.write(TAB3 + ")\n") class_file.write(TAB2 + ")\n") class_file.write(TAB + "else:\n") class_file.write(TAB2 + meth_name + " = " + meth_name + "\n") class_file.write(TAB + "# save method is available in all object\n") class_file.write(TAB + "save = save\n\n") # Add the __init__ method if len(class_dict["properties"]) == 0 and class_dict["mother"] == "": class_file.write(generate_init_void() + "\n") else: class_file.write(generate_init(gen_dict, class_dict) + "\n") # Add the __str__ method class_file.write(generate_str(gen_dict, class_dict) + "\n") # Add the __eq__ method class_file.write(generate_eq(gen_dict, class_dict) + "\n") # Add the as_dict method class_file.write(generate_as_dict(gen_dict, class_dict) + "\n") # Add the _set_None method class_file.write(generate_set_None(gen_dict, class_dict)) # Add all the properties getter and setter if len(class_dict["properties"]) > 0: class_file.write("\n" + generate_properties(gen_dict, class_dict) + "\n") # End of class generation class_file.close()