1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-11-21 13:19:16 +01:00
lodel2_mirror/leobject/lefactory.py
2015-10-22 11:25:23 +02:00

193 lines
7.1 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#-*- coding: utf-8 -*-
import importlib
import EditorialModel
from EditorialModel.model import Model
from EditorialModel.fieldtypes.generic import GenericFieldType
## @brief This class is designed to generated the leobject API given an EditorialModel.model
# @note Contains only static methods
#
# The name is not good but i've no other ideas for the moment
class LeFactory(object):
output_file = 'dyn.py'
def __init__(LeFactory):raise NotImplementedError("Not designed (yet?) to be implemented")
## @brief Return a LeObject child class given its name
# @return a python class or False
@staticmethod
def leobj_from_name(name):
mod = importlib.import_module('leobject.'+LeFactory.output_file.split('.')[-1])
try:
res = getattr(mod, name)
except AttributeError:
return False
return res
## @brief Convert an EmType or EmClass name in a python class name
# @param name str : The name
# @return name.title()
@staticmethod
def name2classname(name):
if not isinstance(name, str):
raise AttributeError("Argument name should be a str and not a %s"%type(name))
return name.title()
## @brief Return a call to a FieldType constructor given an EmField
# @param emfield EmField : An EmField
# @return a string representing the python code to instanciate a EmFieldType
@staticmethod
def fieldtype_construct_from_field(emfield):
return '%s.EmFieldType(**%s)'%(
GenericFieldType.module_name(emfield.fieldtype),
repr(emfield._fieldtype_args),
)
## @brief Given a Model and an EmClass instances generate python code for corresponding LeClass
# @param model Model : A Model instance
# @param emclass EmClass : An EmClass instance from model
# @return A string representing the python code for the corresponding LeClass child class
@staticmethod
def emclass_pycode(model, emclass):
cls_fields = dict()
cls_linked_types = list()
for field in emclass.fields():
cls_fields[field.name] = LeFactory.fieldtype_construct_from_field(field)
fti = field.fieldtype_instance()
if fti.name == 'rel2type':
#relationnal field/fieldtype
cls_linked_types.append(LeFactory.name2classname(model.component(fti.rel_to_type_id).name))
cls_fieldgroup = dict()
for fieldgroup in emclass.fieldgroups():
cls_fieldgroup[fieldgroup.name] = list()
for field in fieldgroup.fields():
cls_fieldgroup[fieldgroup.name].append(field.name)
return """
#Initialisation of {name} class attributes
{name}._fieldtypes = {ftypes}
{name}._linked_types = {ltypes}
{name}._fieldgroups = {fgroups}
""".format(
name = LeFactory.name2classname(emclass.name),
ftypes = "{"+(','.join([ '\n\t%s:%s'%(repr(f),v) for f,v in cls_fields.items()]))+"\n}",
ltypes = "{"+(','.join(cls_linked_types))+'}',
fgroups = repr(cls_fieldgroup)
)
## @brief Given a Model and an EmType instances generate python code for corresponding LeType
# @param model Model : A Model instance
# @param emtype EmType : An EmType instance from model
# @return A string representing the python code for the corresponding LeType child class
@staticmethod
def emtype_pycode(model, emtype):
type_fields = list()
type_superiors = list()
for field in emtype.fields():
type_fields.append(field.name)
for nat, sup_l in emtype.superiors().items():
type_superiors.append('%s:[%s]'%(
repr(nat),
','.join([ LeFactory.name2classname(sup.name) for sup in sup_l])
))
return """
#Initialisation of {name} class attributes
{name}._fields = {fields}
{name}._superiors = {dsups}
{name}._leclass = {leclass}
""".format(
name = LeFactory.name2classname(emtype.name),
fields = repr(type_fields),
dsups = '{'+(','.join(type_superiors))+'}',
leclass = LeFactory.name2classname(emtype.em_class.name)
)
## @brief Generate python code containing the LeObject API
# @param backend_cls Backend : A model backend class
# @param backend_args dict : A dict representing arguments for backend_cls instanciation
# @param datasource_cls Datasource : A datasource class
# @param datasource_args dict : A dict representing arguments for datasource_cls instanciation
# @return A string representing python code
@staticmethod
def generate_python(backend_cls, backend_args, datasource_cls, datasource_args):
model = Model(backend=backend_cls(**backend_args))
result = ""
#result += "#-*- coding: utf-8 -*-\n"
#Putting import directives in result
result += """
from EditorialModel.model import Model
from leobject.leobject import _LeObject
from leobject.leclass import LeClass
from leobject.letype import LeType
import EditorialModel.fieldtypes
"""
result += """
import %s
import %s
"""%(backend_cls.__module__, datasource_cls.__module__)
#Generating the code for LeObject class
backend_constructor = '%s.%s(**%s)'%(backend_cls.__module__, backend_cls.__name__, repr(backend_args))
leobj_me_uid = dict()
for comp in model.components('EmType') + model.components('EmClass'):
leobj_me_uid[comp.uid] = LeFactory.name2classname(comp.name)
result += """
## @brief _LeObject concret clas
# @see leobject::leobject::_LeObject
class LeObject(_LeObject):
_model = Model(backend=%s)
_datasource = %s(**%s)
_me_uid = %s
"""%(backend_constructor, datasource_cls.__module__+'.'+datasource_cls.__name__, repr(datasource_args), repr(leobj_me_uid))
emclass_l = model.components(EditorialModel.classes.EmClass)
emtype_l = model.components(EditorialModel.types.EmType)
#LeClass child classes definition
for emclass in emclass_l:
result += """
## @brief EmClass {name} LeClass child class
# @see leobject::leclass::LeClass
class {name}(LeObject,LeClass):
_class_id = {uid}
""".format(
name = LeFactory.name2classname(emclass.name),
uid = emclass.uid
)
#LeType child classes definition
for emtype in emtype_l:
result += """
## @brief EmType {name} LeType child class
# @see leobject::letype::LeType
class {name}({leclass},LeType):
_type_id = {uid}
""".format(
name = LeFactory.name2classname(emtype.name),
leclass = LeFactory.name2classname(emtype.em_class.name),
uid = emtype.uid
)
#Set attributes of created LeClass and LeType child classes
for emclass in emclass_l:
result += LeFactory.emclass_pycode(model, emclass)
for emtype in emtype_l:
result += LeFactory.emtype_pycode(model, emtype)
#Populating LeObject._me_uid dict for a rapid fetch of LeType and LeClass given an EM uid
result += """
## @brief Dict for getting LeClass and LeType child classes given an EM uid
LeObject._me_uid = %s
"""%repr({ comp.uid:LeFactory.name2classname(comp.name) for comp in emclass_l + emtype_l })
return result