# -*- coding: utf-8 -*-
"""Created on Tue Nov 04 09:01:21 2014
@author: pierre_b
"""
from codecs import open as open_co
from os.path import join
from pyleecan.Generator import PYTHON_TYPE, TAB, TAB2, TAB3, TAB4, TAB5, TAB6
from pyleecan.Generator.read_fct import (
find_import_type,
get_value_str,
is_list_pyleecan_type,
)
[docs]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"
)
# 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\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")
if len(class_dict["methods"]) > 0:
class_file.write("\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()
[docs]def generate_init(gen_dict, class_dict):
"""Generate the code for the __init__ method for the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
init_str : str
String containing the __init__ method code
"""
class_name = class_dict["name"]
init_str = "" # This string is for the generated code
init_by_var = "" # For the initialisation with the argument
# Add the parent property only in the top mother classes
if class_dict["mother"] == "":
init_by_var += TAB2 + "self.parent = None\n"
for prop in class_dict["properties"]:
if prop["type"] in PYTHON_TYPE:
# Add => "self.my_var = my_var\n" to init_by_var
init_by_var += TAB2 + "self." + prop["name"] + " = " + prop["name"] + "\n"
elif prop["type"] == "ndarray":
# Default value is None which should call the corresponding init
init_by_var += (
TAB2 + "# " + prop["name"] + " can be None, a ndarray or a list\n"
)
init_by_var += (
TAB2 + 'set_array(self, "' + prop["name"] + '", ' + prop["name"] + ")\n"
)
elif is_list_pyleecan_type(prop["type"]):
# List of pyleecan type
init_by_var += (
TAB2
+ "# "
+ prop["name"]
+ " can be None or a list of "
+ prop["type"][1:-1]
+ " object\n"
)
init_by_var += TAB2 + "self." + prop["name"] + " = list()\n"
init_by_var += TAB2 + "if type(" + prop["name"] + ") is list:\n"
init_by_var += TAB3 + "for obj in " + prop["name"] + ":\n"
init_by_var += TAB4 + "if obj is None: # Default value\n"
init_by_var += (
TAB5
+ "self."
+ prop["name"]
+ ".append("
+ prop["type"][1:-1]
+ "())\n"
)
type_dict = gen_dict[prop["type"][1:-1]]
daug_list = type_dict["daughters"]
init_by_var += generate_set_class_by_dict_list(
prop["name"], prop["type"][1:-1], daug_list
)
init_by_var += TAB4 + "else:\n"
init_by_var += TAB5 + "self." + prop["name"] + ".append(obj)\n"
init_by_var += TAB2 + "elif " + prop["name"] + " is None:\n"
init_by_var += TAB3 + "self." + prop["name"] + " = list()\n"
init_by_var += TAB2 + "else:\n"
init_by_var += TAB3 + "self." + prop["name"] + " = " + prop["name"] + "\n"
else: # For pyleecan Type
init_by_var += (
TAB2
+ "# "
+ prop["name"]
+ " can be None, a "
+ prop["type"]
+ " object or a dict\n"
)
type_dict = gen_dict[prop["type"]]
daug_list = type_dict["daughters"]
init_by_var += generate_set_class_by_dict(
prop["name"], prop["type"], daug_list
)
init_by_var += TAB2 + "else:\n"
init_by_var += TAB3 + "self." + prop["name"] + " = " + prop["name"] + "\n"
# Load all the properties including mother ones
(all_properties, mother_prop_list) = get_mother_attr(
gen_dict, class_dict, "properties"
)
mother_arg_list = "" # For the call of super init
for prop in mother_prop_list:
if mother_arg_list != "": # Avoid the first coma
# Add => ", my_var = my_var" to mother_arg_list
mother_arg_list += ", " + prop["name"] + "=" + prop["name"]
else:
# Add => "my_var = my_var" to mother_arg_list
mother_arg_list += prop["name"] + "=" + prop["name"]
check_dict = "" # list of all the property expectable in the init_dict
init_by_dict = "" # To overwrite the parameter from init_dict
arg_list = "" # For the argument with default value
init_MType = "" # To initialize the pyleecan Type default (-1)
for prop in all_properties:
# To overwrite the parameter from init_dict
init_by_dict += TAB3 + 'if "' + prop["name"] + '" in list(init_dict.keys()):\n'
init_by_dict += TAB4 + prop["name"] + ' = init_dict["' + prop["name"] + '"]\n'
# For the argument with default value
if prop["type"] in PYTHON_TYPE:
# Add => ", my_var = 10" to arg_list
arg_list += (
", " + prop["name"] + "=" + get_value_str(prop["value"], prop["type"])
)
elif prop["type"] == "ndarray":
arg_list += ", " + prop["name"] + "=None"
elif prop["type"][0] == "[" and prop["type"][-1] == "]":
# List of pyleecan type
arg_list += ", " + prop["name"] + "=list()"
else: # pyleecan type
if prop["value"] == "":
arg_list += ", " + prop["name"] + "=-1"
else: # Default value (most likely None)
arg_list += (
", "
+ prop["name"]
+ "="
+ get_value_str(prop["value"], prop["type"])
)
# To initialize the pyleecan Type default (-1)
init_MType += TAB2 + "if " + prop["name"] + " == -1:\n"
init_MType += TAB3 + prop["name"] + " = " + prop["type"] + "()\n"
# For check_init_dict
if check_dict == "": # First variable
check_dict += "'" + prop["name"] + "'"
else:
check_dict += ", '" + prop["name"] + "'"
# Code generation in init_str
init_str += TAB + "def __init__(self" + arg_list + ", init_dict=None):\n"
init_str += TAB2 + '"""Constructor of the class. Can be use in two ways ' ":\n"
init_str += (
TAB2 + "- __init__ (arg1 = 1, arg3 = 5) every parameters "
"have name and default values\n"
)
init_str += (
TAB3 + "for Matrix, None will initialise the property with " "an empty Matrix\n"
)
init_str += TAB3 + "for pyleecan type, None will call the default " "constructor\n"
init_str += (
TAB2 + "- __init__ (init_dict = d) d must be a dictionnary "
"wiht every properties as keys\n\n"
)
init_str += TAB2 + "ndarray or list can be given for Vector and Matrix\n"
init_str += TAB2 + 'object or dict can be given for pyleecan Object"""\n\n'
init_str += init_MType
init_str += TAB2 + "if init_dict is not None: # Initialisation by dict\n"
init_str += TAB3 + "check_init_dict(init_dict, [" + check_dict + "])\n"
init_str += TAB3 + "# Overwrite default value with init_dict content\n"
init_str += init_by_dict
init_str += TAB2 + "# Initialisation by argument\n"
init_str += init_by_var
# Add the call to super __init__ if needed
if class_dict["mother"] != "":
init_str += TAB2 + "# Call " + class_dict["mother"] + " init\n"
init_str += (
TAB2 + "super(" + class_name + ", self).__init__(" + mother_arg_list + ")\n"
)
init_str += (
TAB2
+ "# The class is frozen (in "
+ class_dict["mother"]
+ " init), for now it's impossible "
"to\n" + TAB2 + "# add new "
"properties\n"
)
else:
init_str += (
"\n"
+ TAB2
+ "# The class is frozen, for now it's "
+ "impossible to add new properties\n"
)
init_str += TAB2 + "self._freeze()\n"
return init_str
[docs]def generate_set_class_by_dict_list(prop_name, prop_type, daug_list):
"""Generate the code to set a list of pyleecan class property with a dictionary
Parameters
----------
prop_name : str
Name of the property to set
prop_type : str
Type of the property to set
daug_list : list
List of the Daughter of the class
Returns
-------
class_dict_str : str
String containing the code to set a list of pyleecan class property with a dictionary
"""
class_dict_str = ""
class_dict_str += TAB4 + "elif isinstance(obj, dict):\n"
if len(daug_list) > 0:
# Add the posibility to call the daughter init
class_dict_str += (
TAB5 + "# Call the correct constructor according to " "the dict\n"
)
class_dict_str += TAB5 + "load_dict = {"
for daughter_name in daug_list:
class_dict_str += '"' + daughter_name + '": ' + daughter_name + ", "
class_dict_str += '"' + prop_type + '": ' + prop_type + "}\n"
class_dict_str += TAB5 + "obj_class = obj.get('__class__')\n"
class_dict_str += TAB5 + "if obj_class is None:\n"
class_dict_str += (
TAB6 + "self." + prop_name + ".append(" + prop_type + "(init_dict=obj))\n"
)
class_dict_str += TAB5 + "elif obj_class in list(load_dict.keys()):\n"
class_dict_str += (
TAB6 + "self." + prop_name + ".append(load_dict["
"obj_class]("
"init_dict=obj))\n"
)
class_dict_str += (
TAB5 + "else: # Avoid generation error or wrong " "modification in json\n"
)
class_dict_str += (
TAB6 + 'raise InitUnKnowClassError("Unknow class name '
"in init_dict for " + prop_name + '")\n'
)
else: # No daughter
class_dict_str += (
TAB5 + "self." + prop_name + ".append(" + prop_type + "(init_dict=obj))\n"
)
return class_dict_str
[docs]def generate_set_class_by_dict(prop_name, prop_type, daug_list):
"""Generate the code to set a pyleecan class property with a dictionary
Parameters
----------
prop_name : str
Name of the property to set
prop_type : str
Type of the property to set
daug_list : list
List of the Daughter of the class
Returns
-------
class_dict_str : str
String containing the code to set a pyleecan class property with a dictionary
"""
class_dict_str = ""
class_dict_str += TAB2 + "if isinstance(" + prop_name + ", dict):\n"
if len(daug_list) > 0:
# Add the posibility to call the daughter init
class_dict_str += (
TAB3 + "# Call the correct constructor according to " "the dict\n"
)
class_dict_str += TAB3 + "load_dict = {"
for daughter_name in daug_list:
class_dict_str += '"' + daughter_name + '": ' + daughter_name + ", "
class_dict_str += '"' + prop_type + '": ' + prop_type + "}\n"
class_dict_str += TAB3 + "obj_class = " + prop_name + ".get('__class__')\n"
class_dict_str += TAB3 + "if obj_class is None:\n"
class_dict_str += (
TAB4
+ "self."
+ prop_name
+ " = "
+ prop_type
+ "(init_dict="
+ prop_name
+ ")\n"
)
class_dict_str += TAB3 + "elif obj_class in list(load_dict.keys()):\n"
class_dict_str += (
TAB4 + "self." + prop_name + " = load_dict[obj_class]("
"init_dict=" + prop_name + ")\n"
)
class_dict_str += (
TAB3 + "else: # Avoid generation error or wrong " "modification in json\n"
)
class_dict_str += (
TAB4 + 'raise InitUnKnowClassError("Unknow class name '
"in init_dict for " + prop_name + '")\n'
)
else: # No daughter
class_dict_str += (
TAB3
+ "self."
+ prop_name
+ " = "
+ prop_type
+ "(init_dict="
+ prop_name
+ ")\n"
)
return class_dict_str
[docs]def generate_init_void():
"""Generate the code for the init method with no property
Returns
-------
init_str : str
String containing the code to initialize a class with no property
"""
init_str = ""
init_str += TAB + "def __init__(self, init_dict=None):\n"
init_str += TAB2 + '"""Constructor of the class. Can be use in two ways ' ":\n"
init_str += (
TAB2 + "- __init__ (arg1 = 1, arg3 = 5) every parameters "
"have name and default values\n"
)
init_str += (
TAB3 + "for Matrix, None will initialise the property with " "an empty Matrix\n"
)
init_str += TAB3 + "for pyleecan type, None will call the default " "constructor\n"
init_str += (
TAB2 + "- __init__ (init_dict = d) d must be a dictionnary "
"wiht every properties as keys\n\n"
)
init_str += TAB2 + "ndarray or list can be given for Vector and Matrix\n"
init_str += TAB2 + 'object or dict can be given for pyleecan Object"""\n\n'
init_str += TAB2 + "if init_dict is not None: # Initialisation by dict\n"
init_str += TAB3 + "check_init_dict(init_dict, [])\n"
init_str += (
TAB2 + "# The class is frozen, for now it's impossible to "
"add new properties\n"
)
init_str += TAB2 + "self.parent = None\n"
init_str += TAB2 + "self._freeze()\n"
return init_str
[docs]def generate_str(gen_dict, class_dict):
"""Generate the code for the __str__ method of the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
str_str : str
String containing the code for the __str__ method of the class
"""
class_name = class_dict["name"]
str_str = "" # This string is for the generated code
var_str = "" # For the creation of the return string (in __str__)
# Display parent only in the top mother class __str__ method
if class_dict["mother"] == "":
var_str += TAB2 + "if self.parent is None:\n"
var_str += TAB3 + class_name + '_str += "parent = None " + linesep\n'
var_str += TAB2 + "else:\n"
var_str += (
TAB3
+ class_name
+ '_str += "parent = " + '
+ 'str(type(self.parent)) + " object" + linesep\n'
)
for ii, prop in enumerate(class_dict["properties"]):
if prop["type"] == "str":
# Add => < MyClass_str += 'my_var = "'+self.MyVar+'"' >to var_str
var_str += (
TAB2
+ class_name
+ "_str += '"
+ prop["name"]
+ ' = "'
+ "' + str(self."
+ prop["name"]
+ ") + "
+ """'"'"""
)
elif prop["type"] in ["int", "float", "bool", "complex"]:
# Add => < MyClass_str += "my_var = "+str(self.my_var) >to var_str
var_str += (
TAB2
+ class_name
+ '_str += "'
+ prop["name"]
+ ' = " + str(self.'
+ prop["name"]
+ ")"
)
elif prop["type"] == "ndarray":
# For Matrix (skip a line then print the matrix)
# Add => < MyClass_str += "my_var = "+ linesep + str(
# self.my_var) >to var_str
var_str += (
TAB2
+ class_name
+ '_str += "'
+ prop["name"]
+ ' = " + linesep + str(self.'
+ prop["name"]
+ ")"
)
elif is_list_pyleecan_type(prop["type"]):
var_str += TAB2 + "if len(self." + prop["name"] + ") == 0:\n"
var_str += TAB3 + class_name + '_str += "' + prop["name"] + ' = []"\n'
var_str += TAB2 + "for ii in range(len(self." + prop["name"] + ")):\n"
var_str += (
TAB3
+ class_name
+ '_str += "'
+ prop["name"]
+ '["+str(ii)+"] = "+str(self.'
+ prop["name"]
+ '[ii].as_dict())+"\\n"'
)
else: # For pyleecan type print the dict (from as_dict)
# Add => < "MyClass = "+str(self.my_var.as_dict()) >to var_str
var_str += (
TAB2
+ class_name
+ '_str += "'
+ prop["name"]
+ ' = " + str(self.'
+ prop["name"]
+ ".as_dict())"
)
# Add linesep except for the last line
if ii == len(class_dict["properties"]) - 1:
var_str += "\n"
else:
if prop["type"] in PYTHON_TYPE:
var_str += " + linesep\n"
else: # Skip two lines for pyleecan type and ndarray
var_str += " + linesep + linesep\n"
# Code generation
str_str += TAB + "def __str__(self):\n"
str_str += (
TAB2 + '"""Convert this objet in a readeable string ' + '(for print)"""\n\n'
)
str_str += TAB2 + class_name + "_str = ''\n"
if class_dict["mother"] != "":
str_str += (
TAB2 + "# Get the properties inherited from " + class_dict["mother"] + "\n"
)
# Add => "Class_str += super(Class, self).__str__() + linesep
str_str += (
TAB2
+ class_name
+ "_str += super("
+ class_name
+ ", self).__str__() + linesep\n"
)
str_str += var_str
str_str += TAB2 + "return " + class_name + "_str\n"
return str_str
[docs]def generate_eq(gen_dict, class_dict):
"""Generate the code for the __eq__ method of the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
eq_str : str
String containing the code for the __eq__ method of the class
"""
class_name = class_dict["name"]
eq_str = "" # This string is for the generated code
# Code generation
eq_str += TAB + "def __eq__(self, other):\n"
eq_str += TAB2 + '"""Compare two objects (skip parent)"""\n\n'
# Check the type
eq_str += TAB2 + "if type(other) != type(self):\n"
eq_str += TAB3 + "return False\n"
# Call mother eq
if class_dict["mother"] != "":
eq_str += (
TAB2
+ "\n# Check the properties inherited from "
+ class_dict["mother"]
+ "\n"
)
eq_str += TAB2 + "if not super(" + class_name + ", self).__eq__(other):\n"
eq_str += TAB3 + "return False\n"
# Check that all the propoperties (except parent) are equal
for prop in class_dict["properties"]:
eq_str += TAB2 + "if other." + prop["name"] + " != self." + prop["name"] + ":\n"
eq_str += TAB3 + "return False\n"
eq_str += TAB2 + "return True\n"
return eq_str
[docs]def generate_as_dict(gen_dict, class_dict):
"""Generate the code for the as_dict method of the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
dict_str : str
String containing the code for the as_dict method of the class
"""
class_name = class_dict["name"]
dict_str = "" # This string is for the generated code
var_str = "" # For the creation of the return dict (in as_dict)
for prop in class_dict["properties"]:
if prop["type"] in PYTHON_TYPE:
# Add => "class_name ["var_name"] = self.var_name" to var_str
var_str += (
TAB2
+ class_name
+ '_dict["'
+ prop["name"]
+ '"] = self.'
+ prop["name"]
+ "\n"
)
elif prop["type"] == "ndarray":
# Add => "class_name ["var_name"] = self.var_name.tolist()" to
# var_str
var_str += TAB2 + "if self." + prop["name"] + " is None:\n"
var_str += TAB3 + class_name + '_dict["' + prop["name"] + '"] = None\n'
var_str += TAB2 + "else:\n"
var_str += (
TAB3
+ class_name
+ '_dict["'
+ prop["name"]
+ '"] = self.'
+ prop["name"]
+ ".tolist()\n"
)
elif is_list_pyleecan_type(prop["type"]):
var_str += TAB2 + class_name + '_dict["' + prop["name"] + '"] = list()\n'
var_str += TAB2 + "for obj in self." + prop["name"] + ":\n"
var_str += (
TAB3
+ class_name
+ '_dict["'
+ prop["name"]
+ '"].append(obj.as_dict())\n'
)
else:
# Add => "class_name ["var_name"] = self.var_name.as_dict()" to
# var_str
var_str += TAB2 + "if self." + prop["name"] + " is None:\n"
var_str += TAB3 + class_name + '_dict["' + prop["name"] + '"] = None\n'
var_str += TAB2 + "else:\n"
var_str += (
TAB3
+ class_name
+ '_dict["'
+ prop["name"]
+ '"] = self.'
+ prop["name"]
+ ".as_dict()\n"
)
# Code generation
dict_str += TAB + "def as_dict(self):\n"
dict_str += (
TAB2 + '"""Convert this objet in a json seriable dict (can '
"be use in __init__)\n" + TAB2 + '"""\n\n'
)
if class_dict["mother"] != "":
# Get the properties of the mother class (if needed)
dict_str += (
TAB2 + "# Get the properties inherited from " + class_dict["mother"] + "\n"
)
dict_str += (
TAB2 + class_name + "_dict = super(" + class_name + ", self).as_dict()\n"
)
else:
dict_str += TAB2 + class_name + "_dict = dict()\n"
dict_str += var_str
dict_str += (
TAB2 + "# The class name is added to the dict for" + "deserialisation purpose\n"
)
if class_dict["mother"] != "":
dict_str += TAB2 + "# Overwrite the mother class name\n"
dict_str += TAB2 + class_name + "_dict['__class__'] = '" + class_name + "'\n"
dict_str += TAB2 + "return " + class_name + "_dict\n"
return dict_str
[docs]def generate_set_None(gen_dict, class_dict):
"""Generate the code for the _set_None method of the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
None_str : str
String containing the code for the _set_None method of the class
"""
class_name = class_dict["name"]
None_str = "" # This string is for the generated code
# Code line to set every properties to None (except pyleecan object)
var_str = ""
for prop in class_dict["properties"]:
if prop["type"] in PYTHON_TYPE or prop["type"] == "ndarray":
var_str += TAB2 + "self." + prop["name"] + " = None\n"
elif is_list_pyleecan_type(prop["type"]):
var_str += TAB2 + "for obj in self." + prop["name"] + ":\n"
var_str += TAB3 + "obj._set_None()\n"
else: # Pyleecan type
var_str += TAB2 + "if self." + prop["name"] + " is not None:\n"
var_str += TAB3 + "self." + prop["name"] + "._set_None()\n"
# Code generation
None_str += TAB + "def _set_None(self):\n"
None_str += (
TAB2 + '"""Set all the properties to None (except ' + 'pyleecan object)"""\n\n'
)
None_str += var_str
if class_dict["mother"] != "":
# Get the properties of the mother class (if needed)
None_str += (
TAB2
+ "# Set to None the properties inherited from "
+ class_dict["mother"]
+ "\n"
)
None_str += TAB2 + "super(" + class_name + ", self)._set_None()\n"
return None_str
[docs]def generate_properties(gen_dict, class_dict):
"""Generate the code for the getter and setter of the properties of the class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
Returns
-------
prop_str : str
String containing the code for the getter and setter of the properties of the class
"""
prop_str = "" # This string is for the generated code
for prop in class_dict["properties"]:
# Getter
prop_str += TAB + "def _get_" + prop["name"] + "(self):\n"
prop_str += TAB2 + '"""getter of ' + prop["name"] + '"""\n'
if is_list_pyleecan_type(prop["type"]):
# TODO: Update the parent should be done only in the setter but
# their is an issue with .append for list of pyleecan type
prop_str += TAB2 + "for obj in self._" + prop["name"] + ":\n"
prop_str += TAB3 + "if obj is not None:\n"
prop_str += TAB4 + "obj.parent = self\n"
prop_str += TAB2 + "return self._" + prop["name"] + "\n\n"
# Setter
prop_str += TAB + "def _set_" + prop["name"] + "(self, value):\n"
prop_str += TAB2 + '"""setter of ' + prop["name"] + '"""\n'
# Convert ndarray if needed
if prop["type"] == "ndarray":
prop_str += TAB2 + "if type(value) is list:\n"
prop_str += TAB3 + "try:\n"
prop_str += TAB4 + "value = array(value)\n"
prop_str += TAB3 + "except:\n"
prop_str += TAB4 + "pass\n"
# Add check_var("var_name",value, "var_type", min=var_min, max=var_max)
prop_str += (
TAB2 + 'check_var("' + prop["name"] + '", value, "' + prop["type"] + '"'
)
# Min and max are added only if needed
if prop["type"] in ["float", "int", "ndarray"]:
if str(prop["min"]) is not "":
prop_str += ", Vmin=" + str(prop["min"])
if str(prop["max"]) is not "":
prop_str += ", Vmax=" + str(prop["max"])
prop_str += ")\n"
prop_str += TAB2 + "self._" + prop["name"] + " = value\n\n"
if is_list_pyleecan_type(prop["type"]):
# List of pyleecan type
prop_str += TAB2 + "for obj in self._" + prop["name"] + ":\n"
prop_str += TAB3 + "if obj is not None:\n"
prop_str += TAB4 + "obj.parent = self\n"
elif prop["type"] not in PYTHON_TYPE and prop["type"] != "ndarray":
# pyleecan type
prop_str += TAB2 + "if self._" + prop["name"] + " is not None:\n"
prop_str += TAB3 + "self._" + prop["name"] + ".parent = self\n"
# Property declaration
# For doxygen : TODO: still needed for sphinx ?
prop_str += TAB + "# " + prop["desc"] + "\n"
prop_str += TAB + "# Type : " + prop["type"]
if str(prop["min"]) is not "":
prop_str += ", min = " + str(prop["min"])
if str(prop["max"]) is not "":
prop_str += ", max = " + str(prop["max"])
prop_str += "\n"
# Add "var_name = property(fget=_get_var_name, fset=_set_var_name,
# doc = "this is doc")"
prop_str += TAB + prop["name"] + " = property(fget=_get_" + prop["name"]
prop_str += ", fset=_set_" + prop["name"]
# "Clean" the doc string from excel
prop_str += ",\n" + TAB4
for ii in range(len(prop["name"])): # Align doc with fget
prop_str += " "
prop_str += 'doc=u"""' + prop["desc"] + '""")\n\n'
return prop_str[:-2] # Remove last \n\n
[docs]def get_mother_attr(gen_dict, class_dict, key):
"""Get the list of the key value from the class, including mother ones.
Used to get all the properties or method of a class
Parameters
----------
gen_dict : dict
Dict with key = class name and value = class dict (name, package, properties, methods...)
class_dict : dict
Dictionnary of the class to generate (keys are name, package, properties, methods...)
key : str
Key to extract from the mother class(es) ("properties" or "methods")
Returns
-------
(all_list, mother_list) : tuple
all_list: List of all the "key" of the class including mother class(es) ones
mother_list: List of the "key" from the mother class(es) only
"""
# Load all the mother properties
all_list = list(class_dict[key])
mother_list = list()
while class_dict["mother"] != "":
class_dict = gen_dict[class_dict["mother"]]
mother_list.extend(class_dict[key])
all_list.extend(mother_list)
return (all_list, mother_list)