mirror of
https://github.com/yweber/lodel2.git
synced 2026-06-14 06:20:48 +02:00
No extended checks was done. Only tested if the check passes without syntax error and without failing with no reason
160 lines
6.6 KiB
Python
160 lines
6.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
## @file editorialmodel.py
|
|
# Manage instance of an editorial model
|
|
|
|
from EditorialModel.migrationhandler.dummy import DummyMigrationHandler
|
|
from EditorialModel.classes import EmClass
|
|
from EditorialModel.fieldgroups import EmFieldGroup
|
|
from EditorialModel.fields import EmField
|
|
from EditorialModel.types import EmType
|
|
from EditorialModel.exceptions import *
|
|
import EditorialModel
|
|
|
|
|
|
## Manages the Editorial Model
|
|
class Model(object):
|
|
|
|
components_class = [EmClass, EmField, EmFieldGroup, EmType]
|
|
|
|
## Constructor
|
|
#
|
|
# @param backend unknown: A backend object instanciated from one of the classes in the backend module
|
|
def __init__(self, backend, migration_handler = None):
|
|
self.migration_handler = DummyMigrationHandler() if migration_handler is None else migration_handler
|
|
self.backend = backend
|
|
self._components = {'uids': {}, 'EmClass': [], 'EmType': [], 'EmField': [], 'EmFieldGroup': []}
|
|
self.load()
|
|
|
|
@staticmethod
|
|
## Given a name return an EmComponent child class
|
|
# @param class_name str : The name to identify an EmComponent class
|
|
# @return A python class or False if the class_name is not a name of an EmComponent child class
|
|
def emclass_from_name(class_name):
|
|
for cls in Model.components_class:
|
|
if cls.__name__ == class_name:
|
|
return cls
|
|
return False
|
|
|
|
@staticmethod
|
|
## Given a python class return a name
|
|
# @param cls : The python class we want the name
|
|
# @return A class name as string or False if cls is not an EmComponent child class
|
|
def name_from_emclass(em_class):
|
|
if em_class not in Model.components_class:
|
|
return False
|
|
return em_class.__name__
|
|
|
|
## Loads the structure of the Editorial Model
|
|
#
|
|
# Gets all the objects contained in that structure and creates a dict indexed by their uids
|
|
# @todo Change the thrown exception when a components check fails
|
|
# @throw ValueError When a component class don't exists
|
|
def load(self):
|
|
datas = self.backend.load()
|
|
for uid, kwargs in datas.items():
|
|
#Store and delete the EmComponent class name from datas
|
|
cls_name = kwargs['component']
|
|
del kwargs['component']
|
|
cls = self.emclass_from_name(cls_name)
|
|
if cls:
|
|
kwargs['uid'] = uid
|
|
# create a dict for the component and one indexed by uids, store instanciated component in it
|
|
self._components['uids'][uid] = cls(self, **kwargs)
|
|
self._components[cls_name].append(self._components['uids'][uid])
|
|
else:
|
|
raise ValueError("Unknow EmComponent class : '" + cls_name + "'")
|
|
|
|
#Sorting by rank
|
|
for component_class in Model.components_class:
|
|
self.sort_components(component_class)
|
|
|
|
#Check integrity
|
|
for uid, component in self._components['uids'].items():
|
|
try:
|
|
component.check()
|
|
except EmComponentCheckError as e:
|
|
raise EmComponentCheckError("The component with uid %d is not valid. Check returns the following error : \"%s\"" % (uid, str(e)))
|
|
|
|
## Saves data using the current backend
|
|
def save(self):
|
|
return self.backend.save()
|
|
|
|
## Given a EmComponent child class return a list of instances
|
|
# @param cls EmComponent : A python class
|
|
# @return a list of instances or False if the class is not an EmComponent child
|
|
def components(self, cls):
|
|
key_name = self.name_from_emclass(cls)
|
|
return False if key_name is False else self._components[key_name]
|
|
|
|
## Return an EmComponent given an uid
|
|
# @param uid int : An EmComponent uid
|
|
# @return The corresponding instance or False if uid don't exists
|
|
def component(self, uid):
|
|
return False if uid not in self._components['uids'] else self._components['uids'][uid]
|
|
|
|
## Sort components by rank in Model::_components
|
|
# @param emclass pythonClass : The type of components to sort
|
|
# @throw AttributeError if emclass is not valid
|
|
def sort_components(self, component_class):
|
|
if component_class not in self.components_class:
|
|
raise AttributeError("Bad argument emclass : '"+emclass+"', excpeting one of "+str(self.components_class))
|
|
|
|
self._components[self.name_from_emclass(component_class)] = sorted(self.components(component_class), key=lambda comp: comp.rank)
|
|
|
|
## Return a new uid
|
|
# @return a new uid
|
|
def new_uid(self):
|
|
used_uid = [ int(uid) for uid in self._components['uids'].keys()]
|
|
return sorted(used_uid)[-1] + 1 if len(used_uid) > 0 else 1
|
|
|
|
## Create a component from a component type and datas
|
|
#
|
|
# @note if datas does not contains a rank the new component will be added last
|
|
# @note datas['rank'] can be an integer or two specials strings 'last' or 'first'
|
|
# @param component_type str : a component type ( component_class, component_fieldgroup, component_field or component_type )
|
|
# @param datas dict : the options needed by the component creation
|
|
# @throw ValueError if datas['rank'] is not valid (too big or too small, not an integer nor 'last' or 'first' )
|
|
def create_component(self, component_type, datas):
|
|
|
|
em_obj = self.emclass_from_name(component_type)
|
|
|
|
rank = 'last'
|
|
if 'rank' in datas:
|
|
rank = datas['rank']
|
|
del datas['rank']
|
|
|
|
datas['uid'] = self.new_uid()
|
|
em_component = em_obj(self, **datas)
|
|
|
|
self._components['uids'][em_component.uid] = em_component
|
|
self._components[self.name_from_emclass(em_component.__class__)].append(em_component)
|
|
|
|
em_component.rank = em_component.get_max_rank()
|
|
if rank != 'last':
|
|
em_component.set_rank( 1 if rank == 'first' else rank)
|
|
|
|
return em_component
|
|
|
|
## Delete a component
|
|
# @param uid int : Component identifier
|
|
# @throw EditorialModel.components.EmComponentNotExistError
|
|
# @todo unable uid check
|
|
def delete_component(self, uid):
|
|
if uid not in self._components[uid]:
|
|
raise EditorialModel.components.EmComponentNotExistError()
|
|
em_component = self._components[uid]
|
|
if em_component.delete_p():
|
|
self._components[self.name_from_emclass(em_component.__class__)].remove(em_component)
|
|
del self._components['uids'][uid]
|
|
return True
|
|
|
|
## Changes the current backend
|
|
#
|
|
# @param backend unknown: A backend object
|
|
def set_backend(self, backend):
|
|
self.backend = backend
|
|
|
|
## Returns a list of all the EmClass objects of the model
|
|
def classes(self):
|
|
return list(self._components[self.name_from_emclass(EmClass)])
|