No Description
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 6.4KB

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