1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-06-13 22:20:47 +02:00

New way to specify _fields and table in EmComponent's child classes

Now _fields and table MUST be class attribute.
Its important to note that _fields now consist in a list of (name, ftype) tuples and that ftype is a EmFieldType class and NOT an EmFieldType instance
This commit is contained in:
Yann 2015-06-19 12:26:46 +02:00
commit 00614d90e9
5 changed files with 80 additions and 47 deletions

View file

@ -425,7 +425,7 @@ EXTRACT_ALL = YES
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
EXTRACT_PRIVATE = YES
# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# scope will be included in the documentation.

View file

@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
""" Manipulate Classes of the Editorial Model
Create classes of object
@see EmClass, EmType, EmFieldGroup, EmField
"""
## @file classes.py
# @see EditorialModel::classes::EmClass
import logging as logger
@ -14,18 +12,24 @@ import sqlalchemy as sql
import EditorialModel.fieldtypes as ftypes
import EditorialModel
## @brief Manipulate Classes of the Editorial Model
# Create classes of object.
#@see EmClass, EmType, EmFieldGroup, EmField
class EmClass(EmComponent):
table = 'em_class'
## @brief Specific EmClass fields
# @see EditorialModel::components::EmComponent::_fields
_fields = [
('classtype', ftypes.EmField_char),
('icon', ftypes.EmField_integer),
('sortcolumn', ftypes.EmField_char)
]
def __init__(self, id_or_name):
self.table = EmClass.table
self._fields = [('classtype', ftypes.EmField_char()), ('icon', ftypes.EmField_integer()), ('sortcolumn', ftypes.EmField_char())]
super(EmClass, self).__init__(id_or_name)
""" create a new class
@param name str: name of the new class
@param class_type EmClasstype: type of the class
"""
## Create a new class
# @param name str: name of the new class
# @param class_type EmClasstype: type of the class
# @return An EmClass instance
@classmethod
def create(c, name, class_type):
try:
@ -38,8 +42,9 @@ class EmClass(EmComponent):
return res
@classmethod
## Isolate SQL for create
## Isolate SQL for EmClass::create
# @todo Remove hardcoded default value for icon
# @return An instance of EmClass
def _createDb(c, name, class_type):
""" Do the db querys for EmClass::create() """
@ -62,15 +67,16 @@ class EmClass(EmComponent):
return resclass
""" retrieve list of the field_groups of this class
@return field_groups [EmFieldGroup]:
"""
## Retrieve list of the field_groups of this class
# @return field_groups [EmFieldGroup]:
def fieldgroups(self):
records = self._fieldgroupsDb()
fieldgroups = [ EditorialModel.fieldgroups.EmFieldGroup(int(record.uid)) for record in records ]
return fieldgroups
## Isolate SQL for EmClass::fieldgroups
# @return An array of dict (sqlalchemy fetchall)
def _fieldgroupsDb(self):
dbe = self.__class__.getDbE()
emfg = sql.Table(EditorialModel.fieldgroups.EmFieldGroup.table, sqlutils.meta(dbe))
@ -81,21 +87,21 @@ class EmClass(EmComponent):
return res.fetchall()
""" retrieve list of fields
@return fields [EmField]:
"""
## Retrieve list of fields
# @return fields [EmField]:
def fields(self):
pass
""" retrieve list of type of this class
@return types [EmType]:
"""
## Retrieve list of type of this class
# @return types [EmType]:
def types(self):
records = self._typesDb()
types = [ EditorialModel.types.EmType(int(record.uid)) for record in records ]
return types
## Isolate SQL for EmCLass::types
# @return An array of dict (sqlalchemy fetchall)
def _typesDb(self):
dbe = self.__class__.getDbE()
emtype = sql.Table(EditorialModel.types.EmType.table, sqlutils.meta(dbe))
@ -104,15 +110,13 @@ class EmClass(EmComponent):
res = conn.execute(req)
return res.fetchall()
""" add a new EmType that can ben linked to this class
@param t EmType: type to link
@return success bool: done or not
"""
## Add a new EmType that can ben linked to this class
# @param t EmType: type to link
# @return success bool: done or not
def link_type(self, t):
pass
""" retrieve list of EmType that are linked to this class
@return types [EmType]:
"""
## Retrieve list of EmType that are linked to this class
# @return types [EmType]:
def linked_types(self):
pass

View file

@ -30,8 +30,24 @@ class EmComponent(object):
## Used by EmComponent::modify_rank
ranked_in = None
##Read only properties
_ro_properties = [ 'date_update', 'date_create', 'uid', 'rank']
## Read only properties
_ro_properties = [ 'date_update', 'date_create', 'uid', 'rank', 'deleted']
## @brief List fields name and fieldtype
#
# This is a list that describe database fields common for each EmComponent child classes.
# A database field is defined here by a tuple(name, type) with name a string and type an EditorialModel.fieldtypes.EmFieldType
# @warning The EmFieldType in second position in the tuples must be a class type and not a class instance !!!
# @see EditorialModel::classes::EmClass::_fields EditorialModel::fieldgroups::EmFieldGroup::_fields EditorialModel::types::EmType::_fields EditorialModel::fields::EmField::_fields
_fields = [
('uid', ftypes.EmField_integer),
('name', ftypes.EmField_char),
('rank', ftypes.EmField_integer),
('date_update', ftypes.EmField_date),
('date_create', ftypes.EmField_date),
('string', ftypes.EmField_mlstring),
('help', ftypes.EmField_mlstring)
]
## Instaciate an EmComponent
# @param id_or_name int|str: name or id of the object
@ -42,8 +58,11 @@ class EmComponent(object):
if type(self) is EmComponent:
raise NotImplementedError('Abstract class')
# data fields of the object
self._fields = OrderedDict([('uid', ftypes.EmField_integer()), ('name', ftypes.EmField_char()), ('rank', ftypes.EmField_integer()), ('date_update', ftypes.EmField_date()), ('date_create', ftypes.EmField_date()), ('string', ftypes.EmField_mlstring()), ('help', ftypes.EmField_mlstring())] + self._fields)
## @brief An OrderedDict storing fields name and values
# Values are handled by EditorialModel::fieldtypes::EmFieldType
# @warning \ref _fields instance property is not the same than EmComponent::_fields class property. In the instance property the EditorialModel::fieldtypes::EmFieldType are instanciated to be able to handle datas
# @see EmComponent::_fields EditorialModel::fieldtypes::EmFieldType
self._fields = OrderedDict([ (name, ftype()) for (name,ftype) in (EmComponent._fields + self.__class__._fields) ] )
# populate
if isinstance(id_or_name, int):
@ -52,6 +71,7 @@ class EmComponent(object):
self.name = id_or_name
else:
raise TypeError('Bad argument: expecting <int> or <str> but got : '+str(type(id_or_name)))
self.table = self.__class__.table
self.populate()
## Access values of data fields from the object properties
@ -60,8 +80,17 @@ class EmComponent(object):
def __getattr__(self, name):
if name != '_fields' and name in self._fields:
return self._fields[name].value
else:
return super(EmComponent, self).__getattribute__(name)
raise AttributeError('Error unknown attribute : '+name)
#raise AttributeError('Error unknown attribute : '+name)
def __getattribute__(self, name):
if super(EmComponent, self).__getattribute__('deleted'):
#raise EmComponentNotExistError("This component has been deleted")
raise EmComponentNotExistError("This "+super(EmComponent, self).__getattribute__('__class__').__name__+" has been deleted")
res = super(EmComponent, self).__getattribute(name)
return res
## Set values of data fields from the object properties
# @param name str: The propertie name
@ -85,6 +114,8 @@ class EmComponent(object):
if keys in record:
self._fields[keys].from_string(record[keys])
super(EmComponent, self).__setattr__('deleted', False)
@classmethod
## Shortcut that return the sqlAlchemy engine
def getDbE(c):
@ -108,7 +139,7 @@ class EmComponent(object):
c.close()
if not res or len(res) == 0:
raise EmComponentNotExistError("No component found with "+('name ' + self.name if self.uid == None else 'uid ' + str(self.uid) ))
raise EmComponentNotExistError("No "+self.__class__.__name__+" found with "+('name ' + self.name if self.uid == None else 'uid ' + str(self.uid) ))
return res
@ -198,6 +229,8 @@ class EmComponent(object):
c.close
if not res:
raise RuntimeError("Unable to delete the component in the database")
super(EmComponent, self).__setattr__('deleted', True)
#</SQL>
pass

View file

@ -19,17 +19,13 @@ class EmFieldGroup(EmComponent):
table = 'em_fieldgroup'
## List of fields
# @todo Bad storage, here we want an ordereddict not a tuple list
_fields = [('class_id', ftypes.EmField_integer())]
_fields = [('class_id', ftypes.EmField_integer)]
## Instanciate an EmFieldGroup with data fetched from db
# @param id_or_name str|int: Identify the EmFieldGroup by name or by global_id
# @throw TypeError
# @see EditorialModel::components::EmComponent::__init__()
# @throw EditorialModel::components::EmComponentNotExistError
def __init__(self, id_or_name):
self.table = EmFieldGroup.table
self._fields = self.__class__._fields
super(EmFieldGroup, self).__init__(id_or_name)
@classmethod
## Create a new EmFieldGroup

View file

@ -115,10 +115,7 @@ def tearDownModule():
class EmTestComp(EmComponent):
table = 'ttest'
ranked_in = 'rank_fam'
def __init__(self, ion):
self._fields = [('rank_fam', ftypes.EmField_char())]
super(EmTestComp, self).__init__(ion)
pass
_fields = [('rank_fam', ftypes.EmField_char)]
# The parent class of all other test cases for component
# It defines a SetUp function and some utility functions for EmComponent tests
@ -431,6 +428,9 @@ class TestCreate(ComponentTestCase):
pass
#====================#
# EmComponent.delete #
#====================#
class TestDelete(ComponentTestCase):
def test_delete(self):
@ -466,7 +466,7 @@ class TestDelete(ComponentTestCase):
for j in range(i+1,len(vals)):
try:
tc = EmTestComp(tcv['name'])
tc = EmTestComp(vals[j]['name'])
except EmComponentNotExistError:
self.fail('EmComponent should not be deleted')
pass