improvement

This commit is contained in:
Emmanuel Garette 2019-01-10 09:54:22 +01:00
parent 3446a38287
commit e1f62e8044
2 changed files with 255 additions and 121 deletions

View File

@ -0,0 +1,4 @@
from .api import Config
__all__ = ('Config',)

View File

@ -3,12 +3,16 @@ import warnings
import re import re
from .tiramisu_json import TiramisuJson, _
from tiramisu.error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError from tiramisu.error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError
from tiramisu.setting import undefined from tiramisu.setting import undefined
# FIXME
def _(val):
return val
class Option: class Option:
# fake Option (IntOption, StrOption, ...)
def __init__(self, def __init__(self,
name, name,
path): path):
@ -26,11 +30,14 @@ class Option:
class TiramisuOptionOption: class TiramisuOptionOption:
# config.option(path).option
def __init__(self, def __init__(self,
path: str, path: str,
schema: Dict) -> None: schema: Dict,
model: Dict) -> None:
self._path = path self._path = path
self.schema = schema self.schema = schema
self.model = model
def doc(self): def doc(self):
return self.schema['title'] return self.schema['title']
@ -38,6 +45,9 @@ class TiramisuOptionOption:
def path(self): def path(self):
return self._path return self._path
def name(self):
return self._path.rsplit('.', 1)[-1]
def isoptiondescription(self): def isoptiondescription(self):
return self.schema['type'] in ['object', 'array'] return self.schema['type'] in ['object', 'array']
@ -69,14 +79,29 @@ class TiramisuOptionOption:
return types[self.schema['type']] return types[self.schema['type']]
raise Exception('unsupported type {}'.format(self.schema['type'])) raise Exception('unsupported type {}'.format(self.schema['type']))
def properties(self) -> List[str]:
props = []
model = self.model[self._path]
if model.get('required'):
#FIXME 'empty', 'needs_len'
props.append('mandatory')
if model.get('readOnly'):
props.append('frozen')
if model.get('hidden'):
props.append('hidden')
return props
def requires(self) -> None:
# FIXME
return None
class TiramisuOptionProperty: class TiramisuOptionProperty:
# config.option(path).property
def __init__(self, def __init__(self,
model: Dict) -> None: model: Dict) -> None:
self.model = model self.model = model
def get(self): def get(self, only_raises=False):
properties = self.model.get('properties', [])[:]
# FIXME if slave: # FIXME if slave:
#if not isslave and childapi.option.ismulti(): #if not isslave and childapi.option.ismulti():
# if 'empty' in props: # if 'empty' in props:
@ -85,33 +110,54 @@ class TiramisuOptionProperty:
# if 'mandatory' in props: # if 'mandatory' in props:
# obj['needs_len'] = True # obj['needs_len'] = True
# props.remove('mandatory') # props.remove('mandatory')
if self.model.get('required', False): if not only_raises:
properties.append('mandatory') properties = self.model.get('properties', [])[:]
if self.model.get('readOnly', False): if self.model.get('required', False):
properties.append('frozen') properties.append('mandatory')
if self.model.get('readOnly', False):
properties.append('frozen')
else:
properties = []
if self.model.get('hidden', False): if self.model.get('hidden', False):
properties.append('hidden') properties.append('hidden')
return properties return properties
class TiramisuOptionValue: class _Value:
def __init__(self, def _dict_walk(self,
config: 'Config', ret: Dict,
schema: Dict, schema: Dict,
model: List[Dict], root: str,
form: List[Dict], fullpath: bool,
temp: List[Dict], withwarning: bool):
path: str, for key, option in schema['properties'].items():
index: int) -> None: hidden = self.temp.get(key, {}).get('hidden', None)
self.config = config model_hidden = not self.model.get(key, {}).get('hidden', False) and \
self.schema = schema self.model.get(key, {}).get('display', True)
self.model = model if hidden is False or (hidden is None and model_hidden):
self.form = form if option['type'] == 'object':
self.temp = temp self._dict_walk(ret,
self.path = path option,
self.index = index root,
fullpath,
withwarning)
else:
value = self._get_value(key, schema)
self._display_warnings(key, value, option['type'], option['name'], withwarning)
ret[key] = value
def _display_warnings(self, path, value, type, name): def dict(self,
fullpath: bool=False,
withwarning: bool=False):
ret = {}
self._dict_walk(ret,
self.schema,
self.path,
fullpath,
withwarning)
return ret
def _display_warnings(self, path, value, type, name, withwarning=True):
if self.model.get(path, {}).get('error'): if self.model.get(path, {}).get('error'):
for err in self.model.get(path, {}).get('error'): for err in self.model.get(path, {}).get('error'):
warnings.warn_explicit(ValueOptionError(value, warnings.warn_explicit(ValueOptionError(value,
@ -121,28 +167,13 @@ class TiramisuOptionValue:
ValueErrorWarning, ValueErrorWarning,
self.__class__.__name__, 0) self.__class__.__name__, 0)
if self.model.get(path, {}).get('warnings'): if withwarning and self.model.get(path, {}).get('warnings'):
for warn in self.model.get(path, {}).get('warnings'): for warn in self.model.get(path, {}).get('warnings'):
warnings.warn_explicit(ValueWarning('{0}'.format(warn), warnings.warn_explicit(ValueWarning('{0}'.format(warn),
Option(name, path)), Option(name, path)),
ValueWarning, ValueWarning,
self.__class__.__name__, 0) self.__class__.__name__, 0)
def _dict_walk(self,
ret: Dict,
schema: Dict):
for key, option in schema['properties'].items():
hidden = self.temp.get(self.path, {}).get('hidden', None)
if hidden is False or (hidden is None and \
not self.model.get(self.path, {}).get('hidden', False) and \
self.model.get(self.path, {}).get('display', True)):
if option['type'] == 'object':
self._dict_walk(ret, option)
else:
value = self._get_value(key, schema)
self._display_warnings(key, value, option['type'], option['name'])
ret[key] = value
def _get_value(self, def _get_value(self,
path: str, path: str,
schema: Dict) -> Any: schema: Dict) -> Any:
@ -154,14 +185,26 @@ class TiramisuOptionValue:
value = [] value = []
return value return value
def dict(self,
fullpath: bool=False, class TiramisuOptionValue(_Value):
withwarning: bool=False): # config.option(path).value
if not fullpath or not withwarning: def __init__(self,
raise NotImplementedError() config: 'Config',
ret = {} schema: Dict,
self._dict_walk(ret, self.schema) model: List[Dict],
return ret form: List[Dict],
temp: List[Dict],
path: str,
index: int) -> None:
self.config = config
self.schema = schema
if schema.get('properties') != None:
raise Exception('pouet')
self.model = model
self.form = form
self.temp = temp
self.path = path
self.index = index
def get(self) -> Any: def get(self) -> Any:
value = self._get_value(self.path, self.schema) value = self._get_value(self.path, self.schema)
@ -184,7 +227,75 @@ class TiramisuOptionValue:
self.form.get(self.path, {}).get('remote', False)) self.form.get(self.path, {}).get('remote', False))
class _Option:
def list(self,
type='option'):
if type not in ['all', 'option']:
raise NotImplementedError()
if self.schema.get('properties') is None:
raise Exception(list(self.schema.keys()))
for path, schema in self.schema['properties'].items():
if type == 'all' or schema['type'] not in ['object', 'array']:
hidden = self.temp.get(path, {}).get('hidden', None)
if self.temp.get(path, {}).get('hidden', False) is not True and \
not self.model.get(path, {}).get('hidden', False) and \
self.model.get(path, {}).get('display', True):
if schema['type'] in ['object', 'array']:
yield TiramisuOptionDescription(self.config,
schema,
self.model,
self.form,
self.temp,
path)
else:
yield TiramisuOption(self.config,
schema,
self.model,
self.form,
self.temp,
path,
self.index)
class TiramisuOptionDescription(_Option):
# config.option(path) (with path == OptionDescription)
def __init__(self,
config: 'Config',
schema: Dict,
model: List[Dict],
form: List[Dict],
temp: List[Dict],
path: str) -> None:
self.config = config
self.schema = schema
self.model = model
self.form = form
self.temp = temp
self.path = path
self.index = None
def __getattr__(self,
subfunc: str) -> Any:
if subfunc == 'option':
return TiramisuOptionOption(self.path,
self.schema,
self.model)
if subfunc == 'property':
return TiramisuOptionProperty(self.model.get(self.path, {}))
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
def group_type(self):
hidden = self.temp.get(self.path, {}).get('hidden', None)
if hidden is False or (hidden is None and \
not self.model.get(self.path, {}).get('hidden', False) and \
self.model.get(self.path, {}).get('display', True)):
# FIXME
return 'default'
raise PropertiesOptionError(None, None, None, opt_type='optiondescription')
class TiramisuOption: class TiramisuOption:
# config.option(path) (with path == Option)
def __init__(self, def __init__(self,
config: 'Config', config: 'Config',
schema: Dict, schema: Dict,
@ -207,7 +318,8 @@ class TiramisuOption:
if self.index != None: if self.index != None:
raise NotImplementedError() raise NotImplementedError()
return TiramisuOptionOption(self.path, return TiramisuOptionOption(self.path,
self.schema) self.schema,
self.model)
if subfunc == 'value': if subfunc == 'value':
return TiramisuOptionValue(self.config, return TiramisuOptionValue(self.config,
self.schema, self.schema,
@ -222,34 +334,9 @@ class TiramisuOption:
return TiramisuOptionProperty(self.model.get(self.path, {})) return TiramisuOptionProperty(self.model.get(self.path, {}))
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) raise APIError(_('please specify a valid sub function ({})').format(subfunc))
def group_type(self):
hidden = self.temp.get(self.path, {}).get('hidden', None)
if hidden is False or (hidden is None and \
not self.model.get(self.path, {}).get('hidden', False) and \
self.model.get(self.path, {}).get('display', True)):
# FIXME
return 'default'
raise PropertiesOptionError(None, None, None, opt_type='optiondescription')
def list(self,
type='option'):
if type != 'all':
raise NotImplementedError()
for path, schema in self.schema['properties'].items():
hidden = self.temp.get(path, {}).get('hidden', None)
if self.temp.get(path, {}).get('hidden', False) is not True and \
not self.model.get(path, {}).get('hidden', False) and \
self.model.get(path, {}).get('display', True):
yield TiramisuOption(self.config,
schema,
self.model,
self.form,
self.temp,
path,
self.index)
class TiramisuContextProperty: class TiramisuContextProperty:
# config.property
# def __init__(self, # def __init__(self,
# json): # json):
# self.json = json # self.json = json
@ -259,7 +346,63 @@ class TiramisuContextProperty:
return ['demoting_error_warning'] return ['demoting_error_warning']
class ContextOption(_Option):
# config.option
def __init__(self,
config: 'Config',
model: Dict,
form: Dict,
schema: Dict,
temp: Dict) -> None:
self.config = config
self.model = model
self.form = form
schema = {'properties': schema}
self.schema = schema
self.temp = temp
self.index = None
def __call__(self,
path: str,
index: Optional[int]=None) -> TiramisuOption:
return TiramisuOption(self.config,
self.config.get_schema(path),
self.model,
self.form,
self.temp,
path,
index)
class ContextValue(_Value):
# config.value
def __init__(self,
config: 'Config',
model: Dict,
form: Dict,
schema: Dict,
temp: Dict) -> None:
self.config = config
self.model = model
self.form = form
first = next(iter(schema.keys()))
self.path = first.rsplit('.', 1)[0]
schema = {'properties': schema}
self.schema = schema
self.temp = temp
def __call__(self) -> TiramisuOptionValue:
return TiramisuOptionValue(self.config,
self.schema,
self.model,
self.form,
self.temp,
path,
index)
class Config: class Config:
# config
def __init__(self, def __init__(self,
json): json):
self.model_ori = json['model'] self.model_ori = json['model']
@ -273,43 +416,31 @@ class Config:
self.temp = {} self.temp = {}
self.schema = json['schema'] self.schema = json['schema']
self.updates = [] self.updates = []
first_path = next(iter(self.schema.keys()))
if '.' in first_path:
self.root = first_path.rsplit('.', 1)[0]
else:
self.root = ''
def __getattr__(self, def __getattr__(self,
subfunc: str) -> Any: subfunc: str) -> Any:
if subfunc == 'property': if subfunc == 'property':
return TiramisuContextProperty() return TiramisuContextProperty()
if subfunc == 'option':
return ContextOption(self,
self.model,
self.form,
self.schema,
self.temp)
if subfunc == 'value':
return ContextValue(self,
self.model,
self.form,
self.schema,
self.temp)
raise APIError(_('please specify a valid sub function ({})').format(subfunc)) raise APIError(_('please specify a valid sub function ({})').format(subfunc))
def option(self,
path: str,
index: Optional[int]=None) -> TiramisuOption:
first = next(iter(self.schema.keys()))
if '.' in first:
root_path = first.rsplit('.', 1)[0]
len_root_path = len(root_path)
len_path = len(path)
if len_root_path >= len_path:
spath = []
else:
spath = path[len_root_path + 1:].split('.')
schema = {'properties': self.schema}
else:
root_path, *spath = path.split('.')
schema = self.schema[root_path]['properties']
fullsubpath = [root_path]
for subpath in spath:
fullsubpath.append(subpath)
schema = schema['properties']['.'.join(fullsubpath)]
return TiramisuOption(self,
schema,
self.model,
self.form,
self.temp,
path,
index)
def add_value(self, def add_value(self,
path: str, path: str,
index: Optional[int], index: Optional[int],
@ -360,21 +491,20 @@ class Config:
def get_schema(self, def get_schema(self,
path): path):
first_path = next(iter(self.schema.keys())) root_path = self.root
if '.' in first_path: if root_path:
root = first_path.rsplit('.', 1)[0].split('.') schema = {'properties': self.schema}
root = self.root.split('.')
subpaths = path.split('.')[len(root):]
for subpath in subpaths:
if root_path:
root_path += '.' + subpath
else:
root_path = subpath
schema = schema['properties'][root_path]
print(path, schema)
else: else:
root = [] schema = self.schema[path]
s_path = path.split('.')
schema = {'properties': self.schema}
root_path = '.'.join(root)
for subpath in path.split('.')[len(root):]:
if root_path:
root_path += '.' + subpath
else:
root_path = subpath
schema = schema['properties'][root_path]
return schema return schema
@ -411,7 +541,7 @@ class Config:
last_body['action'] == 'modify' and action == 'delete': last_body['action'] == 'modify' and action == 'delete':
update_last_action = True update_last_action = True
elif last_body['action'] == 'add' and action == 'delete': elif last_body['action'] == 'add' and action == 'delete':
del this.updates[-1] del self.updates[-1]
if update_last_action: if update_last_action:
if value is None: if value is None: