From 589d7f2eefcf4d65585f1970089758b88b9486b1 Mon Sep 17 00:00:00 2001 From: Yann Date: Wed, 21 Oct 2015 09:47:30 +0200 Subject: [PATCH] Changed the way LeFactory generates python code Added a test on LeFactory generated code --- leobject/lefactory.py | 166 ++++++++++++++++++--------------- leobject/letype.py | 6 +- leobject/test/test_leobject.py | 1 - 3 files changed, 94 insertions(+), 79 deletions(-) diff --git a/leobject/lefactory.py b/leobject/lefactory.py index ae5f0ad..a653e5e 100644 --- a/leobject/lefactory.py +++ b/leobject/lefactory.py @@ -40,10 +40,68 @@ class LeFactory(object): def fieldtype_construct_from_field(emfield): return '%s.EmFieldType(**%s)'%( GenericFieldType.module_name(emfield.fieldtype), - emfield._fieldtype_args.__repr__(), + 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 """ +{name}._fildtypes = {ftypes} +{name}._linked_types = {ltypes} +{name}._fieldgroups = {fgroups} +""".format( + name = LeFactory.name2classname(emclass.name), + ftypes = repr(cls_fields), + 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 """ +{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 model_args dict : Dict of Model __init__ method arguments # @param datasource_args dict : Dict of datasource __init__ method arguments @@ -53,89 +111,47 @@ class LeFactory(object): model = Model(backend=backend_cls(**backend_args)) result = "" - result += "#-*- coding: utf-8 -*-\n" + #result += "#-*- coding: utf-8 -*-\n" #Putting import directives in result - result += "\n\n\ -from EditorialModel.model import Model\n\ -from leobject.leobject import _LeObject\n\ -from leobject.leclass import LeClass\n\ -from leobject.letype import LeType\n\ -import EditorialModel.fieldtypes\n\ -" + result += """ - result += "\n\ -import %s\n\ -import %s\n\ -"%(backend_cls.__module__, datasource_cls.__module__) +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__, backend_args.__repr__()) + 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 += "\n\ -class LeObject(_LeObject):\n\ - _model = Model(backend=%s)\n\ - _datasource = %s(**%s)\n\ - _me_uid = %s\n\ -\n\ -"%(backend_constructor, datasource_cls.__name__, datasource_args.__repr__(), leobj_me_uid.__repr__()) + result += """ +class LeObject(_LeObject): + _model = Model(backend=%s) + _datasource = %s(**%s) + _me_uid = %s + +"""%(backend_constructor, datasource_cls.__name__, repr(datasource_args), repr(leobj_me_uid)) + #LeClass and LeType child classes definition for emclass in model.components(EditorialModel.classes.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) - - result += "\n\ -class %s(LeObject, LeClass):\n\ - _fieldtypes = %s\n\ - _linked_types = [%s]\n\ - _fieldgroups = %s\n\ -\n\ -"%( - LeFactory.name2classname(emclass.name), - cls_fields.__repr__(), - ','.join(cls_linked_types), - cls_fieldgroup.__repr__() -) - + result += 'class %s(LeObject,LeType): pass\n'%(LeFactory.name2classname(emclass.name)) for emtype in model.components(EditorialModel.types.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]'%( - nat.__repr__(), - ','.join([ LeFactory.name2classname(sup.name) for sup in sup_l]) - )) - - - result += "\n\ -class %s(%s,LeType):\n\ - _fields = %s\n\ - _superiors = {%s}\n\ - _leClass = %s\n\ -\n\ -"%( - LeFactory.name2classname(emtype.name), - LeFactory.name2classname(emtype.em_class.name), - type_fields.__repr__(), - ','.join(type_superiors), - LeFactory.name2classname(emtype.em_class.name) -) - + result += 'class %s(%s,LeType): pass\n'%(LeFactory.name2classname(emtype.name),LeFactory.name2classname(emtype.em_class.name),) + + #Set attributes of created LeClass and LeType child classes + for emclass in model.components(EditorialModel.classes.EmClass): + result += LeFactory.emclass_pycode(model, emclass) + for emtype in model.components(EditorialModel.types.EmType): + result += LeFactory.emtype_pycode(model, emtype) + return result diff --git a/leobject/letype.py b/leobject/letype.py index b4926e3..c7fdd5d 100644 --- a/leobject/letype.py +++ b/leobject/letype.py @@ -26,7 +26,7 @@ class LeType(object): ## Populate the object from the datas received in kwargs for name, value in kwargs.items(): if name not in self._fields: - raise AttributeError("No such field '%s' for %s"%(name, self.__class__.__name__) + raise AttributeError("No such field '%s' for %s"%(name, self.__class__.__name__)) setattr(self, name, value) ## @brief Delete the LeType from Db @@ -77,9 +77,9 @@ class LeType(object): autom_fields = [f.name for f in cls._fieldtypes if f.internal] for dname, dval in datas.items(): if dname in autom_fields: - raise AttributeError("The field '%s' is internal"%(dname) + raise AttributeError("The field '%s' is internal"%(dname)) if dname not in cls._fields: - raise AttributeError("No such field '%s' for %s"%(dname, self.__class__.__name__) + raise AttributeError("No such field '%s' for %s"%(dname, self.__class__.__name__)) cls._fieldtypess[dname].check_or_raise(dval) fields = [f.name for f in cls._fieldtypes if not f.internal] diff --git a/leobject/test/test_leobject.py b/leobject/test/test_leobject.py index 771876d..3016f90 100644 --- a/leobject/test/test_leobject.py +++ b/leobject/test/test_leobject.py @@ -2,7 +2,6 @@ Tests for _LeObject """ -import os import unittest from unittest import TestCase