mirror of
https://github.com/yweber/lodel2.git
synced 2026-07-05 07:10:48 +02:00
First commit with an em_editor instance
This commit is contained in:
parent
3325e8ee16
commit
362c67529c
16 changed files with 1891 additions and 5 deletions
|
|
@ -139,10 +139,6 @@ class EmField(EmComponent):
|
|||
#Uniq Name check
|
||||
if len([f for f in self.em_class.fields() if f.name == self.name]) > 1:
|
||||
raise EmComponentCheckError("The field %d has a name '%s' that is not uniq in the EmClass %d" % (self.uid, self.name, self.em_class.uid))
|
||||
#rel2type uniq check
|
||||
if self.fieldtype == 'rel2type':
|
||||
if len([f for f in self.em_class.fields() if f.fieldtype == 'rel2type' and f.rel_to_type_id == self.rel_to_type_id]) > 1:
|
||||
raise EmComponentCheckError("The rel2type %d is not uniq, another field is linked to the same type '%s' in the same class '%s'" % (self.uid, self.model.component(self.rel_to_type_id).name, self.em_class.name))
|
||||
|
||||
## @brief Delete a field if it's not linked
|
||||
# @return bool : True if deleted False if deletion aborded
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ class Model(object):
|
|||
em_obj = self.emclass_from_name(component_type)
|
||||
|
||||
rank = 'last'
|
||||
if 'rank' in datas:
|
||||
if 'rank' in datas and not datas['rank'] is None:
|
||||
rank = datas['rank']
|
||||
del datas['rank']
|
||||
|
||||
|
|
@ -221,6 +221,28 @@ class Model(object):
|
|||
|
||||
return em_component
|
||||
|
||||
## @brief Create a new EmClass
|
||||
def add_class(self, name, classtype, string=None, help_text=None, date_update = None, date_create = None, rank = None):
|
||||
datas = locals()
|
||||
del(datas['self'])
|
||||
return self.create_component('EmClass', datas)
|
||||
|
||||
## @brief Create a new EmType
|
||||
def add_type(self, name, emclass, fields_list = None, superiors_list = None, icon='0', sortcolumn='rank', string = None, help_text = None, date_update = None, date_create = None, rank = None):
|
||||
datas = locals()
|
||||
del(datas['self'])
|
||||
emclass = datas['emclass']
|
||||
del(datas['emclass'])
|
||||
datas['class_id'] = emclass.uid if isinstance(emclass, EmClass) else emclass
|
||||
return self.create_component('EmType', datas)
|
||||
|
||||
## @brief Add a new EmField
|
||||
def add_field(self, name, emclass, fieldtype, **kwargs):
|
||||
kwargs['name'] = name
|
||||
kwargs['fieldtype'] = fieldtype
|
||||
kwargs['class_id'] = emclass.uid if isinstance(emclass, EmClass) else emclass
|
||||
return self.create_component('EmField', kwargs)
|
||||
|
||||
## @brief Add to a class (if not exists) the default fields
|
||||
#
|
||||
# @param class_uid int : An EmClass uid
|
||||
|
|
|
|||
26
em_editor/Makefile
Normal file
26
em_editor/Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
all: refreshdyn dbinit dirinit
|
||||
|
||||
refreshdyn: distclean
|
||||
python -c "import utils; utils.refreshdyn()"
|
||||
|
||||
dbinit:
|
||||
python -c "import utils; utils.db_init()"
|
||||
|
||||
dirinit:
|
||||
python -c "import utils; utils.dir_init()"
|
||||
|
||||
emgraph:
|
||||
python -c "import utils; utils.em_graph()"
|
||||
|
||||
.PHONY: clean cleanpycache cleanpyc refreshdyn distclean
|
||||
|
||||
distclean: clean
|
||||
-@rm -vf dynleapi.py
|
||||
|
||||
clean: cleanpycache
|
||||
|
||||
cleanpyc:
|
||||
-@rm -vf *.pyc
|
||||
|
||||
cleanpycache: cleanpyc
|
||||
-@rm -vfR __pycache__
|
||||
11
em_editor/README.txt
Normal file
11
em_editor/README.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
Common operations :
|
||||
===================
|
||||
|
||||
Refresh leapi dynamic code (when the Editorial Model is updated) :
|
||||
make refreshdyn
|
||||
|
||||
Update or init the database :
|
||||
make dbinit
|
||||
|
||||
To run an interactive python interpreter in the instance environnment run :
|
||||
python loader.py
|
||||
334
em_editor/dynleapi.py
Normal file
334
em_editor/dynleapi.py
Normal file
|
|
@ -0,0 +1,334 @@
|
|||
## @author LeFactory
|
||||
|
||||
import EditorialModel
|
||||
from EditorialModel import fieldtypes
|
||||
from EditorialModel.fieldtypes import naturerelation, leo, datetime, dictionary, rank, namerelation, pk, bool, i18n, char, integer, emuid
|
||||
from Lodel.utils.mlstring import MlString
|
||||
|
||||
import leapi
|
||||
import leapi.lecrud
|
||||
import leapi.leobject
|
||||
import leapi.lerelation
|
||||
from leapi.leclass import _LeClass
|
||||
from leapi.letype import _LeType
|
||||
|
||||
import DataSource.MySQL.leapidatasource
|
||||
|
||||
|
||||
## @brief _LeCrud concret class
|
||||
# @see leapi.lecrud._LeCrud
|
||||
class LeCrud(leapi.lecrud._LeCrud):
|
||||
_datasource = DataSource.MySQL.leapidatasource.LeDataSourceSQL(**{})
|
||||
_uid_fieldtype = None
|
||||
|
||||
## @brief _LeObject concret class
|
||||
# @see leapi.leobject._LeObject
|
||||
class LeObject(LeCrud, leapi.leobject._LeObject):
|
||||
_me_uid = {32: 'Emclass', 33: 'Emtype', 34: 'Emfield', 22: 'Emcomponent', 1: '_Editorialmodel', 8: '_Classtype', 15: '_Hierarchy', 29: 'Classtype', 30: 'Hierarchyoptions', 31: 'Editorialmodel'}
|
||||
_me_uid_field_names = ('class_id', 'type_id')
|
||||
_uid_fieldtype = { 'lodel_id': EditorialModel.fieldtypes.pk.EmFieldType(**{'uniq': False, 'nullable': False, 'immutable': True, 'internal': 'autosql', 'string': '{"___": "", "fre": "identifiant lodel", "eng": "lodel identifier"}'}) }
|
||||
_leo_fieldtypes = {
|
||||
'class_id': EditorialModel.fieldtypes.emuid.EmFieldType(**{'uniq': False, 'nullable': False, 'immutable': True, 'internal': 'automatic', 'string': '{"___": "", "fre": "identifiant de la classe", "eng": "class identifier"}', 'is_id_class': True}),
|
||||
'type_id': EditorialModel.fieldtypes.emuid.EmFieldType(**{'uniq': False, 'nullable': False, 'immutable': True, 'internal': 'automatic', 'string': '{"___": "", "fre": "identifiant de la type", "eng": "type identifier"}', 'is_id_class': False}),
|
||||
'modification_date': EditorialModel.fieldtypes.datetime.EmFieldType(**{'uniq': False, 'internal': 'autosql', 'now_on_update': True, 'immutable': True, 'nullable': False, 'now_on_create': True, 'string': '{"___": "", "fre": "Date de modification", "eng": "Modification date"}'}),
|
||||
'string': None,
|
||||
'creation_date': EditorialModel.fieldtypes.datetime.EmFieldType(**{'uniq': False, 'internal': 'autosql', 'now_on_create': True, 'immutable': True, 'nullable': False, 'string': '{"___": "", "fre": "Date de création", "eng": "Creation date"}'})
|
||||
}
|
||||
|
||||
## @brief _LeRelation concret class
|
||||
# @see leapi.lerelation._LeRelation
|
||||
class LeRelation(LeCrud, leapi.lerelation._LeRelation):
|
||||
_uid_fieldtype = { 'id_relation': EditorialModel.fieldtypes.pk.EmFieldType(**{'immutable': True, 'internal': 'autosql'}) }
|
||||
_rel_fieldtypes = {
|
||||
'relation_name': EditorialModel.fieldtypes.namerelation.EmFieldType(**{'max_length': 128, 'immutable': True}),
|
||||
'nature': EditorialModel.fieldtypes.naturerelation.EmFieldType(**{'immutable': True}),
|
||||
'superior': EditorialModel.fieldtypes.leo.EmFieldType(**{'immutable': True, 'superior': True}),
|
||||
'depth': EditorialModel.fieldtypes.integer.EmFieldType(**{'immutable': True, 'internal': 'automatic'}),
|
||||
'rank': EditorialModel.fieldtypes.rank.EmFieldType(**{'immutable': True, 'internal': 'automatic'}),
|
||||
'subordinate': EditorialModel.fieldtypes.leo.EmFieldType(**{'immutable': True, 'superior': False})
|
||||
}
|
||||
## WARNING !!!! OBSOLETE ! DON'T USE IT
|
||||
_superior_field_name = 'superior'
|
||||
## WARNING !!!! OBSOLETE ! DON'T USE IT
|
||||
_subordinate_field_name = 'subordinate'
|
||||
|
||||
class LeHierarch(LeRelation, leapi.lerelation._LeHierarch):
|
||||
pass
|
||||
|
||||
class LeRel2Type(LeRelation, leapi.lerelation._LeRel2Type):
|
||||
pass
|
||||
|
||||
class LeClass(LeObject, _LeClass):
|
||||
pass
|
||||
|
||||
class LeType(LeClass, _LeType):
|
||||
pass
|
||||
|
||||
## @brief EmClass _Editorialmodel LeClass child class
|
||||
# @see leapi.leclass.LeClass
|
||||
class _Editorialmodel(LeClass, LeObject):
|
||||
_class_id = 1
|
||||
ml_string = MlString('_EditorialModel')
|
||||
|
||||
|
||||
## @brief EmClass _Classtype LeClass child class
|
||||
# @see leapi.leclass.LeClass
|
||||
class _Classtype(LeClass, LeObject):
|
||||
_class_id = 8
|
||||
ml_string = MlString('_ClassType')
|
||||
|
||||
|
||||
## @brief EmClass _Hierarchy LeClass child class
|
||||
# @see leapi.leclass.LeClass
|
||||
class _Hierarchy(LeClass, LeObject):
|
||||
_class_id = 15
|
||||
ml_string = MlString('_Hierarchy')
|
||||
|
||||
|
||||
## @brief EmClass Emcomponent LeClass child class
|
||||
# @see leapi.leclass.LeClass
|
||||
class Emcomponent(LeClass, LeObject):
|
||||
_class_id = 22
|
||||
ml_string = MlString('EmComponent')
|
||||
|
||||
|
||||
## @brief EmType Classtype LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Classtype(LeType, _Classtype):
|
||||
_type_id = 29
|
||||
ml_string = MlString('ClassType')
|
||||
|
||||
|
||||
## @brief EmType Hierarchyoptions LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Hierarchyoptions(LeType, _Hierarchy):
|
||||
_type_id = 30
|
||||
ml_string = MlString('HierarchyOptions')
|
||||
|
||||
|
||||
## @brief EmType Editorialmodel LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Editorialmodel(LeType, _Editorialmodel):
|
||||
_type_id = 31
|
||||
ml_string = MlString('EditorialModel')
|
||||
|
||||
|
||||
## @brief EmType Emclass LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Emclass(LeType, Emcomponent):
|
||||
_type_id = 32
|
||||
ml_string = MlString('EmClass')
|
||||
|
||||
|
||||
## @brief EmType Emtype LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Emtype(LeType, Emcomponent):
|
||||
_type_id = 33
|
||||
ml_string = MlString('EmType')
|
||||
|
||||
|
||||
## @brief EmType Emfield LeType child class
|
||||
# @see leobject::letype::LeType
|
||||
class Emfield(LeType, Emcomponent):
|
||||
_type_id = 34
|
||||
ml_string = MlString('EmField')
|
||||
|
||||
|
||||
class Rel_ClasstypeHierarchyoptionsHierarchy_Specs(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
'nature': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 10, 'uniq': False, 'nullable': False})
|
||||
}
|
||||
_superior_cls = _Classtype
|
||||
_subordinate_cls = Hierarchyoptions
|
||||
_relation_name = 'hierarchy_specs'
|
||||
|
||||
|
||||
class RelEmcomponentClasstypeClasstype(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Classtype
|
||||
_relation_name = 'classtype'
|
||||
|
||||
|
||||
class RelEmcomponentEmfieldSort_Column(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Emfield
|
||||
_relation_name = 'sort_column'
|
||||
|
||||
|
||||
class RelEmcomponentEmclassParent_Class(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Emclass
|
||||
_relation_name = 'parent_class'
|
||||
|
||||
|
||||
class RelEmcomponentEmfieldSelected_Field(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Emfield
|
||||
_relation_name = 'selected_field'
|
||||
|
||||
|
||||
class RelEmcomponentEmtypeSuperiors(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
'nature': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': '10', 'uniq': False, 'nullable': False})
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Emtype
|
||||
_relation_name = 'superiors'
|
||||
|
||||
|
||||
class RelEmcomponentEmfieldRel_Field(LeRel2Type):
|
||||
_rel_attr_fieldtypes = {
|
||||
}
|
||||
_superior_cls = Emcomponent
|
||||
_subordinate_cls = Emfield
|
||||
_relation_name = 'rel_field'
|
||||
|
||||
|
||||
#Initialisation of _Editorialmodel class attributes
|
||||
_Editorialmodel._fieldtypes = {
|
||||
'description': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 4096, 'uniq': False, 'nullable': False}),
|
||||
'string': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': 'automatic', 'max_length': 128, 'immutable': False, 'uniq': False, 'nullable': True}),
|
||||
'name': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 56, 'uniq': False, 'nullable': False})
|
||||
}
|
||||
_Editorialmodel.ml_fields_strings = {
|
||||
'class_id': MlString({"___": "class_id", "eng": "class identifier", "fre": "identifiant de la classe"}),
|
||||
'type_id': MlString({"___": "type_id", "eng": "type identifier", "fre": "identifiant de la type"}),
|
||||
'name': MlString({"___": "name"}),
|
||||
'lodel_id': MlString({"___": "lodel_id", "eng": "lodel identifier", "fre": "identifiant lodel"}),
|
||||
'modification_date': MlString({"___": "modification_date", "eng": "Modification date", "fre": "Date de modification"}),
|
||||
'string': MlString({"___": "string", "eng": "String representation", "fre": "Repr\u00e9sentation textuel"}),
|
||||
'creation_date': MlString({"___": "creation_date", "eng": "Creation date", "fre": "Date de cr\u00e9ation"}),
|
||||
'description': MlString({"___": "description"})
|
||||
}
|
||||
_Editorialmodel._linked_types = {
|
||||
}
|
||||
_Editorialmodel._classtype = 'entity'
|
||||
|
||||
#Initialisation of _Classtype class attributes
|
||||
_Classtype._fieldtypes = {
|
||||
'string': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': 'automatic', 'max_length': 128, 'immutable': False, 'uniq': False, 'nullable': True}),
|
||||
'name': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 56, 'uniq': False, 'nullable': False})
|
||||
}
|
||||
_Classtype.ml_fields_strings = {
|
||||
'class_id': MlString({"___": "class_id", "eng": "class identifier", "fre": "identifiant de la classe"}),
|
||||
'type_id': MlString({"___": "type_id", "eng": "type identifier", "fre": "identifiant de la type"}),
|
||||
'name': MlString({"___": "name"}),
|
||||
'lodel_id': MlString({"___": "lodel_id", "eng": "lodel identifier", "fre": "identifiant lodel"}),
|
||||
'modification_date': MlString({"___": "modification_date", "eng": "Modification date", "fre": "Date de modification"}),
|
||||
'string': MlString({"___": "string", "eng": "String representation", "fre": "Repr\u00e9sentation textuel"}),
|
||||
'creation_date': MlString({"___": "creation_date", "eng": "Creation date", "fre": "Date de cr\u00e9ation"}),
|
||||
'hierarchy_specs': MlString({"___": "hierarchy_specs"}),
|
||||
'nature': MlString({"___": "nature"})
|
||||
}
|
||||
_Classtype._linked_types = {
|
||||
'hierarchy_specs': Hierarchyoptions
|
||||
}
|
||||
_Classtype._classtype = 'entity'
|
||||
|
||||
#Initialisation of _Hierarchy class attributes
|
||||
_Hierarchy._fieldtypes = {
|
||||
'string': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': 'automatic', 'max_length': 128, 'immutable': False, 'uniq': False, 'nullable': True}),
|
||||
'attach': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 10, 'uniq': False, 'nullable': False}),
|
||||
'maxdepth': EditorialModel.fieldtypes.integer.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'maxchildren': EditorialModel.fieldtypes.integer.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'automatic': EditorialModel.fieldtypes.bool.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False})
|
||||
}
|
||||
_Hierarchy.ml_fields_strings = {
|
||||
'maxchildren': MlString({"___": "maxchildren"}),
|
||||
'class_id': MlString({"___": "class_id", "eng": "class identifier", "fre": "identifiant de la classe"}),
|
||||
'type_id': MlString({"___": "type_id", "eng": "type identifier", "fre": "identifiant de la type"}),
|
||||
'lodel_id': MlString({"___": "lodel_id", "eng": "lodel identifier", "fre": "identifiant lodel"}),
|
||||
'modification_date': MlString({"___": "modification_date", "eng": "Modification date", "fre": "Date de modification"}),
|
||||
'automatic': MlString({"___": "automatic"}),
|
||||
'string': MlString({"___": "string", "eng": "String representation", "fre": "Repr\u00e9sentation textuel"}),
|
||||
'creation_date': MlString({"___": "creation_date", "eng": "Creation date", "fre": "Date de cr\u00e9ation"}),
|
||||
'attach': MlString({"___": "attach"}),
|
||||
'maxdepth': MlString({"___": "maxdepth"})
|
||||
}
|
||||
_Hierarchy._linked_types = {
|
||||
}
|
||||
_Hierarchy._classtype = 'entity'
|
||||
|
||||
#Initialisation of Emcomponent class attributes
|
||||
Emcomponent._fieldtypes = {
|
||||
'fieldtype': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'name': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': False, 'max_length': 56, 'uniq': False, 'nullable': False}),
|
||||
'string': EditorialModel.fieldtypes.char.EmFieldType(**{'internal': 'automatic', 'max_length': 128, 'immutable': False, 'uniq': False, 'nullable': True}),
|
||||
'help_text': EditorialModel.fieldtypes.i18n.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'fieldtype_options': EditorialModel.fieldtypes.dictionary.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'date_update': EditorialModel.fieldtypes.datetime.EmFieldType(**{'now_on_update': True, 'nullable': False, 'uniq': False, 'internal': False}),
|
||||
'date_create': EditorialModel.fieldtypes.datetime.EmFieldType(**{'now_on_create': True, 'internal': False, 'uniq': False, 'nullable': False}),
|
||||
'rank': EditorialModel.fieldtypes.integer.EmFieldType(**{'internal': False, 'uniq': False, 'nullable': False})
|
||||
}
|
||||
Emcomponent.ml_fields_strings = {
|
||||
'superiors': MlString({"___": "superiors"}),
|
||||
'creation_date': MlString({"___": "creation_date", "eng": "Creation date", "fre": "Date de cr\u00e9ation"}),
|
||||
'name': MlString({"___": "name"}),
|
||||
'lodel_id': MlString({"___": "lodel_id", "eng": "lodel identifier", "fre": "identifiant lodel"}),
|
||||
'modification_date': MlString({"___": "modification_date", "eng": "Modification date", "fre": "Date de modification"}),
|
||||
'parent_class': MlString({"___": "parent_class"}),
|
||||
'fieldtype_options': MlString({"___": "fieldtype_options"}),
|
||||
'help_text': MlString({"___": "help_text"}),
|
||||
'rank': MlString({"___": "rank"}),
|
||||
'sort_column': MlString({"___": "sort_column"}),
|
||||
'fieldtype': MlString({"___": "fieldtype"}),
|
||||
'class_id': MlString({"___": "class_id", "eng": "class identifier", "fre": "identifiant de la classe"}),
|
||||
'selected_field': MlString({"___": "selected_field"}),
|
||||
'rel_field': MlString({"___": "rel_field"}),
|
||||
'string': MlString({"___": "string", "eng": "String representation", "fre": "Repr\u00e9sentation textuel"}),
|
||||
'type_id': MlString({"___": "type_id", "eng": "type identifier", "fre": "identifiant de la type"}),
|
||||
'classtype': MlString({"___": "classtype"}),
|
||||
'date_create': MlString({"___": "date_create"}),
|
||||
'nature': MlString({"___": "nature"}),
|
||||
'date_update': MlString({"___": "date_update"})
|
||||
}
|
||||
Emcomponent._linked_types = {
|
||||
'superiors': Emtype,
|
||||
'rel_field': Emfield,
|
||||
'classtype': Classtype,
|
||||
'parent_class': Emclass,
|
||||
'sort_column': Emfield,
|
||||
'selected_field': Emfield
|
||||
}
|
||||
Emcomponent._classtype = 'entity'
|
||||
|
||||
#Initialisation of Classtype class attributes
|
||||
Classtype._fields = ['name']
|
||||
Classtype._superiors = {}
|
||||
Classtype._leclass = _Classtype
|
||||
|
||||
#Initialisation of Hierarchyoptions class attributes
|
||||
Hierarchyoptions._fields = ['attach', 'automatic', 'maxdepth', 'maxchildren']
|
||||
Hierarchyoptions._superiors = {}
|
||||
Hierarchyoptions._leclass = _Hierarchy
|
||||
|
||||
#Initialisation of Editorialmodel class attributes
|
||||
Editorialmodel._fields = ['name', 'description']
|
||||
Editorialmodel._superiors = {}
|
||||
Editorialmodel._leclass = _Editorialmodel
|
||||
|
||||
#Initialisation of Emclass class attributes
|
||||
Emclass._fields = ['name', 'help_text', 'date_update', 'date_create', 'rank']
|
||||
Emclass._superiors = {'parent': [Editorialmodel]}
|
||||
Emclass._leclass = Emcomponent
|
||||
|
||||
#Initialisation of Emtype class attributes
|
||||
Emtype._fields = ['name', 'help_text', 'date_update', 'date_create', 'rank']
|
||||
Emtype._superiors = {'parent': [Emclass]}
|
||||
Emtype._leclass = Emcomponent
|
||||
|
||||
#Initialisation of Emfield class attributes
|
||||
Emfield._fields = ['name', 'help_text', 'date_update', 'date_create', 'rank', 'fieldtype', 'fieldtype_options']
|
||||
Emfield._superiors = {'parent': [Emtype]}
|
||||
Emfield._leclass = Emcomponent
|
||||
|
||||
## @brief Dict for getting LeClass and LeType child classes given an EM uid
|
||||
LeObject._me_uid = {32: Emclass, 1: _Editorialmodel, 34: Emfield, 22: Emcomponent, 33: Emtype, 8: _Classtype, 31: Editorialmodel, 29: Classtype, 30: Hierarchyoptions, 15: _Hierarchy}
|
||||
1022
em_editor/em.json
Normal file
1022
em_editor/em.json
Normal file
File diff suppressed because it is too large
Load diff
32
em_editor/em_editor.py
Normal file
32
em_editor/em_editor.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
from loader import *
|
||||
|
||||
import os, os.path, code
|
||||
|
||||
from EditorialModel.model import Model
|
||||
from EditorialModel.backend.json_backend import EmBackendJson
|
||||
from EditorialModel.classes import EmClass
|
||||
from EditorialModel.types import EmType
|
||||
from EditorialModel.fields import EmField
|
||||
from EditorialModel.classtypes import *
|
||||
|
||||
emfile = input("Enter em path please : ")
|
||||
|
||||
if not os.path.isfile(emfile):
|
||||
with open(emfile,'w+') as fd:
|
||||
fd.write('{}')
|
||||
|
||||
em = Model(EmBackendJson(emfile))
|
||||
|
||||
print("Editorial model loaded in em variable : ")
|
||||
for comptype in [ 'EmClass', 'EmType', 'EmField' ]:
|
||||
print("\t* %s :" % comptype)
|
||||
complist = em.components(comptype)
|
||||
if len(complist) == 0:
|
||||
print("\t\tEMPTY")
|
||||
for comp in complist:
|
||||
print("\t\t- %s" % comp.name)
|
||||
|
||||
|
||||
code.interact(local=locals())
|
||||
|
||||
112
em_editor/init_em.py
Normal file
112
em_editor/init_em.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
from loader import *
|
||||
|
||||
import os, os.path, code
|
||||
|
||||
from EditorialModel.model import Model
|
||||
from EditorialModel.backend.json_backend import EmBackendJson
|
||||
from EditorialModel.classes import EmClass
|
||||
from EditorialModel.types import EmType
|
||||
from EditorialModel.fields import EmField
|
||||
from EditorialModel.classtypes import *
|
||||
from EditorialModel.fieldtypes.generic import GenericFieldType
|
||||
|
||||
|
||||
emfile = 'em.json'
|
||||
|
||||
if not os.path.isfile(emfile):
|
||||
with open(emfile,'w+') as fd:
|
||||
fd.write('{}')
|
||||
|
||||
em = Model(EmBackendJson(emfile))
|
||||
|
||||
|
||||
#GenericFieldType.from_name()
|
||||
|
||||
def ft(name):
|
||||
return GenericFieldType.from_name()
|
||||
|
||||
|
||||
class_em = em.add_class('_EditorialModel', classtype = 'entity')
|
||||
class_ctype = em.add_class('_ClassType', classtype='entity')
|
||||
class_ctype_h = em.add_class('_Hierarchy', classtype='entity')
|
||||
class_comp = em.add_class('EmComponent', classtype='entity')
|
||||
# class_ftype = em.add_class('_FieldType', classtype = 'entity')
|
||||
|
||||
# type_ftype = em.add_type('FieldType', class_ftype)
|
||||
type_ctype = em.add_type('ClassType', class_ctype)
|
||||
type_ctype_h = em.add_type('HierarchyOptions', class_ctype_h)
|
||||
type_em = em.add_type('EditorialModel', class_em)
|
||||
|
||||
type_class = em.add_type('EmClass', class_comp, superiors_list = {'parent': [type_em.uid]})
|
||||
type_type = em.add_type('EmType', class_comp, superiors_list = {'parent':[type_class.uid]})
|
||||
type_field = em.add_type('EmField', class_comp, superiors_list = {'parent':[type_type.uid]})
|
||||
|
||||
# FieldType common fields
|
||||
# em.add_field('name', class_ftype, fieldtype = 'char', max_length = 56)
|
||||
# em.add_field('max_length', class_ftype, optional = True, fieldtype = 'integer')
|
||||
|
||||
# EditorialModel common fields
|
||||
em.add_field('name', class_em, fieldtype = 'char', max_length = 56)
|
||||
em.add_field('description', class_em, fieldtype = 'char', max_length = 4096)
|
||||
|
||||
# Hierarchy options common fields
|
||||
em.add_field('attach', class_ctype_h, fieldtype = 'char', max_length = 10)
|
||||
em.add_field('automatic', class_ctype_h, fieldtype = 'bool')
|
||||
em.add_field('maxdepth', class_ctype_h, fieldtype = 'integer')
|
||||
em.add_field('maxchildren', class_ctype_h, fieldtype = 'integer')
|
||||
|
||||
# ClassType common fields
|
||||
em.add_field('name', class_ctype, fieldtype = 'char', max_length = 56)
|
||||
field_hspec = em.add_field('hierarchy_specs', class_ctype, fieldtype = 'rel2type', rel_to_type_id = type_ctype_h)
|
||||
em.add_field('nature', class_ctype, fieldtype = 'char', max_length = 10, rel_field_id = field_hspec.uid)
|
||||
|
||||
# EmComponent common fields
|
||||
em.add_field('name', class_comp, fieldtype = 'char', max_length = 56)
|
||||
# Part of default fields #em.add_field('string', class_comp, fieldtype = 'i18n')
|
||||
em.add_field('help_text', class_comp, fieldtype = 'i18n')
|
||||
em.add_field('date_update', class_comp, fieldtype = 'datetime', now_on_update = True)
|
||||
em.add_field('date_create', class_comp, fieldtype = 'datetime', now_on_create = True)
|
||||
em.add_field('rank', class_comp, fieldtype = 'integer')
|
||||
# EmComponent optional fields
|
||||
field_ctype = em.add_field('classtype', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_ctype.uid)
|
||||
field_sortcol = em.add_field('sort_column', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_field.uid)
|
||||
|
||||
field_pclass = em.add_field('parent_class', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_class.uid)
|
||||
field_selfield = em.add_field('selected_field', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_field.uid)
|
||||
field_superior = em.add_field('superiors', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_type.uid)
|
||||
field_nature = em.add_field('nature', class_comp, optional = True, fieldtype = 'char', max_length = 10, rel_field_id = field_superior.uid)
|
||||
|
||||
# field_ftype = em.add_field('fieldtype', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_ftype)
|
||||
field_ftype = em.add_field('fieldtype', class_comp, optional = True, fieldtype = 'char')
|
||||
field_ftypeopt = em.add_field('fieldtype_options', class_comp, optional = True, fieldtype = 'dictionary')
|
||||
field_relfield = em.add_field('rel_field', class_comp, optional = True, fieldtype = 'rel2type', rel_to_type_id = type_field)
|
||||
|
||||
# EmClass field selection
|
||||
type_class.select_field(field_ctype)
|
||||
type_class.select_field(field_sortcol)
|
||||
# EmType field selection
|
||||
type_type.select_field(field_sortcol)
|
||||
type_type.select_field(field_pclass)
|
||||
type_type.select_field(field_selfield)
|
||||
type_type.select_field(field_superior)
|
||||
type_type.select_field(field_nature)
|
||||
# EmField field selection
|
||||
type_field.select_field(field_ftype)
|
||||
type_field.select_field(field_relfield)
|
||||
type_field.select_field(field_ftypeopt)
|
||||
em.save()
|
||||
|
||||
"""
|
||||
print("Editorial model loaded in em variable : ")
|
||||
for comptype in [ 'EmClass', 'EmType', 'EmField' ]:
|
||||
print("\t* %s :" % comptype)
|
||||
complist = em.components(comptype)
|
||||
if len(complist) == 0:
|
||||
print("\t\tEMPTY")
|
||||
for comp in complist:
|
||||
print("\t\t- %s" % comp.name)
|
||||
|
||||
|
||||
code.interact(local=locals())
|
||||
"""
|
||||
26
em_editor/instance_settings.py
Normal file
26
em_editor/instance_settings.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#-*- coding:utf8 -*-
|
||||
|
||||
import pymysql
|
||||
import os
|
||||
|
||||
sitename = 'em_editor'
|
||||
lodel2_lib_path = '/home/yannweb/dev/lodel2/lodel2-git'
|
||||
|
||||
templates_base_dir = 'LODEL2_INSTANCE_TEMPLATES_BASE_DIR'
|
||||
|
||||
debug = False
|
||||
|
||||
em_file = 'em.json'
|
||||
dynamic_code_file = 'dynleapi.py'
|
||||
|
||||
ds_package = 'MySQL'
|
||||
mh_classname = 'MysqlMigrationHandler'
|
||||
datasource = {
|
||||
'default': {
|
||||
'module': pymysql,
|
||||
'host': '127.0.0.1',
|
||||
'user': 'lodel',
|
||||
'passwd': 'bruno',
|
||||
'db': 'lodel2tests'
|
||||
}
|
||||
}
|
||||
38
em_editor/loader.py
Normal file
38
em_editor/loader.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import instance_settings
|
||||
import importlib
|
||||
import sys
|
||||
import os
|
||||
|
||||
sys.path.append(instance_settings.lodel2_lib_path)
|
||||
|
||||
from Lodel.settings import Settings
|
||||
|
||||
# Settings initialisation
|
||||
Settings.load_module(instance_settings)
|
||||
globals()['Settings'] = Settings
|
||||
|
||||
from Lodel import logger # logger import and initialisation
|
||||
|
||||
from plugins import * #Load activated plugins
|
||||
|
||||
# Import dynamic code
|
||||
if os.path.isfile(Settings.dynamic_code_file):
|
||||
from dynleapi import *
|
||||
|
||||
# Import wanted datasource objects
|
||||
for db_modname in ['leapidatasource', 'migrationhandler']:
|
||||
mod = importlib.import_module("DataSource.{pkg_name}.{mod_name}".format(
|
||||
pkg_name=Settings.get('ds_package'),
|
||||
mod_name=db_modname,
|
||||
)
|
||||
)
|
||||
# Expose the module in globals
|
||||
globals()[db_modname] = mod
|
||||
|
||||
if __name__ == '__main__':
|
||||
import code
|
||||
print("""
|
||||
Running interactive python in Lodel2 %s instance environment
|
||||
|
||||
"""%Settings.sitename)
|
||||
code.interact(local=locals())
|
||||
64
em_editor/manage_lodel.py
Normal file
64
em_editor/manage_lodel.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
try:
|
||||
from loader import *
|
||||
except ImportError: pass
|
||||
|
||||
from plugins import *
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'--list-hooks',
|
||||
action='store_const',
|
||||
const=True,
|
||||
default=False,
|
||||
help='Display the list of registered hooks'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--list-plugins',
|
||||
action='store_const',
|
||||
const=True,
|
||||
default=False,
|
||||
help='Display the list of plugins'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--plugin',
|
||||
action='store',
|
||||
type=str,
|
||||
metavar='PLUGIN_NAME',
|
||||
nargs='+',
|
||||
help='Filter on plugins name'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--hookname',
|
||||
action='store',
|
||||
type=str,
|
||||
metavar='HOOK_NAME',
|
||||
nargs='+',
|
||||
help='Filter on hook name'
|
||||
)
|
||||
kwargs = parser.parse_args()
|
||||
|
||||
# Listing registered hooks
|
||||
if kwargs.list_hooks:
|
||||
import Lodel.plugins
|
||||
list_args = {}
|
||||
if kwargs.plugin is not None and len(kwargs.plugin) > 0:
|
||||
list_args['plugins'] = kwargs.plugin
|
||||
if kwargs.hookname is not None and len(kwargs.hookname) > 0:
|
||||
list_args['names'] = kwargs.hookname
|
||||
|
||||
print(Lodel.plugins.list_hooks(**list_args))
|
||||
exit(0)
|
||||
# Listing plugins
|
||||
elif kwargs.list_plugins:
|
||||
import Lodel.plugins
|
||||
print(Lodel.plugins.list_plugins())
|
||||
exit(0)
|
||||
|
||||
parser.print_help()
|
||||
exit(1)
|
||||
88
em_editor/netipy.py
Normal file
88
em_editor/netipy.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#!/usr/bin/python3
|
||||
#-*- coding: utf-8 -*-
|
||||
|
||||
#
|
||||
# A server that provide access to interactive python interpreter through network
|
||||
#
|
||||
# This is a demo implementation of a Lodel2 interface
|
||||
|
||||
import socket
|
||||
import threading
|
||||
import subprocess
|
||||
import time
|
||||
import sys
|
||||
import signal
|
||||
|
||||
PORT = 1337
|
||||
#BIND = None
|
||||
BIND = 'localhost'
|
||||
THREAD_COUNT = 10
|
||||
SOCK_TIMEOUT = 5
|
||||
|
||||
servsock = None # Stores the server socket in order to close it when exception is raised
|
||||
|
||||
|
||||
# Thread function called when client connected
|
||||
def client_thread(sock, addr):
|
||||
# Starting interactive Lodel2 python in a subprocess
|
||||
sock.setblocking(True)
|
||||
sock_stdin = sock.makefile(mode='r', encoding='utf-8', newline="\n")
|
||||
sock_stdout = sock.makefile(mode='w', encoding='utf-8', newline="\n")
|
||||
|
||||
ipy = subprocess.Popen(['python', 'netipy_loader.py', addr[0]], stdin=sock_stdin, stdout=sock_stdout, stderr=sock_stdout)
|
||||
ipy.wait()
|
||||
sock.close()
|
||||
return True
|
||||
|
||||
# Main loop
|
||||
def main():
|
||||
servsock = socket.socket(family = socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
servsock.settimeout(5)
|
||||
bind_addr = socket.gethostname() if BIND is None else BIND
|
||||
servsock.bind((bind_addr, PORT))
|
||||
servsock.listen(5)
|
||||
globals()['servsock'] = servsock
|
||||
|
||||
threads = list()
|
||||
|
||||
print("Server listening on %s:%s" % (bind_addr, PORT))
|
||||
while True:
|
||||
# Accept if rooms left in threads list
|
||||
if len(threads) < THREAD_COUNT:
|
||||
try:
|
||||
(clientsocket, addr) = servsock.accept()
|
||||
print("Client connected : %s" % addr[0])
|
||||
thread = threading.Thread(target = client_thread, kwargs = {'sock': clientsocket, 'addr': addr})
|
||||
threads.append(thread)
|
||||
thread.start()
|
||||
except socket.timeout:
|
||||
pass
|
||||
|
||||
# Thread cleanup
|
||||
for i in range(len(threads)-1,-1,-1):
|
||||
thread = threads[i]
|
||||
thread.join(0.1) #useless ?
|
||||
if not thread.is_alive():
|
||||
print("Thread %d exited" % i)
|
||||
threads.pop(i)
|
||||
|
||||
# Signal handler designed to close socket when SIGINT
|
||||
def sigint_sock_close(signal, frame):
|
||||
if globals()['servsock'] is not None:
|
||||
globals()['servsock'].close()
|
||||
print("\nCtrl+c pressed, exiting...")
|
||||
exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
signal.signal(signal.SIGINT, sigint_sock_close)
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
if globals()['servsock'] is not None:
|
||||
globals()['servsock'].close()
|
||||
raise e
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
22
em_editor/netipy_loader.py
Normal file
22
em_editor/netipy_loader.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#-*- coding: utf-8 -*-
|
||||
|
||||
import sys
|
||||
import code
|
||||
from loader import *
|
||||
from Lodel import logger
|
||||
from Lodel.user import UserContext
|
||||
|
||||
|
||||
logger.remove_console_handlers()
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) < 2:
|
||||
raise RuntimeError("Usage : %s client_ip")
|
||||
UserContext.init(sys.argv[1])
|
||||
print("""
|
||||
netipy interface of Lodel2 %s instance environment.
|
||||
|
||||
Welcome %s.
|
||||
To authenticate use UserContext.authenticate(identifier, proof) function
|
||||
""" % (Settings.sitename, UserContext.identity().username))
|
||||
code.interact(local=locals())
|
||||
1
em_editor/templates/base.html
Normal file
1
em_editor/templates/base.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
{% extends "templates/base.html" %}
|
||||
1
em_editor/templates/base_backend.html
Normal file
1
em_editor/templates/base_backend.html
Normal file
|
|
@ -0,0 +1 @@
|
|||
{% extends "templates/base_backend.html" %}
|
||||
91
em_editor/utils.py
Executable file
91
em_editor/utils.py
Executable file
|
|
@ -0,0 +1,91 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from loader import *
|
||||
import warnings
|
||||
|
||||
|
||||
def refreshdyn():
|
||||
import sys
|
||||
from EditorialModel.model import Model
|
||||
from leapi.lefactory import LeFactory
|
||||
from EditorialModel.backend.json_backend import EmBackendJson
|
||||
from DataSource.MySQL.leapidatasource import LeDataSourceSQL
|
||||
OUTPUT = Settings.dynamic_code_file
|
||||
EMJSON = Settings.em_file
|
||||
# Load editorial model
|
||||
em = Model(EmBackendJson(EMJSON))
|
||||
# Generate dynamic code
|
||||
fact = LeFactory(OUTPUT)
|
||||
# Create the python file
|
||||
fact.create_pyfile(em, LeDataSourceSQL, {})
|
||||
|
||||
|
||||
def db_init():
|
||||
from EditorialModel.backend.json_backend import EmBackendJson
|
||||
from EditorialModel.model import Model
|
||||
mh = getattr(migrationhandler,Settings.mh_classname)()
|
||||
em = Model(EmBackendJson(Settings.em_file))
|
||||
em.migrate_handler(mh)
|
||||
|
||||
|
||||
def em_graph(output_file = None, image_format = None):
|
||||
from EditorialModel.model import Model
|
||||
from EditorialModel.backend.json_backend import EmBackendJson
|
||||
from EditorialModel.backend.graphviz import EmBackendGraphviz
|
||||
import subprocess
|
||||
|
||||
if image_format is None:
|
||||
if hasattr(Settings, 'em_graph_format'):
|
||||
image_format = Settings.em_graph_format
|
||||
else:
|
||||
image_format = 'png'
|
||||
if output_file is None:
|
||||
if hasattr(Settings, 'em_graph_output'):
|
||||
output_file = Settings.em_graph_output
|
||||
else:
|
||||
output_file = '/tmp/em_%s_graph.dot'
|
||||
image_format = image_format.lower()
|
||||
try:
|
||||
output_file = output_file%Settings.sitename
|
||||
except TypeError:
|
||||
warnings.warn("Bad filename for em_graph output. The filename should be in the form '/foo/bar/file_%s_name.png")
|
||||
pass
|
||||
|
||||
dot_file = output_file+".dot"
|
||||
|
||||
graphviz_bckend = EmBackendGraphviz(dot_file)
|
||||
edmod = Model(EmBackendJson(Settings.em_file))
|
||||
graphviz_bckend.save(edmod)
|
||||
dot_cmd = [
|
||||
"dot",
|
||||
"-T%s"%image_format,
|
||||
dot_file
|
||||
]
|
||||
with open(output_file, "w+") as outfp:
|
||||
subprocess.check_call(dot_cmd, stdout=outfp)
|
||||
os.unlink(dot_file)
|
||||
print("Output image written in file : '%s'" % output_file)
|
||||
|
||||
|
||||
def dir_init():
|
||||
import os
|
||||
|
||||
# Templates
|
||||
print("Creating Base Templates ...")
|
||||
templates = {
|
||||
'base': {'file': 'base.html', 'content': '{% extends "templates/base.html" %}'},
|
||||
'base_backend': {'file': 'base_backend.html', 'content': '{% extends "templates/base_backend.html" %}'}
|
||||
}
|
||||
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
templates_directory = os.path.join(current_directory,'templates')
|
||||
if not os.path.exists(templates_directory):
|
||||
os.makedirs(templates_directory)
|
||||
|
||||
for _, template in templates.items():
|
||||
my_file_path = os.path.join(templates_directory, template['file'])
|
||||
if os.path.exists(my_file_path):
|
||||
os.unlink(my_file_path)
|
||||
with open(my_file_path, 'w') as my_file:
|
||||
my_file.write(template['content'])
|
||||
print("Created %s" % my_file_path)
|
||||
Loading…
Add table
Add a link
Reference in a new issue