1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-01-05 15:12:13 +01:00

Fixing the code because of DataSources changes

This commit is contained in:
Yann 2016-02-25 14:33:26 +01:00
commit 14b5bd0fdb
15 changed files with 72 additions and 54 deletions

View file

@ -57,9 +57,10 @@ class EmField(EmComponent):
self._fieldtype_args = kwargs
self._fieldtype_args.update({'nullable': nullable, 'uniq': uniq, 'internal': self.internal})
self.set_fieldtype_options(**self._fieldtype_args)
fieldtype_instance = self._fieldtype_cls(**self._fieldtype_args)
if 'default' in kwargs:
if not fieldtype_instance.check(default):
if not fieldtype_instance.check_data_value(kwargs['default']):
raise TypeError("Default value ('%s') is not valid given the fieldtype '%s'" % (default, fieldtype))
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)

View file

@ -4,7 +4,7 @@
# Contains the class managing and editorial model
import EditorialModel
from DataSource.dummy.migrationhandler import DummyMigrationHandler
from DataSource.dummy.migrationhandler import MigrationHandler
from EditorialModel.backend.dummy_backend import EmBackendDummy
from EditorialModel.classes import EmClass
from EditorialModel.fields import EmField
@ -24,8 +24,8 @@ class Model(object):
# @param migration_handler : A migration handler
def __init__(self, backend, migration_handler=None):
if migration_handler is None:
self.migration_handler = DummyMigrationHandler()
elif issubclass(migration_handler.__class__, DummyMigrationHandler):
self.migration_handler = MigrationHandler()
elif issubclass(migration_handler.__class__, MigrationHandler):
self.migration_handler = migration_handler
else:
raise TypeError("migration_handler should be an instance from a subclass of DummyMigrationhandler")

View file

@ -15,7 +15,7 @@ from EditorialModel.types import EmType
from EditorialModel.fields import EmField
from EditorialModel.model import Model
from EditorialModel.backend.json_backend import EmBackendJson
from DataSource.dummy.migrationhandler import DummyMigrationHandler
from DataSource.dummy.migrationhandler import MigrationHandler
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Lodel.settings")
EM_TEST = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'me.json')
@ -26,7 +26,7 @@ EM_TEST_OBJECT = None
def setUpModule():
global EM_TEST_OBJECT
#EM_TEST_OBJECT = Model(EmBackendJson(EM_TEST), migration_handler=DjandoMigrationHandler('LodelTestInstance'))
EM_TEST_OBJECT = Model(EmBackendJson(EM_TEST), migration_handler=DummyMigrationHandler())
EM_TEST_OBJECT = Model(EmBackendJson(EM_TEST), migration_handler=MigrationHandler())
logging.basicConfig(level=logging.CRITICAL)

View file

@ -9,7 +9,7 @@ from EditorialModel.fields import EmField
from Lodel.utils.mlstring import MlString
from EditorialModel.backend.json_backend import EmBackendJson
from DataSource.dummy.migrationhandler import DummyMigrationHandler
from DataSource.dummy.migrationhandler import MigrationHandler
class TestEmComponent(unittest.TestCase):
@ -19,7 +19,7 @@ class TestEmComponent(unittest.TestCase):
def test_hashes(self):
""" Testing __hash__ and __eq__ methods """
me1 = Model(EmBackendJson('EditorialModel/test/me.json'))
me2 = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=DummyMigrationHandler())
me2 = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=MigrationHandler())
for comp_class in [EmClass, EmType, EmField]:
comp_l1 = me1.components(comp_class)

View file

@ -1,5 +1,6 @@
import os
import unittest
from unittest import TestCase
from EditorialModel.fields import EmField
from EditorialModel.model import Model
@ -63,6 +64,7 @@ class TestField(FieldTestCase):
with self.assertRaises(ValueError, msg="Only common_fields should be internal='object'"):
field = EM_TEST_OBJECT.create_component(EmField.__name__, {'name': 'testbadinternal','internal': 'object', 'class_id': self.test_class.uid, 'fieldtype': self.test_fieldtype})
@unittest.skip("rel2type are not uniq like this anymore")
def test_double_rel2type(self):
""" Test the rel2type unicity """
em = EM_TEST_OBJECT

View file

@ -11,7 +11,7 @@ from Lodel.utils.mlstring import MlString
from EditorialModel.backend.json_backend import EmBackendJson
from EditorialModel.backend.dummy_backend import EmBackendDummy
from DataSource.dummy.migrationhandler import DummyMigrationHandler
from DataSource.dummy.migrationhandler import MigrationHandler
class TestModel(unittest.TestCase):
@ -24,15 +24,15 @@ class TestModel(unittest.TestCase):
model = Model(EmBackendJson('EditorialModel/test/me.json'))
self.assertTrue(isinstance(model, Model))
model = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=DummyMigrationHandler())
model = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=MigrationHandler())
self.assertTrue(isinstance(model, Model))
def test_bad_init(self):
""" Test initialisation with bad arguments """
for bad in [None, int, EmBackendDummy, DummyMigrationHandler, 'foobar']:
for bad in [None, int, EmBackendDummy, MigrationHandler, 'foobar']:
with self.assertRaises(TypeError, msg="Tried to instanciate a Model with a bad backend"):
Model(bad)
for bad in [int, EmBackendDummy, DummyMigrationHandler, 'foobar']:
for bad in [int, EmBackendDummy, MigrationHandler, 'foobar']:
with self.assertRaises(TypeError, msg="Tried to instanciate a Model with a migration_handler"):
Model(EmBackendDummy(), bad)
@ -246,8 +246,8 @@ class TestModel(unittest.TestCase):
for nat, sup_l in emtype.superiors().items():
superiors_list_orig[nat] = [sup.uid for sup in sup_l]
with patch.object(DummyMigrationHandler, 'register_change', return_value=None) as mh_mock:
self.ed_mod.migrate_handler(DummyMigrationHandler())
with patch.object(MigrationHandler, 'register_change', return_value=None) as mh_mock:
self.ed_mod.migrate_handler(MigrationHandler())
#Getting cloned EM instance
new_me = mh_mock.mock_calls[-1][1][0]
for emtype in new_me.components(EmType):
@ -269,8 +269,8 @@ class TestModel(unittest.TestCase):
def test_migrate_handler_hashes(self):
""" Testing that the migrate_handler() method create an EM with the same hash as the original EM """
with patch.object(DummyMigrationHandler, 'register_change', return_value=None) as mh_mock:
self.ed_mod.migrate_handler(DummyMigrationHandler())
with patch.object(MigrationHandler, 'register_change', return_value=None) as mh_mock:
self.ed_mod.migrate_handler(MigrationHandler())
#Getting the cloned EM instance
last_call = mh_mock.mock_calls[-1]
self.assertEqual(hash(last_call[1][0]), hash(self.ed_mod))
@ -278,7 +278,7 @@ class TestModel(unittest.TestCase):
def test_hash(self):
""" Test that __hash__ and __eq__ work properly on models """
me1 = Model(EmBackendJson('EditorialModel/test/me.json'))
me2 = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=DummyMigrationHandler())
me2 = Model(EmBackendJson('EditorialModel/test/me.json'), migration_handler=MigrationHandler())
self.assertEqual(hash(me1), hash(me2), "When instanciate from the same backend & file but with another migration handler the hashes differs")
self.assertTrue(me1.__eq__(me2))

View file

@ -88,4 +88,4 @@ def dir_init():
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)
print("Created %s" % my_file_path)

View file

@ -10,6 +10,7 @@ import importlib
import re
from Lodel import logger
from Lodel.settings import Settings
from EditorialModel.fieldtypes.generic import DatasConstructor
from Lodel.hooks import LodelHook
@ -44,9 +45,29 @@ class LeApiQueryError(LeApiErrors): pass
## @brief When an error concerns a datas
class LeApiDataCheckError(LeApiErrors): pass
class _MetaLeCrud(type):
def __getattribute__(self, name):
if name == '_datasource':
if super().__getattribute__('_datasource') is None:
module = importlib.import_module("DataSource.{pkg_name}.leapidatasource".format(
pkg_name = Settings.ds_package,
mod_name = 'leapidatasource'
))
ds_cls = getattr(module, 'LeapiDataSource')
super().__setattr__('_datasource', ds_cls(**Settings.datasource_options))
return super().__getattribute__(name)
if 'leapidatasource' in globals():
if name == '_datasource' and isinstance(self._datasource, DummyDatasource):
#if name == '_datasource' and self._datasource == None:
leapids = globals()['leapidatasource']
if not isinstance(leapids, DummyDatasource):
self._datasource = leapids({})
return super().__getattribute__(name)
## @brief Main class to handler lodel editorial components (relations and objects)
class _LeCrud(object):
class _LeCrud(object, metaclass = _MetaLeCrud):
## @brief The datasource
_datasource = None
@ -102,6 +123,11 @@ class _LeCrud(object):
## @brief A flag to indicate if the object was fully intanciated or not
self._instanciation_complete = len(kwargs) + 1 == len(self.fieldlist())
def __getattribute__(self, name):
if name == '_datasource':
return _MetaLeCrud.__getattribute__(self.__class__, name)
return super().__getattribute__(name)
## @brief Convert an EmType or EmClass name in a python class name
# @param name str : The name
# @return name.title()

View file

@ -38,9 +38,9 @@ class LeFactory(object):
## @brief Write generated code to a file
# @todo better options/params for file creation
def create_pyfile(self, model, datasource_cls, datasource_args):
def create_pyfile(self, model):
with open(self._code_filename, "w+") as dynfp:
dynfp.write(self.generate_python(model, datasource_cls, datasource_args))
dynfp.write(self.generate_python(model))
## @brief Generate fieldtypes for concret classes
# @param ft_dict dict : key = fieldname value = fieldtype __init__ args
@ -176,7 +176,7 @@ class {classname}(LeRel2Type):
# @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
def generate_python(self, model, datasource_cls, datasource_args):
def generate_python(self, model):
self.needed_fieldtypes = set() #Stores the list of fieldtypes that will be used by generated code
model = model
@ -199,11 +199,6 @@ from leapi.leclass import _LeClass
from leapi.letype import _LeType
"""
result += """
import %s
""" % (datasource_cls.__module__)
#Generating the code for LeObject class
leobj_me_uid = dict()
for comp in model.components('EmType') + model.components('EmClass'):
@ -224,7 +219,6 @@ import %s
## @brief _LeCrud concret class
# @see leapi.lecrud._LeCrud
class LeCrud(leapi.lecrud._LeCrud):
_datasource = {ds_classname}(**{ds_kwargs})
_uid_fieldtype = None
## @brief _LeObject concret class
@ -257,8 +251,6 @@ class LeClass(LeObject, _LeClass):
class LeType(LeClass, _LeType):
pass
""".format(
ds_classname = datasource_cls.__module__ + '.' + datasource_cls.__name__,
ds_kwargs = repr(datasource_args),
me_uid_l = repr(leobj_me_uid),
leo_uid_fieldtype = leobj_uid_fieldtype,
leo_fieldtypes = '{\n\t' + (',\n\t'.join(leobj_fieldtypes))+ '\n\t}',

View file

@ -179,7 +179,7 @@ class LeCrudTestCase(TestCase):
# Tests mocking the datasource
# 
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert(self, dsmock):
from dyncode import Publication, Numero, LeObject, Personne, Article
ndatas = [
@ -205,7 +205,7 @@ class LeCrudTestCase(TestCase):
dsmock.reset_mock()
## @todo try failing on inserting from LeClass child or LeObject
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert_fails(self, dsmock):
from dyncode import Publication, Numero, LeObject, Personne, Article
ndatas = [
@ -221,7 +221,7 @@ class LeCrudTestCase(TestCase):
assert not dsmock.called
pass
@patch('DataSource.dummy.leapidatasource.DummyDatasource.update')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.update')
def test_update(self, dsmock):
from dyncode import Publication, Numero, LeObject
@ -242,7 +242,7 @@ class LeCrudTestCase(TestCase):
dsmock.assert_called_once_with(ccls, eid, **qdatas)
## @todo test invalid get
@patch('DataSource.dummy.leapidatasource.DummyDatasource.select')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.select')
def test_get(self, dsmock):
""" Test the select method without group, limit, sort or offset """
from dyncode import Publication, Numero, LeObject, Textes
@ -321,7 +321,7 @@ class LeCrudTestCase(TestCase):
)
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.select')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.select')
def test_get_complete(self, dsmock):
""" Test the select method with group limit sort and offset arguments """
from dyncode import Numero

View file

@ -58,7 +58,7 @@ class LeObjectMockDatasourceTestCase(TestCase):
""" Remove the temporary directory created at class setup """
leapi.test.utils.cleanup(cls.tmpdir)
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert(self, dsmock):
from dyncode import Publication, Numero, LeObject
ndatas = [
@ -81,7 +81,7 @@ class LeObjectMockDatasourceTestCase(TestCase):
dsmock.assert_called_once_with(Numero, **expt_dats)
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.update')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.update')
def test_update(self, dsmock):
from dyncode import Publication, Numero, LeObject, Personne, Article, RelTextesPersonneAuteur
@ -98,7 +98,7 @@ class LeObjectMockDatasourceTestCase(TestCase):
dsmock.assert_called_once_with(instance.__class__, instance.uidget(), **datas)
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.delete')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.delete')
def test_delete(self, dsmock):
from dyncode import Publication, Numero, LeObject, LeType, LeRelation

View file

@ -69,7 +69,7 @@ class LeRelationTestCase(TestCase):
for i in range(3):
self.assertEqual(filter_res[i], res[i], "%s != %s"%(filter_res, res))
@patch('DataSource.dummy.leapidatasource.DummyDatasource.delete')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.delete')
def test_delete(self, dsmock):
""" Testing LeHierarch insert method """
from dyncode import LeCrud, Publication, Numero, Personnes, LeObject, Rubrique, LeHierarch, LeRelation
@ -81,7 +81,7 @@ class LeRelationTestCase(TestCase):
class LeHierarch(LeRelationTestCase):
@patch('DataSource.dummy.leapidatasource.DummyDatasource.select')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.select')
def test_get(self, dsmock):
""" Tests the LeHierarch.get() method without limit group order etc."""
from dyncode import LeCrud, Publication, Numero, Personnes, LeObject, Rubrique, LeHierarch, LeRelation
@ -123,7 +123,7 @@ class LeHierarch(LeRelationTestCase):
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert(self, dsmock):
""" Testing LeHierarch insert method """
from dyncode import LeCrud, Publication, Numero, Personnes, LeObject, Rubrique, LeHierarch, LeRelation
@ -194,7 +194,7 @@ class LeHierarch(LeRelationTestCase):
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.delete')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.delete')
def test_delete(self, dsmock):
""" Testing LeHierarch delete method """
from dyncode import LeCrud, Publication, Numero, Personnes, LeObject, Rubrique, LeHierarch, LeRelation
@ -203,7 +203,7 @@ class LeHierarch(LeRelationTestCase):
dsmock.assert_called_once_with(LeHierarch, 10)
@patch('DataSource.dummy.leapidatasource.DummyDatasource.update')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.update')
def test_update(self, dsmock):
""" test LeHierach update method"""
from dyncode import LeHierarch
@ -214,7 +214,7 @@ class LeHierarch(LeRelationTestCase):
class LeRel2TypeTestCase(LeRelationTestCase):
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert(self, dsmock):
""" test LeHierach update method"""
from dyncode import LeObject, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, RelTextesPersonneAuteur
@ -265,7 +265,7 @@ class LeRel2TypeTestCase(LeRelationTestCase):
dsmock.assert_called_once_with(RelTextesPersonneAuteur, **eres)
dsmock.reset_mock()
@patch('DataSource.dummy.leapidatasource.DummyDatasource.insert')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.insert')
def test_insert_fails(self, dsmock):
""" test LeHierach update method"""
from dyncode import LeObject, Rubrique, Numero, Article, Textes, Personne, Personnes, LeHierarch, LeRel2Type, RelTextesPersonneAuteur

View file

@ -102,7 +102,7 @@ class LeTypeMockDsTestCase(TestCase):
""" Remove the temporary directory created at class setup """
leapi.test.utils.cleanup(cls.tmpdir)
@patch('DataSource.dummy.leapidatasource.DummyDatasource.select')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.select')
def test_populate(self, dsmock):
from dyncode import Publication, Numero, LeObject
@ -112,7 +112,7 @@ class LeTypeMockDsTestCase(TestCase):
num.populate()
dsmock.assert_called_once_with(Numero, missing_fields, [('lodel_id','=',1)],[])
@patch('DataSource.dummy.leapidatasource.DummyDatasource.update')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.update')
def test_update(self, dsmock):
from dyncode import Publication, Numero, LeObject
@ -125,7 +125,7 @@ class LeTypeMockDsTestCase(TestCase):
mock_populate.assert_called_once_with()
dsmock.assert_called_once_with(Numero, num.uidget(), **datas)
@patch('DataSource.dummy.leapidatasource.DummyDatasource.delete')
@patch('DataSource.dummy.leapidatasource.LeapiDataSource.delete')
def test_delete(self, dsmock):
from dyncode import Publication, Numero, LeObject

View file

@ -5,15 +5,13 @@ import sys
from EditorialModel.model import Model
import leapi
from EditorialModel.backend.json_backend import EmBackendJson
from DataSource.MySQL.leapidatasource import DummyDatasource
from DataSource.dummy.leapidatasource import LeapiDataSource
from leapi.lefactory import LeFactory
genepy_args = {
'model' : Model(EmBackendJson(json_file = 'EditorialModel/test/me.json')),
'datasource_cls': DummyDatasource,
'datasource_args': {}
}
def tmp_load_factory_code(name='dyncode'):

View file

@ -6,7 +6,6 @@ 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 = 'leapi/dyn.py' if len(sys.argv) == 1 else sys.argv[1]
EMJSON = 'EditorialModel/test/me.json' if len(sys.argv) < 3 else sys.argv[2]
@ -14,7 +13,7 @@ EMJSON = 'EditorialModel/test/me.json' if len(sys.argv) < 3 else sys.argv[2]
em = Model(EmBackendJson(EMJSON))
fact = LeFactory(OUTPUT)
fact.create_pyfile(em, LeDataSourceSQL, {})
print(fact.generate_python(em, LeDataSourceSQL, {}))
fact.create_pyfile(em)
print(fact.generate_python(em))