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.

classes.py 6.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # -*- coding: utf-8 -*-
  2. ## @file classes.py
  3. # @see EditorialModel::classes::EmClass
  4. import copy
  5. # imports used in classtypes <-> actual model checks
  6. import difflib
  7. import warnings
  8. import EditorialModel
  9. from EditorialModel.components import EmComponent
  10. from EditorialModel.classtypes import EmClassType
  11. ## @brief Manipulate Classes of the Editorial Model
  12. # Create classes of object.
  13. # @see EmClass, EditorialModel.types.EmType, EditorialModel.fieldgroups.EmFieldGroup, EmField
  14. # @todo sortcolumn handling
  15. class EmClass(EmComponent):
  16. ranked_in = 'classtype'
  17. ## EmClass instanciation
  18. # @todo Classtype initialisation and test is not good EmClassType should give an answer or something like that
  19. # @todo defines types check for icon and sortcolumn
  20. def __init__(self, model, uid, name, classtype, icon='0', sortcolumn='rank', string=None, help_text=None, date_update=None, date_create=None, rank=None):
  21. if EmClassType.get(classtype) is None:
  22. raise AttributeError("Unknown classtype '%s'" % classtype)
  23. self.classtype = classtype
  24. self.icon = icon
  25. self.sortcolumn = sortcolumn # 'rank'
  26. super(EmClass, self).__init__(model=model, uid=uid, name=name, string=string, help_text=help_text, date_update=date_update, date_create=date_create, rank=rank)
  27. ## @brief Check if the EmComponent is valid
  28. #
  29. # This function add default and common fields to the EmClass if they are not yet created (and raises warning if existing common fields are outdated given the one describe in EditorialModel.classtypes
  30. # @throw EmComponentCheckError if fails
  31. #
  32. # @warning If default parameters of EmField constructor changes this method can be broken
  33. def check(self):
  34. # Checks that this class is up to date given the common_fields described in EditorialModel.classtypes
  35. # if not just print a warning, don't raise an Exception
  36. for field in self.fields():
  37. if field.name in EditorialModel.classtypes.common_fields:
  38. # Building fieltypes options to match the ones stored in EditorialModel.classtypes
  39. ftype_opts = field.fieldtype_options()
  40. ftype_opts['fieldtype'] = field.fieldtype
  41. ctype_opts = EditorialModel.classtypes.common_fields[field.name]
  42. #Adding default value for options nullable, uniq and internal to fieldtypes options stored in classtypes
  43. defaults = { 'nullable': False, 'uniq': False, 'internal': False}
  44. for opt_name, opt_val in defaults.items():
  45. if opt_name not in ctype_opts:
  46. ctype_opts[opt_name] = opt_val
  47. if ftype_opts != ctype_opts:
  48. # If options mismatch produce a diff and display a warning
  49. ctype_opts = [ "%s: %s\n"%(repr(k), repr(ctype_opts[k])) for k in sorted(ctype_opts.keys())]
  50. ftype_opts = [ "%s: %s\n"%(repr(k), repr(ftype_opts[k])) for k in sorted(ftype_opts.keys())]
  51. diff_list = difflib.unified_diff(
  52. ctype_opts,
  53. ftype_opts,
  54. fromfile="Classtypes.%s" % field.name,
  55. tofile="CurrentModel_%s.%s" % (self.name, field.name)
  56. )
  57. diff = ''.join(diff_list)
  58. warnings.warn("LOADED MODEL IS OUTDATED !!! The common_fields defined in classtypes differs from the fields in this model.\nHere is a diff : \n%s" % diff)
  59. for fname in self.default_fields_list().keys():
  60. if fname not in [f.name for f in self.fields()]:
  61. self.model.add_default_class_fields(self.uid)
  62. super(EmClass, self).check()
  63. ## @brief Return the default fields list for this EmClass
  64. # @return a dict with key = fieldname and value is a dict to pass to the EditorialModel::model::Model::creat_component() method
  65. def default_fields_list(self):
  66. ctype = EditorialModel.classtypes.EmClassType.get(self.classtype)
  67. res = ctype['default_fields']
  68. for k, v in EditorialModel.classtypes.common_fields.items():
  69. res[k] = copy.copy(v)
  70. return res
  71. ## @brief Delete a class if it's ''empty''
  72. # If a class has no fieldgroups delete it
  73. # @return bool : True if deleted False if deletion aborded
  74. def delete_check(self):
  75. for emtype in self.model.components(EditorialModel.types.EmType):
  76. if emtype.class_id == self.uid:
  77. return False
  78. #If the class contains EmField that are not added by default, you cannot delete the EmClass
  79. if len([f for f in self.fields() if f.name not in self.default_fields_list().keys()]) > 0:
  80. return False
  81. return True
  82. ## Retrieve list of the field_groups of this class
  83. # @return A list of fieldgroups instance
  84. def _fieldgroups(self):
  85. ret = []
  86. for fieldgroup in self.model.components(EditorialModel.fieldgroups.EmFieldGroup):
  87. if fieldgroup.class_id == self.uid:
  88. ret.append(fieldgroup)
  89. return ret
  90. ## Retrieve list of fields
  91. # @return fields [EmField]:
  92. def fields(self, relational=True):
  93. if relational:
  94. return [f for f in self.model.components('EmField') if f.class_id == self.uid]
  95. else:
  96. return [f for f in self.model.components('EmField') if f.class_id == self.uid and f.fieldtype != 'rel2type' and f.rel_field_id is None]
  97. ## Retrieve list of type of this class
  98. # @return types [EditorialModel.types.EmType]:
  99. def types(self):
  100. ret = []
  101. for emtype in self.model.components(EditorialModel.types.EmType):
  102. if emtype.class_id == self.uid:
  103. ret.append(emtype)
  104. return ret
  105. ## Add a new EditorialModel.types.EmType that can ben linked to this class
  106. # @param em_type EditorialModel.types.EmType: type to link
  107. # @return success bool: done or not
  108. # @deprecated To do this add a rel2type field to any fieldtype of this EmClass
  109. def link_type(self, em_type):
  110. pass
  111. ## Retrieve list of EditorialModel.types.EmType that are linked to this class
  112. # @return types [EditorialModel.types.EmType]:
  113. def linked_types(self):
  114. res = list()
  115. for field in self.fields():
  116. if field.fieldtype_instance().name == 'rel2type':
  117. res.append(self.model.component(field.rel_to_type_id))
  118. return res