Nessuna descrizione
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lefactory.py 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #-*- coding: utf-8 -*-
  2. import importlib
  3. import EditorialModel
  4. from EditorialModel.model import Model
  5. from EditorialModel.fieldtypes.generic import GenericFieldType
  6. ## @brief This class is designed to generated the leobject API given an EditorialModel.model
  7. # @note Contains only static methods
  8. #
  9. # The name is not good but i've no other ideas for the moment
  10. class LeFactory(object):
  11. output_file = 'dyn.py'
  12. modname = None
  13. def __init__(LeFactory):raise NotImplementedError("Not designed (yet?) to be implemented")
  14. ## @brief Return a LeObject child class given its name
  15. # @return a python class or False
  16. @staticmethod
  17. def leobj_from_name(name):
  18. if LeFactory.modname is None:
  19. modname = 'leobject.'+LeFactory.output_file.split('.')[1]
  20. else:
  21. modname = LeFactory.modname
  22. mod = importlib.import_module(modname)
  23. try:
  24. res = getattr(mod, name)
  25. except AttributeError:
  26. return False
  27. return res
  28. ## @brief Convert an EmType or EmClass name in a python class name
  29. # @param name str : The name
  30. # @return name.title()
  31. @staticmethod
  32. def name2classname(name):
  33. if not isinstance(name, str):
  34. raise AttributeError("Argument name should be a str and not a %s"%type(name))
  35. return name.title()
  36. ## @brief Return a call to a FieldType constructor given an EmField
  37. # @param emfield EmField : An EmField
  38. # @return a string representing the python code to instanciate a EmFieldType
  39. @staticmethod
  40. def fieldtype_construct_from_field(emfield):
  41. return '%s.EmFieldType(**%s)'%(
  42. GenericFieldType.module_name(emfield.fieldtype),
  43. repr(emfield._fieldtype_args),
  44. )
  45. ## @brief Given a Model and an EmClass instances generate python code for corresponding LeClass
  46. # @param model Model : A Model instance
  47. # @param emclass EmClass : An EmClass instance from model
  48. # @return A string representing the python code for the corresponding LeClass child class
  49. @staticmethod
  50. def emclass_pycode(model, emclass):
  51. cls_fields = dict()
  52. cls_linked_types = list()
  53. for field in emclass.fields():
  54. cls_fields[field.name] = LeFactory.fieldtype_construct_from_field(field)
  55. fti = field.fieldtype_instance()
  56. if fti.name == 'rel2type':
  57. #relationnal field/fieldtype
  58. cls_linked_types.append(LeFactory.name2classname(model.component(fti.rel_to_type_id).name))
  59. cls_fieldgroup = dict()
  60. for fieldgroup in emclass.fieldgroups():
  61. cls_fieldgroup[fieldgroup.name] = list()
  62. for field in fieldgroup.fields():
  63. cls_fieldgroup[fieldgroup.name].append(field.name)
  64. return """
  65. #Initialisation of {name} class attributes
  66. {name}._fieldtypes = {ftypes}
  67. {name}._linked_types = {ltypes}
  68. {name}._fieldgroups = {fgroups}
  69. """.format(
  70. name = LeFactory.name2classname(emclass.name),
  71. ftypes = "{"+(','.join([ '\n\t%s:%s'%(repr(f),v) for f,v in cls_fields.items()]))+"\n}",
  72. ltypes = "{"+(','.join(cls_linked_types))+'}',
  73. fgroups = repr(cls_fieldgroup)
  74. )
  75. ## @brief Given a Model and an EmType instances generate python code for corresponding LeType
  76. # @param model Model : A Model instance
  77. # @param emtype EmType : An EmType instance from model
  78. # @return A string representing the python code for the corresponding LeType child class
  79. @staticmethod
  80. def emtype_pycode(model, emtype):
  81. type_fields = list()
  82. type_superiors = list()
  83. for field in emtype.fields():
  84. type_fields.append(field.name)
  85. for nat, sup_l in emtype.superiors().items():
  86. type_superiors.append('%s:[%s]'%(
  87. repr(nat),
  88. ','.join([ LeFactory.name2classname(sup.name) for sup in sup_l])
  89. ))
  90. return """
  91. #Initialisation of {name} class attributes
  92. {name}._fields = {fields}
  93. {name}._superiors = {dsups}
  94. {name}._leclass = {leclass}
  95. """.format(
  96. name = LeFactory.name2classname(emtype.name),
  97. fields = repr(type_fields),
  98. dsups = '{'+(','.join(type_superiors))+'}',
  99. leclass = LeFactory.name2classname(emtype.em_class.name)
  100. )
  101. ## @brief Generate python code containing the LeObject API
  102. # @param backend_cls Backend : A model backend class
  103. # @param backend_args dict : A dict representing arguments for backend_cls instanciation
  104. # @param datasource_cls Datasource : A datasource class
  105. # @param datasource_args dict : A dict representing arguments for datasource_cls instanciation
  106. # @return A string representing python code
  107. @staticmethod
  108. def generate_python(backend_cls, backend_args, datasource_cls, datasource_args):
  109. model = Model(backend=backend_cls(**backend_args))
  110. result = ""
  111. #result += "#-*- coding: utf-8 -*-\n"
  112. #Putting import directives in result
  113. result += """
  114. from EditorialModel.model import Model
  115. from leobject.leobject import _LeObject
  116. from leobject.leclass import LeClass
  117. from leobject.letype import LeType
  118. import EditorialModel.fieldtypes
  119. """
  120. result += """
  121. import %s
  122. import %s
  123. """%(backend_cls.__module__, datasource_cls.__module__)
  124. #Generating the code for LeObject class
  125. backend_constructor = '%s.%s(**%s)'%(backend_cls.__module__, backend_cls.__name__, repr(backend_args))
  126. leobj_me_uid = dict()
  127. for comp in model.components('EmType') + model.components('EmClass'):
  128. leobj_me_uid[comp.uid] = LeFactory.name2classname(comp.name)
  129. result += """
  130. ## @brief _LeObject concret clas
  131. # @see leobject::leobject::_LeObject
  132. class LeObject(_LeObject):
  133. _model = Model(backend=%s)
  134. _datasource = %s(**%s)
  135. _me_uid = %s
  136. """%(backend_constructor, datasource_cls.__module__+'.'+datasource_cls.__name__, repr(datasource_args), repr(leobj_me_uid))
  137. emclass_l = model.components(EditorialModel.classes.EmClass)
  138. emtype_l = model.components(EditorialModel.types.EmType)
  139. #LeClass child classes definition
  140. for emclass in emclass_l:
  141. result += """
  142. ## @brief EmClass {name} LeClass child class
  143. # @see leobject::leclass::LeClass
  144. class {name}(LeObject,LeClass):
  145. _class_id = {uid}
  146. """.format(
  147. name = LeFactory.name2classname(emclass.name),
  148. uid = emclass.uid
  149. )
  150. #LeType child classes definition
  151. for emtype in emtype_l:
  152. result += """
  153. ## @brief EmType {name} LeType child class
  154. # @see leobject::letype::LeType
  155. class {name}({leclass},LeType):
  156. _type_id = {uid}
  157. """.format(
  158. name = LeFactory.name2classname(emtype.name),
  159. leclass = LeFactory.name2classname(emtype.em_class.name),
  160. uid = emtype.uid
  161. )
  162. #Set attributes of created LeClass and LeType child classes
  163. for emclass in emclass_l:
  164. result += LeFactory.emclass_pycode(model, emclass)
  165. for emtype in emtype_l:
  166. result += LeFactory.emtype_pycode(model, emtype)
  167. #Populating LeObject._me_uid dict for a rapid fetch of LeType and LeClass given an EM uid
  168. me_uid = { comp.uid:LeFactory.name2classname(comp.name) for comp in emclass_l + emtype_l }
  169. result += """
  170. ## @brief Dict for getting LeClass and LeType child classes given an EM uid
  171. LeObject._me_uid = %s
  172. """%"{"+(','.join([ '%s:%s'%(k,v) for k,v in me_uid.items()]))+"}"
  173. return result