1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-06-14 06:20:48 +02:00

Supressed _fields from EmComponent and transforming the EmComponent in a standart object with standarts attributes

This commit is contained in:
Yann 2015-07-24 12:01:17 +02:00
commit b6ef37752f
8 changed files with 93 additions and 161 deletions

View file

@ -9,6 +9,13 @@ import json
## Manages a Json file based backend structure ## Manages a Json file based backend structure
class EmBackendJson(object): class EmBackendJson(object):
cast_methods = {
'uid' : int,
'rank' : int,
'class_id' : int,
'fieldgroup_id' : int
}
## Constructor ## Constructor
# #
# @param json_file str: path to the json_file used as data source # @param json_file str: path to the json_file used as data source
@ -22,5 +29,11 @@ class EmBackendJson(object):
def load(self): def load(self):
data = {} data = {}
for index, component in self.data.items(): for index, component in self.data.items():
data[int(index)] = component attributes = {}
for attr_name, attr_value in component.items():
if attr_name in EmBackendJson.cast_methods:
attributes[attr_name] = EmBackendJson.cast_methods[attr_name](attr_value)
else:
attributes[attr_name] = attr_value
data[int(index)] = attributes
return data return data

View file

@ -24,6 +24,15 @@ class EmClass(EmComponent):
('sortcolumn', ftypes.EmField_char) ('sortcolumn', ftypes.EmField_char)
] ]
## EmClass instanciation
def __init__(self, model, uid, name, classtype, icon = '0', sortcolumn = 'rank', string = None, help_text = None, date_update = None, date_create = None, rank = None):
self.classtype = classtype
self.icon = icon
self.sortcolumn = 'rank'
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)
pass
## Check if the EmComponent is valid ## Check if the EmComponent is valid
# @return True if valid False if not # @return True if valid False if not
def check(self): def check(self):

View file

@ -7,6 +7,7 @@ import datetime
import logging import logging
import EditorialModel.fieldtypes as ftypes import EditorialModel.fieldtypes as ftypes
from Lodel.utils.mlstring import MlString
from collections import OrderedDict from collections import OrderedDict
logger = logging.getLogger('Lodel2.EditorialModel') logger = logging.getLogger('Lodel2.EditorialModel')
@ -22,78 +23,21 @@ class EmComponent(object):
## Used by EmComponent::modify_rank ## Used by EmComponent::modify_rank
ranked_in = None ranked_in = None
## Read only properties def __init__(self, model, uid, name, string = None, help_text = None, date_update = None, date_create = None, rank = None):
_ro_properties = ['date_update', 'date_create', 'uid', 'rank', 'deleted']
## @brief List fields name and fieldtype
#
# This is a list that describe database fields common for each EmComponent child classes.
# A database field is defined here by a tuple(name, type) with name a string and type an EditorialModel.fieldtypes.EmFieldType
# @warning The EmFieldType in second position in the tuples must be a class type and not a class instance !!!
# @see EditorialModel::classes::EmClass::_fields EditorialModel::fieldgroups::EmFieldGroup::_fields EditorialModel::types::EmType::_fields EditorialModel::fields::EmField::_fields
_fields = [
('uid', ftypes.EmField_integer),
('name', ftypes.EmField_char),
('rank', ftypes.EmField_integer),
('date_update', ftypes.EmField_date),
('date_create', ftypes.EmField_date),
('string', ftypes.EmField_mlstring),
('help', ftypes.EmField_mlstring)
]
## Instaciate an EmComponent
# @param id_or_name int|str: name or id of the object
# @throw TypeError if id_or_name is not an integer nor a string
# @throw NotImplementedError if called with EmComponent
def __init__(self, data, model):
if type(self) == EmComponent: if type(self) == EmComponent:
raise NotImplementedError('Abstract class') raise NotImplementedError('Abstract class')
## @brief An OrderedDict storing fields name and values
# Values are handled by EditorialModel::fieldtypes::EmFieldType
# @warning \ref _fields instance property is not the same than EmComponent::_fields class property. In the instance property the EditorialModel::fieldtypes::EmFieldType are instanciated to be able to handle datas
# @see EmComponent::_fields EditorialModel::fieldtypes::EmFieldType
self._fields = OrderedDict([(name, ftype()) for (name, ftype) in (EmComponent._fields + self.__class__._fields)])
self.model = model self.model = model
self.uid = uid
self.name = name
self.string = MlString() if string is None else string
self.help_text = MlString() if help_text is None else help_text
self.date_update = datetime.datetime.now() if date_update is None else date_update #WARNING timezone !
self.date_create = datetime.datetime.now() if date_create is None else date_create #WARNING timezone !
for name, value in data.items(): #Handling specials ranks for component creation
if name in self._fields: self.rank = rank
self._fields[name].from_string(value) pass
## @brief Access an attribute of an EmComponent
# This method is overloads the default __getattr__ to search in EmComponents::_fields . If there is an EditorialModel::EmField with a corresponding name in the component
# it returns its value.
# @param name str: The attribute name
# @throw AttributeError if attribute don't exists
# @see EditorialModel::EmField::value
def __getattr__(self, name):
if name != '_fields' and name in self._fields:
return self._fields[name].value
else:
return super(EmComponent, self).__getattribute__(name)
## @brief Access an EmComponent attribute
# This function overload the default __getattribute__ in order to check if the EmComponent was deleted.
# @param name str: The attribute name
# @throw EmComponentNotExistError if the component was deleted
def __getattribute__(self, name):
if super(EmComponent, self).__getattribute__('deleted'):
raise EmComponentNotExistError("This " + super(EmComponent, self).__getattribute__('__class__').__name__ + " has been deleted")
res = super(EmComponent, self).__getattribute(name)
return res
## Set the value of an EmComponent attribute
# @param name str: The propertie name
# @param value *: The value
def __setattr__(self, name, value):
if name in self.__class__._ro_properties:
raise TypeError("Propertie '" + name + "' is readonly")
if name != '_fields' and hasattr(self, '_fields') and name in object.__getattribute__(self, '_fields'):
self._fields[name].from_python(value)
else:
object.__setattr__(self, name, value)
## @brief Hash function that allows to compare two EmComponent ## @brief Hash function that allows to compare two EmComponent
# @return EmComponent+ClassName+uid # @return EmComponent+ClassName+uid
@ -105,17 +49,6 @@ class EmComponent(object):
def __eq__(self, other): def __eq__(self, other):
return self.__class__ == other.__class__ and self.uid == other.uid return self.__class__ == other.__class__ and self.uid == other.uid
## Set all fields
def populate(self):
records = [] # TODO
for record in records:
for keys in self._fields.keys():
if keys in record:
self._fields[keys].from_string(record[keys])
super(EmComponent, self).__setattr__('deleted', False)
## Check if the EmComponent is valid ## Check if the EmComponent is valid
# This function has to check that rank are correct and continuous other checks are made in childs classes # This function has to check that rank are correct and continuous other checks are made in childs classes
# @warning Hardcoded minimum rank # @warning Hardcoded minimum rank
@ -125,7 +58,7 @@ class EmComponent(object):
if self.get_max_rank() > len(self.same_rank_group()): if self.get_max_rank() > len(self.same_rank_group()):
#Non continuous ranks #Non continuous ranks
for i, component in enumerate(self.same_rank_group()): for i, component in enumerate(self.same_rank_group()):
component._fields['rank'].value = i + 1 component.rank = i + 1
# No need to sort again here # No need to sort again here
return True return True
@ -133,7 +66,7 @@ class EmComponent(object):
# @return A positive integer or -1 if no components # @return A positive integer or -1 if no components
def get_max_rank(self): def get_max_rank(self):
components = self.same_rank_group() components = self.same_rank_group()
return -1 if len(components) == 0 else components[-1].rank return 1 if len(components) == 0 else components[-1].rank
## Return an array of instances that are concerned by the same rank ## Return an array of instances that are concerned by the same rank
# @return An array of instances that are concerned by the same rank # @return An array of instances that are concerned by the same rank
@ -167,9 +100,9 @@ class EmComponent(object):
limits.sort() limits.sort()
for component in [ c for c in self.same_rank_group() if c.rank >= limits[0] and c.rank <= limits[1] ] : for component in [ c for c in self.same_rank_group() if c.rank >= limits[0] and c.rank <= limits[1] ] :
component._fields['rank'].value = component.rank + ( -1 if mod > 0 else 1 ) component.rank = component.rank + ( -1 if mod > 0 else 1 )
self._fields['rank'].value = new_rank self.rank = new_rank
self.model.sort_components(self.__class__) self.model.sort_components(self.__class__)

View file

@ -13,8 +13,11 @@ class EmFieldGroup(EmComponent):
ranked_in = 'class_id' ranked_in = 'class_id'
## List of fields ## EmFieldGroup instanciation
_fields = [('class_id', ftypes.EmField_integer)] def __init__(self, model, uid, name, class_id, string = None, help_text = None, date_update = None, date_create = None, rank = None):
self.class_id = class_id
super(EmFieldGroup, self).__init__(model=model, uid=uid, name=name, string=string, help_text=help_text, date_update=date_update, date_create=date_create, rank=rank)
pass
## Check if the EmFieldGroup is valid ## Check if the EmFieldGroup is valid
# @return True if valid False if not # @return True if valid False if not

View file

@ -9,20 +9,17 @@ from EditorialModel.fieldtypes import EmField_boolean, EmField_char, EmField_int
# Represents one data for a lodel2 document # Represents one data for a lodel2 document
class EmField(EmComponent): class EmField(EmComponent):
table = 'em_field'
ranked_in = 'fieldgroup_id' ranked_in = 'fieldgroup_id'
_fields = [
('fieldtype', EmField_char),
('fieldgroup_id', EmField_integer),
('rel_to_type_id', EmField_integer),
('rel_field_id', EmField_integer),
('optional', EmField_boolean),
('internal', EmField_boolean),
('icon', EmField_icon)
]
def __init__(self, datas, model): def __init__(self, model, uid, name, fieldgroup_id, fieldtype, optional = False, internal = False, rel_to_type_id = None, rel_field_id = None, icon = '0', string = None, help_text = None, date_update = None, date_create = None, rank = None):
super(EmField, self).__init__(datas, model) self.fieldgroup_id = fieldgroup_id
self.fieldtype = fieldtype
self.optional = optional
self.internal = internal
self.rel_to_type_id = rel_to_type_id
self.rel_field_id = rel_field_id
self.icon = icon
super(EmField, self).__init__(model=model, uid=uid, name=name, string=string, help_text=help_text, date_update=date_update, date_create=date_create, rank=rank)
## Check if the EmField is valid ## Check if the EmField is valid
# @return True if valid False if not # @return True if valid False if not

View file

@ -50,14 +50,16 @@ class Model(object):
# @todo Change the thrown exception when a components check fails # @todo Change the thrown exception when a components check fails
# @throw ValueError When a component class don't exists # @throw ValueError When a component class don't exists
def load(self): def load(self):
data = self.backend.load() datas = self.backend.load()
for uid, component in data.items(): for uid, kwargs in datas.items():
cls_name = component['component'] #Store and delete the EmComponent class name from datas
cls_name = kwargs['component']
del kwargs['component']
cls = self.emclass_from_name(cls_name) cls = self.emclass_from_name(cls_name)
if cls: if cls:
component['uid'] = uid kwargs['uid'] = uid
# create a dict for the component and one indexed by uids, store instanciated component in it # create a dict for the component and one indexed by uids, store instanciated component in it
self._components['uids'][uid] = cls(component, self) self._components['uids'][uid] = cls(self, **kwargs)
self._components[cls_name].append(self._components['uids'][uid]) self._components[cls_name].append(self._components['uids'][uid])
else: else:
raise ValueError("Unknow EmComponent class : '" + cls_name + "'") raise ValueError("Unknow EmComponent class : '" + cls_name + "'")
@ -114,36 +116,20 @@ class Model(object):
em_obj = self.emclass_from_name(component_type) em_obj = self.emclass_from_name(component_type)
datas['uid'] = self.new_uid() rank = 'last'
em_component = em_obj(datas, self)
rank = None
if 'rank' in datas: if 'rank' in datas:
rank = datas['rank'] rank = datas['rank']
datas['rank'] = None del datas['rank']
datas['uid'] = self.new_uid()
em_component = em_obj(self, **datas)
self._components['uids'][em_component.uid] = em_component self._components['uids'][em_component.uid] = em_component
self._components[self.name_from_emclass(em_component.__class__)].append(em_component) self._components[self.name_from_emclass(em_component.__class__)].append(em_component)
em_component.rank = em_component.get_max_rank()
create_fails = None if rank != 'last':
em_component.set_rank( 1 if rank == 'first' else rank)
if rank is None or rank == 'last':
em_component.rank = em_component.get_max_rank()
elif datas['rank'] == 'first':
em_component.set_rank(1)
elif isinstance(rank, int):
em_component.set_rank(rank)
else:
create_fails = ValueError("Invalid rank : '"+str(datas['rank'])+"'")
self.delete(em_component.uid)
if not em_component.check():
create_fails = RuntimeError("After creation the component self check fails")
if not create_fails is None:
raise create_fails
return em_component return em_component

View file

@ -1,53 +1,53 @@
{ {
"1" : { "1" : {
"component":"EmClass", "name":"textes", "string":"{\"fre\":\"Texte\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "classtype":"entity", "icon":"0", "sortcolumn":"rank" "component":"EmClass", "name":"textes", "string":"{\"fre\":\"Texte\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "classtype":"entity", "icon":"0", "sortcolumn":"rank"
}, },
"2" : { "2" : {
"component":"EmClass", "name":"personnes", "string":"{\"fre\":\"Personnes\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "classtype":"person", "icon":"0", "sortcolumn":"rank" "component":"EmClass", "name":"personnes", "string":"{\"fre\":\"Personnes\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "classtype":"person", "icon":"0", "sortcolumn":"rank"
}, },
"3" : { "3" : {
"component":"EmFieldGroup", "name":"info", "string":"{\"fre\":\"Info\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"1" "component":"EmFieldGroup", "name":"info", "string":"{\"fre\":\"Info\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"1"
}, },
"4" : { "4" : {
"component":"EmField", "name":"titre", "string":"{\"fre\":\"Titre\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"3", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0" "component":"EmField", "name":"titre", "string":"{\"fre\":\"Titre\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"3", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0"
}, },
"5" : { "5" : {
"component":"EmType", "name":"article", "string":"{\"fre\":\"Article\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"1", "icon":"0", "sortcolumn":"rank", "selected_fields":[7] "component":"EmType", "name":"article", "string":"{\"fre\":\"Article\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"1", "icon":"0", "sortcolumn":"rank", "selected_fields":[7]
}, },
"6" : { "6" : {
"component":"EmType", "name":"personne", "string":"{\"fre\":\"Personne\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"2", "icon":"0", "sortcolumn":"rank", "selected_fields":[10] "component":"EmType", "name":"personne", "string":"{\"fre\":\"Personne\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"2", "icon":"0", "sortcolumn":"rank", "selected_fields":[10]
}, },
"7" : { "7" : {
"component":"EmField", "name":"soustitre", "string":"{\"fre\":\"Sous-titre\"}", "help":"{}", "rank":"2", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"3", "rel_to_type_id":"", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0" "component":"EmField", "name":"soustitre", "string":"{\"fre\":\"Sous-titre\"}", "help_text":"{}", "rank":"2", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"3", "rel_to_type_id":"", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0"
}, },
"8" : { "8" : {
"component":"EmFieldGroup", "name":"civilité", "string":"{\"fre\":\"Civilité\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"2" "component":"EmFieldGroup", "name":"civilité", "string":"{\"fre\":\"Civilité\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"2"
}, },
"9" : { "9" : {
"component":"EmField", "name":"nom", "string":"{\"fre\":\"Nom\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"8", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0" "component":"EmField", "name":"nom", "string":"{\"fre\":\"Nom\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"8", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0"
}, },
"10" : { "10" : {
"component":"EmField", "name":"prenom", "string":"{\"fre\":\"Preom\"}", "help":"{}", "rank":"2", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"8", "rel_to_type_id":"", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0" "component":"EmField", "name":"prenom", "string":"{\"fre\":\"Preom\"}", "help_text":"{}", "rank":"2", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"8", "rel_to_type_id":"", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0"
}, },
"11" : { "11" : {
"component":"EmField", "name":"auteur", "string":"{\"fre\":\"Auteur\"}", "help":"{}", "rank":"3", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"17", "rel_to_type_id":"6", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0" "component":"EmField", "name":"auteur", "string":"{\"fre\":\"Auteur\"}", "help_text":"{}", "rank":"3", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"17", "rel_to_type_id":"6", "rel_field_id":"", "optional":"1", "internal":"", "icon":"0"
}, },
"12" : { "12" : {
"component":"EmField", "name":"adresse", "string":"{\"fre\":\"Adresse\"}", "help":"{}", "rank":"4", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"17", "rel_to_type_id":"", "rel_field_id":"11", "optional":"0", "internal":"", "icon":"0" "component":"EmField", "name":"adresse", "string":"{\"fre\":\"Adresse\"}", "help_text":"{}", "rank":"4", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"17", "rel_to_type_id":"", "rel_field_id":"11", "optional":"0", "internal":"", "icon":"0"
}, },
"13" : { "13" : {
"component":"EmClass", "name":"publication", "string":"{\"fre\":\"Publication\"}", "help":"{}", "rank":"2", "date_update":"", "date_create":"", "classtype":"entity", "icon":"0", "sortcolumn":"rank" "component":"EmClass", "name":"publication", "string":"{\"fre\":\"Publication\"}", "help_text":"{}", "rank":"2", "date_update":"", "date_create":"", "classtype":"entity", "icon":"0", "sortcolumn":"rank"
}, },
"14" : { "14" : {
"component":"EmType", "name":"rubrique", "string":"{\"fre\":\"Rubrique\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"13", "icon":"0", "sortcolumn":"rank", "subordinates":[["parent",5], ["parent",14]] "component":"EmType", "name":"rubrique", "string":"{\"fre\":\"Rubrique\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"13", "icon":"0", "sortcolumn":"rank", "subordinates":[["parent",5], ["parent",14]]
}, },
"15" : { "15" : {
"component":"EmFieldGroup", "name":"info", "string":"{\"fre\":\"Info\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"13" "component":"EmFieldGroup", "name":"info", "string":"{\"fre\":\"Info\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "class_id":"13"
}, },
"16" : { "16" : {
"component":"EmField", "name":"titre", "string":"{\"fre\":\"Titre\"}", "help":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"15", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0" "component":"EmField", "name":"titre", "string":"{\"fre\":\"Titre\"}", "help_text":"{}", "rank":"1", "date_update":"", "date_create":"", "fieldtype":"", "fieldgroup_id":"15", "rel_to_type_id":"", "rel_field_id":"", "optional":"0", "internal":"", "icon":"0"
}, },
"17" : { "17" : {
"component":"EmFieldGroup", "name":"gens", "string":"{\"fre\":\"Gens\"}", "help":"{}", "rank":"2", "date_update":"", "date_create":"", "class_id":"1" "component":"EmFieldGroup", "name":"gens", "string":"{\"fre\":\"Gens\"}", "help_text":"{}", "rank":"2", "date_update":"", "date_create":"", "class_id":"1"
} }
} }

View file

@ -20,25 +20,16 @@ import EditorialModel.classes
# @see EditorialModel::components::EmComponent # @see EditorialModel::components::EmComponent
# @todo sortcolumn handling # @todo sortcolumn handling
class EmType(EmComponent): class EmType(EmComponent):
table = 'em_type'
table_hierarchy = 'em_type_hierarchy'
ranked_in = 'class_id' ranked_in = 'class_id'
## @brief Specific EmClass fields def __init__(self, model, uid, name, class_id, selected_fields = [], subordinates = [], icon = '0', sortcolumn = 'rank', string = None, help_text = None, date_update = None, date_create = None, rank = None):
# @see EditorialModel::components::EmComponent::_fields self.class_id = class_id
_fields = [ self.selected_fields = selected_fields
('class_id', ftypes.EmField_integer), self.subordinates = subordinates
('icon', ftypes.EmField_icon), self.icon = icon
('sortcolumn', ftypes.EmField_char) self.sortcolumn = sortcolumn
] super(EmType, self).__init__(model=model, uid=uid, name=name, string=string, help_text=help_text, date_update=date_update, date_create=date_create, rank=rank)
pass
def __init__(self, data, model):
super(EmType, self).__init__(data, model)
for link in ['selected_fields', 'subordinates']:
if link in data:
self._fields[link] = data[link]
else:
self._fields[link] = []
@classmethod @classmethod
## Create a new EmType and instanciate it ## Create a new EmType and instanciate it