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.

model.py 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. #-*- coding:utf-8 -*-
  2. import hashlib
  3. import importlib
  4. from lodel.utils.mlstring import MlString
  5. from lodel.editorial_model.exceptions import *
  6. from lodel.editorial_model.components import EmClass, EmField, EmGroup
  7. ## @brief Describe an editorial model
  8. class EditorialModel(object):
  9. ## @brief Create a new editorial model
  10. # @param name MlString|str|dict : the editorial model name
  11. # @param description MlString|str|dict : the editorial model description
  12. def __init__(self, name, description = None):
  13. self.name = MlString(name)
  14. self.description = MlString(description)
  15. ## @brief Stores all groups indexed by id
  16. self.__groups = dict()
  17. ## @brief Stores all classes indexed by id
  18. self.__classes = dict()
  19. ## @brief EmClass accessor
  20. # @param uid None | str : give this argument to get a specific EmClass
  21. # @return if uid is given returns an EmClass else returns an EmClass iterator
  22. def classes(self, uid = None):
  23. try:
  24. return self.__elt_getter(self.__classes, uid)
  25. except KeyError:
  26. raise EditorialModelException("EmClass not found : '%s'" % uid)
  27. ## @brief EmGroup getter
  28. # @param uid None | str : give this argument to get a specific EmGroup
  29. # @return if uid is given returns an EmGroup else returns an EmGroup iterator
  30. def groups(self, uid = None):
  31. try:
  32. return self.__elt_getter(self.__groups, uid)
  33. except KeyError:
  34. raise EditorialModelException("EmGroup not found : '%s'" % uid)
  35. ## @brief EmField getter
  36. # @param uid str : An EmField uid represented by "CLASSUID.FIELDUID"
  37. # @return Fals or an EmField instance
  38. #
  39. # @todo delete it, useless...
  40. def field(self, uid = None):
  41. spl = uid.split('.')
  42. if len(spl) != 2:
  43. raise ValueError("Malformed EmField identifier : '%s'" % uid)
  44. cls_uid = spl[0]
  45. field_uid = spl[1]
  46. try:
  47. emclass = self.classes(cls_uid)
  48. except KeyError:
  49. return False
  50. try:
  51. return emclass.fields(field_uid)
  52. except KeyError:
  53. pass
  54. return False
  55. ## @brief Add a class to the editorial model
  56. # @param emclass EmClass : the EmClass instance to add
  57. # @return emclass
  58. def add_class(self, emclass):
  59. if not isinstance(emclass, EmClass):
  60. raise ValueError("<class EmClass> expected but got %s " % type(emclass))
  61. if emclass.uid in self.classes():
  62. raise EditorialModelException('Duplicated uid "%s"' % emclass.uid)
  63. self.__classes[emclass.uid] = emclass
  64. return emclass
  65. ## @brief Add a group to the editorial model
  66. # @param emgroup EmGroup : the EmGroup instance to add
  67. # @return emgroup
  68. def add_group(self, emgroup):
  69. if not isinstance(emgroup, EmGroup):
  70. raise ValueError("<class EmGroup> expected but got %s" % type(emgroup))
  71. if emgroup.uid in self.groups():
  72. raise EditorialModelException('Duplicated uid "%s"' % emgroup.uid)
  73. self.__groups[emgroup.uid] = emgroup
  74. return emgroup
  75. ## @brief Add a new EmClass to the editorial model
  76. # @param uid str : EmClass uid
  77. # @param **kwargs : EmClass constructor options ( see @ref lodel.editorial_model.component.EmClass.__init__() )
  78. def new_class(self, uid, **kwargs):
  79. return self.add_class(EmClass(uid, **kwargs))
  80. ## @brief Add a new EmGroup to the editorial model
  81. # @param uid str : EmGroup uid
  82. # @param *kwargs : EmGroup constructor keywords arguments (see @ref lodel.editorial_model.component.EmGroup.__init__() )
  83. def new_group(self, uid, **kwargs):
  84. return self.add_group(EmGroup(uid, **kwargs))
  85. # @brief Save a model
  86. # @param translator module : The translator module to use
  87. # @param **translator_args
  88. def save(self, translator, **translator_kwargs):
  89. if isinstance(translator, str):
  90. translator = self.translator_from_name(translator)
  91. return translator.save(self, **translator_kwargs)
  92. ## @brief Load a model
  93. # @param translator module : The translator module to use
  94. # @param **translator_args
  95. @classmethod
  96. def load(cls, translator, **translator_kwargs):
  97. if isinstance(translator, str):
  98. translator = cls.translator_from_name(translator)
  99. return translator.load(**translator_kwargs)
  100. ## @brief Return a translator module given a translator name
  101. # @param translator_name str : The translator name
  102. # @return the translator python module
  103. # @throw NameError if the translator does not exists
  104. @staticmethod
  105. def translator_from_name(translator_name):
  106. pkg_name = 'lodel.editorial_model.translator.%s' % translator_name
  107. try:
  108. mod = importlib.import_module(pkg_name)
  109. except ImportError:
  110. raise NameError("No translator named %s")
  111. return mod
  112. ## @brief Private getter for __groups or __classes
  113. # @see classes() groups()
  114. def __elt_getter(self, elts, uid):
  115. return list(elts.values()) if uid is None else elts[uid]
  116. ## @brief Lodel hash
  117. def d_hash(self):
  118. payload = "%s%s" % (
  119. self.name,
  120. 'NODESC' if self.description is None else self.description.d_hash()
  121. )
  122. for guid in sorted(self.__groups):
  123. payload += str(self.__groups[guid].d_hash())
  124. for cuid in sorted(self.__classes):
  125. payload += str(self.__classes[cuid].d_hash())
  126. return int.from_bytes(
  127. hashlib.md5(bytes(payload, 'utf-8')).digest(),
  128. byteorder='big'
  129. )