1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-04-02 08:57:15 +02:00

Implements order in fieldtype construct

This commit is contained in:
Yann 2016-01-14 16:36:46 +01:00
commit 1daf9677c6
5 changed files with 83 additions and 30 deletions

View file

@ -10,6 +10,8 @@ class EmFieldType(integer.EmFieldType):
help = 'Fieldtypes designed to handle editorial model UID for LeObjects'
_construct_datas_deps = []
def __init__(self, is_id_class, **kwargs):
self._is_id_class = is_id_class
kwargs['internal'] = 'automatic'
@ -18,18 +20,15 @@ class EmFieldType(integer.EmFieldType):
def _check_data_value(self, value):
return (value, None)
def construct_data(self, lec, fname, datas):
def _construct_data(self, lec, fname, datas, cur_value):
ret = None
if self.is_id_class:
if lec.implements_leclass():
datas[fname] = lec._class_id
else:
datas[fname] = None
ret = lec._class_id
else:
if lec.implements_letype():
datas[fname] = lec._type_id
else:
datas[fname] = None
return datas[fname]
ret = lec._type_id
return ret
def check_data_consistency(self, lec, fname, datas):
if datas[fname] != (lec._class_id if self.is_id_class else lec._type_id):

View file

@ -1,11 +1,15 @@
#-*- coding: utf-8 -*-
import copy
import types
import importlib
class GenericFieldType(object):
help_text = 'Generic field type : abstract class for every fieldtype'
## @brief List fields that will be exposed to the construct_data_method
_construct_datas_deps = []
## @param internal False | str : define wheter or not a field is internal
# @throw NotImplementedError if called from bad class
@ -35,15 +39,22 @@ class GenericFieldType(object):
def _check_data_value(self, value):
return (value, None)
## @brief Wrapper for _construct_data() method
#
# Now useless
def construct_data(self, lec, fname, datas, cur_value):
return self._construct_data(lec, fname, datas, cur_value)
## @brief Build field value
# @param lec LeCrud : A LeCrud child class
# @param fname str : The field name
# @param datas dict : dict storing fields values (from the lec)
# @param cur_value : the value for the current field (identified by fieldname)
# @return constructed datas (for the fname field)
# @throw RuntimeError if unable to construct data
def construct_data(self, lec, fname, datas):
if fname in datas:
return datas[fname]
def _construct_data(self, lec, fname, datas, cur_value):
if fname in datas.keys():
return cur_value
elif hasattr(lec.fieldtypes()[fname], 'default'):
return lec.fieldtypes()[fname].default
elif lec.fieldtypes()[fname].nullable:
@ -152,6 +163,41 @@ class MultiValueFieldType(GenericFieldType):
## stores the fieldtype that handles the values
self.value_fieldtype = value_fieldtype
## @brief Class designed to handle datas access will fieldtypes are constructing datas
class DatasConstructor(object):
## @brief Init a DatasConstructor
# @param lec LeCrud : LeCrud child class
# @param datas dict : dict with field name as key and field values as value
# @param fieldtypes dict : dict with field name as key and fieldtype as value
def __init__(self, lec, datas, fieldtypes):
## Stores concerned class
self._lec = lec
## Stores datas and constructed datas
self._datas = copy.copy(datas)
## Stores fieldtypes
self._fieldtypes = fieldtypes
## Stores list of fieldname for constructed datas
self._constructed = []
## Stores construct calls list
self._construct_calls = []
def keys(self):
return self._datas.keys()
def __getitem__(self, fname):
if fname not in self._constructed:
if fname in self._construct_calls:
raise RuntimeError('Probably circular dependencies in fieldtypes')
cur_value = self._datas[fname] if fname in self._datas else None
self._datas[fname] = self._fieldtypes[fname].construct_data(self._lec, fname, self, cur_value)
self._constructed.append(fname)
return self._datas[fname]
def __setitem__(self, fname, value):
self._datas[fname] = value
#
#
# Exceptions

View file

@ -9,7 +9,7 @@ class EmFieldType(ReferenceFieldType):
help = 'Fieldtypes designed to handle pk of LeObject in LeRelations'
ftype = 'leobject'
_construct_data_deps = []
## @todo Replace hardcoded string for reference initialisation
def __init__(self, superior=True, **kwargs):
@ -25,23 +25,23 @@ class EmFieldType(ReferenceFieldType):
## @brief If field value is an integer, returns a partially instanciated LeObject (only with an ID)
# @todo what should we do if the get fails ? Raise ?
def construct_data(self, lec, fname, datas):
if isinstance(datas[fname], str):
def _construct_data(self, lec, fname, datas, cur_value):
if isinstance(cur_value, str):
# Cast to int
try:
datas[fname] = int(datas[fname])
cur_value = int(cur_value)
except (ValueError, TypeError) as e:
raise e # Raise Here !?
if datas[fname].is_leobject():
if cur_value.is_leobject():
# Its an object not populated (we dont now its type)
datas[fname] = datas[fname].lodel_id #Optimize here giving only class_id and type_id to populate ?
if isinstance(datas[fname], int):
cur_value = cur_value.lodel_id #Optimize here giving only class_id and type_id to populate ?
if isinstance(cur_value, int):
# Get instance with id
resget = lec.name2class('LeObject').get(['lodel_id = %d' % datas[fname]])
resget = lec.name2class('LeObject').get(['lodel_id = %d' % cur_value])
if resget is None or len(resget) != 1:
# Bad filter or bad id... raise ?
raise Exception("BAAAAAD")
return datas[fname]
return cur_value
## @brief checks datas consistency
# @param lec LeCrud : A LeCrud child instance

View file

@ -1,5 +1,6 @@
#-*- coding utf-8 -*-
import EditorialModel.classtypes
import leapi.lerelation as lerelation
from .generic import FieldTypeError
@ -9,17 +10,19 @@ class EmFieldType(integer.EmFieldType):
help = 'Fieldtype designed to handle relations rank'
_construct_datas_deps = [EditorialModel.classtypes.relation_superior]
def __init__(self, **kwargs):
super().__init__(**kwargs)
def construct_data(self, lec, fname, datas):
superior_id = datas[lec._superior_field_name]
def _construct_data(self, lec, fname, datas, cur_value):
superior_id = datas[EditorialModel.classtypes.relation_superior]
if lec.is_lerel2type():
subordinate = lec._subordinate_cls
sub_em_type_id = subordinate._type_id
datas[fname] = lec.get_max_rank(superior_id, sub_em_type_id)
cur_value = lec.get_max_rank(superior_id, sub_em_type_id)
elif lec.is_lehierarch():
datas[fname] = lec.get_max_rank(superior_id, datas['nature'])
cur_value = lec.get_max_rank(superior_id, datas['nature'])
else:
raise ValueError("Called with bad class : ", lec.__name__)
return datas[fname]
return cur_value

View file

@ -9,6 +9,8 @@ import warnings
import importlib
import re
from EditorialModel.fieldtypes.generic import DatasConstructor
REL_SUP = 0
REL_SUB = 1
@ -460,11 +462,14 @@ class _LeCrud(object):
# @todo Decide wether or not the datas are modifed inplace or returned in a new dict (second solution for the moment)
@classmethod
def _construct_datas(cls, datas):
res_datas = copy.copy(datas)
for fname, ftype in cls.fieldtypes().items():
if not ftype.is_internal() or ftype.internal != 'autosql':
res_datas[fname] = ftype.construct_data(cls, fname, res_datas)
return res_datas
constructor = DatasConstructor(cls, datas, cls.fieldtypes())
ret = {
fname:constructor[fname]
for fname, ftype in cls.fieldtypes().items()
if not ftype.is_internal() or ftype.internal != 'autosql'
}
return ret
## @brief Check datas consistency
# 
# @warning assert that datas is complete