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.

leobject.py 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #-*- coding: utf-8 -*-
  2. ## @package leapi.leobject
  3. # @brief Contains abstract class designed to be implemented by LeObject
  4. #
  5. # This package contains abstract classes leapi.leclass.LeClass , leapi.letype.LeType, leapi.leapi._LeObject.
  6. # Those abstract classes are designed to be mother classes of dynamically generated classes ( see leapi.lefactory.LeFactory )
  7. #
  8. # @note LeObject will be generated by leapi.lefactory.LeFactory
  9. import re
  10. import copy
  11. import warnings
  12. import leapi
  13. from leapi.lecrud import _LeCrud, REL_SUP, REL_SUB
  14. from leapi.lefactory import LeFactory
  15. import EditorialModel
  16. from EditorialModel.types import EmType
  17. ## @brief Main class to handle objects defined by the types of an Editorial Model
  18. class _LeObject(_LeCrud):
  19. ## @brief maps em uid with LeType or LeClass keys are uid values are LeObject childs classes
  20. # @todo check if this attribute shouldn't be in _LeCrud
  21. _me_uid = dict()
  22. ## @brief Stores the fields name associated with fieldtype of the fields that are common to every LeObject
  23. _leo_fieldtypes = dict()
  24. ## @brief Stores the names of the fields storing the EM class uid and EM type uid
  25. _me_uid_field_names = (None, None)
  26. ## @return True if the LeObject is partially instanciated
  27. def is_partial(self):
  28. return not hasattr(self, '_classtype')
  29. ## @brief Check if a LeObject is the relation tree Root
  30. # @todo implementation
  31. def is_root(self):
  32. return False
  33. ## @brief Dirty & quick comparison implementation
  34. def __cmp__(self, other):
  35. return 0 if self == other else 1
  36. ## @brief Dirty & quick equality implementation
  37. # @todo check class
  38. def __eq__(self, other):
  39. uid_fname = self.uidname()
  40. if not hasattr(other, uid_fname) \
  41. or self.uidget() != other.uidget() \
  42. or self.__class__ != other.__class__:
  43. return False
  44. if self.is_complete() and other.is_complete():
  45. for fname in self.fieldlist():
  46. if not hasattr(other, fname) or getattr(other, fname) != getattr(self, fname):
  47. print(fname, 'differ', getattr(other, fname), getattr(self, fname))
  48. return False
  49. return True
  50. ## @brief Quick str cast method implementation
  51. def __str__(self):
  52. return "<%s lodel_id=%d>"%(self.__class__, getattr(self, self.uidname()))
  53. def __repr__(self):
  54. return self.__str__()
  55. ## @brief Returns the name of the uid field
  56. @classmethod
  57. def uidname(cls):
  58. return EditorialModel.classtypes.object_uid
  59. ## @brief Given a ME uid return the corresponding LeClass or LeType class
  60. # @return a LeType or LeClass child class
  61. # @throw KeyError if no corresponding child classes
  62. # @todo check if this method shouldn't be in _LeCrud
  63. @classmethod
  64. def uid2leobj(cls, uid):
  65. uid = int(uid)
  66. if uid not in cls._me_uid:
  67. raise KeyError("No LeType or LeClass child classes with uid '%d'"%uid)
  68. return cls._me_uid[uid]
  69. ## @brief instanciate the relevant lodel object using a dict of datas
  70. @classmethod
  71. def object_from_data(cls, datas):
  72. return cls.uid2leobj(datas['type_id'])(**datas)
  73. @classmethod
  74. def fieldtypes(cls):
  75. if cls._fieldtypes_all is None:
  76. cls._fieldtypes_all = dict()
  77. cls._fieldtypes_all.update(cls._uid_fieldtype)
  78. cls._fieldtypes_all.update(cls._leo_fieldtypes)
  79. return cls._fieldtypes_all
  80. @classmethod
  81. def typefilter(cls):
  82. if hasattr(cls, '_type_id'):
  83. return ('type_id','=', cls._type_id)
  84. elif hasattr(cls, '_class_id'):
  85. return ('class_id', '=', cls._class_id)
  86. else:
  87. raise ValueError("Cannot generate a typefilter with %s class"%cls.__name__)
  88. ## @brief Check that a relational field is valid
  89. # @param field str : a relational field
  90. # @return a nature
  91. @staticmethod
  92. def _prepare_relational_fields(field):
  93. spl = field.split('.')
  94. if len(spl) != 2:
  95. return ValueError("The relationalfield '%s' is not valid"%field)
  96. nature = spl[-1]
  97. if nature not in EditorialModel.classtypes.EmNature.getall():
  98. return ValueError("'%s' is not a valid nature in the field %s"%(nature, field))
  99. if spl[0] == 'superior':
  100. return (REL_SUP, nature)
  101. elif spl[0] == 'subordinate':
  102. return (REL_SUB, nature)
  103. else:
  104. return ValueError("Invalid preffix for relationnal field : '%s'"%spl[0])
  105. ## @brief Class designed to represent the hierarchy roots
  106. # @see _LeObject.get_root() _LeObject.is_root()
  107. class LeRoot(object):
  108. pass
  109. class LeObjectError(Exception):
  110. pass
  111. class LeObjectQueryError(LeObjectError):
  112. pass