#-*- coding: utf-8 -*- ## @package leapi.leobject # @brief Contains abstract class designed to be implemented by LeObject # # This package contains abstract classes leapi.leclass.LeClass , leapi.letype.LeType, leapi.leapi._LeObject. # Those abstract classes are designed to be mother classes of dynamically generated classes ( see leapi.lefactory.LeFactory ) # # @note LeObject will be generated by leapi.lefactory.LeFactory import re import copy import warnings import leapi from leapi.lecrud import _LeCrud, REL_SUP, REL_SUB from leapi.lefactory import LeFactory import EditorialModel from EditorialModel.types import EmType ## @brief Main class to handle objects defined by the types of an Editorial Model class _LeObject(_LeCrud): ## @brief maps em uid with LeType or LeClass keys are uid values are LeObject childs classes # @todo check if this attribute shouldn't be in _LeCrud _me_uid = dict() ## @brief Stores the fields name associated with fieldtype of the fields that are common to every LeObject _leo_fieldtypes = dict() ## @brief Stores the names of the fields storing the EM class uid and EM type uid _me_uid_field_names = (None, None) ## @return True if the LeObject is partially instanciated def is_partial(self): return not hasattr(self, '_classtype') ## @brief Check if a LeObject is the relation tree Root # @todo implementation def is_root(self): return False ## @brief Dirty & quick comparison implementation def __cmp__(self, other): return 0 if self == other else 1 ## @brief Dirty & quick equality implementation # @todo check class def __eq__(self, other): uid_fname = self.uidname() if not hasattr(other, uid_fname): return False return getattr(self, uid_fname) == getattr(other, uid_fname) ## @brief Quick str cast method implementation def __str__(self): return "<%s lodel_id=%d>"%(self.__class__, getattr(self, self.uidname())) def __repr__(self): return self.__str__() ## @brief Returns the name of the uid field @classmethod def uidname(cls): return EditorialModel.classtypes.object_uid ## @brief Given a ME uid return the corresponding LeClass or LeType class # @return a LeType or LeClass child class # @throw KeyError if no corresponding child classes # @todo check if this method shouldn't be in _LeCrud @classmethod def uid2leobj(cls, uid): uid = int(uid) if uid not in cls._me_uid: raise KeyError("No LeType or LeClass child classes with uid '%d'"%uid) return cls._me_uid[uid] ## @brief instanciate the relevant lodel object using a dict of datas @classmethod def object_from_data(cls, datas): return cls.uid2leobj(datas['type_id'])(**datas) @classmethod def fieldtypes(cls): if cls._fieldtypes_all is None: cls._fieldtypes_all = dict() cls._fieldtypes_all.update(cls._uid_fieldtype) cls._fieldtypes_all.update(cls._leo_fieldtypes) return cls._fieldtypes_all @classmethod def typefilter(cls): if hasattr(cls, '_type_id'): return ('type_id','=', cls._type_id) elif hasattr(cls, '_class_id'): return ('class_id', '=', cls._class_id) else: raise ValueError("Cannot generate a typefilter with %s class"%cls.__name__) ## @brief Check that a relational field is valid # @param field str : a relational field # @return a nature @staticmethod def _prepare_relational_fields(field): spl = field.split('.') if len(spl) != 2: return ValueError("The relationalfield '%s' is not valid"%field) nature = spl[-1] if nature not in EditorialModel.classtypes.EmNature.getall(): return ValueError("'%s' is not a valid nature in the field %s"%(nature, field)) if spl[0] == 'superior': return (REL_SUP, nature) elif spl[0] == 'subordinate': return (REL_SUB, nature) else: return ValueError("Invalid preffix for relationnal field : '%s'"%spl[0]) ## @brief Class designed to represent the hierarchy roots # @see _LeObject.get_root() _LeObject.is_root() class LeRoot(object): pass class LeObjectError(Exception): pass class LeObjectQueryError(LeObjectError): pass