improvement
This commit is contained in:
parent
3446a38287
commit
e1f62e8044
4
tiramisu_json_api/__init__.py
Normal file
4
tiramisu_json_api/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from .api import Config
|
||||
|
||||
__all__ = ('Config',)
|
||||
|
@ -3,12 +3,16 @@ import warnings
|
||||
import re
|
||||
|
||||
|
||||
from .tiramisu_json import TiramisuJson, _
|
||||
from tiramisu.error import APIError, ValueWarning, ValueOptionError, ValueErrorWarning, PropertiesOptionError
|
||||
from tiramisu.setting import undefined
|
||||
|
||||
# FIXME
|
||||
def _(val):
|
||||
return val
|
||||
|
||||
|
||||
class Option:
|
||||
# fake Option (IntOption, StrOption, ...)
|
||||
def __init__(self,
|
||||
name,
|
||||
path):
|
||||
@ -26,11 +30,14 @@ class Option:
|
||||
|
||||
|
||||
class TiramisuOptionOption:
|
||||
# config.option(path).option
|
||||
def __init__(self,
|
||||
path: str,
|
||||
schema: Dict) -> None:
|
||||
schema: Dict,
|
||||
model: Dict) -> None:
|
||||
self._path = path
|
||||
self.schema = schema
|
||||
self.model = model
|
||||
|
||||
def doc(self):
|
||||
return self.schema['title']
|
||||
@ -38,6 +45,9 @@ class TiramisuOptionOption:
|
||||
def path(self):
|
||||
return self._path
|
||||
|
||||
def name(self):
|
||||
return self._path.rsplit('.', 1)[-1]
|
||||
|
||||
def isoptiondescription(self):
|
||||
return self.schema['type'] in ['object', 'array']
|
||||
|
||||
@ -69,14 +79,29 @@ class TiramisuOptionOption:
|
||||
return types[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:
|
||||
# config.option(path).property
|
||||
def __init__(self,
|
||||
model: Dict) -> None:
|
||||
self.model = model
|
||||
|
||||
def get(self):
|
||||
properties = self.model.get('properties', [])[:]
|
||||
def get(self, only_raises=False):
|
||||
# FIXME if slave:
|
||||
#if not isslave and childapi.option.ismulti():
|
||||
# if 'empty' in props:
|
||||
@ -85,33 +110,54 @@ class TiramisuOptionProperty:
|
||||
# if 'mandatory' in props:
|
||||
# obj['needs_len'] = True
|
||||
# props.remove('mandatory')
|
||||
if self.model.get('required', False):
|
||||
properties.append('mandatory')
|
||||
if self.model.get('readOnly', False):
|
||||
properties.append('frozen')
|
||||
if not only_raises:
|
||||
properties = self.model.get('properties', [])[:]
|
||||
if self.model.get('required', False):
|
||||
properties.append('mandatory')
|
||||
if self.model.get('readOnly', False):
|
||||
properties.append('frozen')
|
||||
else:
|
||||
properties = []
|
||||
if self.model.get('hidden', False):
|
||||
properties.append('hidden')
|
||||
return properties
|
||||
|
||||
|
||||
class TiramisuOptionValue:
|
||||
def __init__(self,
|
||||
config: 'Config',
|
||||
schema: Dict,
|
||||
model: List[Dict],
|
||||
form: List[Dict],
|
||||
temp: List[Dict],
|
||||
path: str,
|
||||
index: int) -> None:
|
||||
self.config = config
|
||||
self.schema = schema
|
||||
self.model = model
|
||||
self.form = form
|
||||
self.temp = temp
|
||||
self.path = path
|
||||
self.index = index
|
||||
class _Value:
|
||||
def _dict_walk(self,
|
||||
ret: Dict,
|
||||
schema: Dict,
|
||||
root: str,
|
||||
fullpath: bool,
|
||||
withwarning: bool):
|
||||
for key, option in schema['properties'].items():
|
||||
hidden = self.temp.get(key, {}).get('hidden', None)
|
||||
model_hidden = not self.model.get(key, {}).get('hidden', False) and \
|
||||
self.model.get(key, {}).get('display', True)
|
||||
if hidden is False or (hidden is None and model_hidden):
|
||||
if option['type'] == 'object':
|
||||
self._dict_walk(ret,
|
||||
option,
|
||||
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'):
|
||||
for err in self.model.get(path, {}).get('error'):
|
||||
warnings.warn_explicit(ValueOptionError(value,
|
||||
@ -121,28 +167,13 @@ class TiramisuOptionValue:
|
||||
ValueErrorWarning,
|
||||
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'):
|
||||
warnings.warn_explicit(ValueWarning('{0}'.format(warn),
|
||||
Option(name, path)),
|
||||
ValueWarning,
|
||||
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,
|
||||
path: str,
|
||||
schema: Dict) -> Any:
|
||||
@ -154,14 +185,26 @@ class TiramisuOptionValue:
|
||||
value = []
|
||||
return value
|
||||
|
||||
def dict(self,
|
||||
fullpath: bool=False,
|
||||
withwarning: bool=False):
|
||||
if not fullpath or not withwarning:
|
||||
raise NotImplementedError()
|
||||
ret = {}
|
||||
self._dict_walk(ret, self.schema)
|
||||
return ret
|
||||
|
||||
class TiramisuOptionValue(_Value):
|
||||
# config.option(path).value
|
||||
def __init__(self,
|
||||
config: 'Config',
|
||||
schema: Dict,
|
||||
model: List[Dict],
|
||||
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:
|
||||
value = self._get_value(self.path, self.schema)
|
||||
@ -184,7 +227,75 @@ class TiramisuOptionValue:
|
||||
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:
|
||||
# config.option(path) (with path == Option)
|
||||
def __init__(self,
|
||||
config: 'Config',
|
||||
schema: Dict,
|
||||
@ -207,7 +318,8 @@ class TiramisuOption:
|
||||
if self.index != None:
|
||||
raise NotImplementedError()
|
||||
return TiramisuOptionOption(self.path,
|
||||
self.schema)
|
||||
self.schema,
|
||||
self.model)
|
||||
if subfunc == 'value':
|
||||
return TiramisuOptionValue(self.config,
|
||||
self.schema,
|
||||
@ -222,34 +334,9 @@ class TiramisuOption:
|
||||
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')
|
||||
|
||||
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:
|
||||
# config.property
|
||||
# def __init__(self,
|
||||
# json):
|
||||
# self.json = json
|
||||
@ -259,7 +346,63 @@ class TiramisuContextProperty:
|
||||
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:
|
||||
# config
|
||||
def __init__(self,
|
||||
json):
|
||||
self.model_ori = json['model']
|
||||
@ -273,43 +416,31 @@ class Config:
|
||||
self.temp = {}
|
||||
self.schema = json['schema']
|
||||
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,
|
||||
subfunc: str) -> Any:
|
||||
if subfunc == 'property':
|
||||
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))
|
||||
|
||||
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,
|
||||
path: str,
|
||||
index: Optional[int],
|
||||
@ -360,21 +491,20 @@ class Config:
|
||||
|
||||
def get_schema(self,
|
||||
path):
|
||||
first_path = next(iter(self.schema.keys()))
|
||||
if '.' in first_path:
|
||||
root = first_path.rsplit('.', 1)[0].split('.')
|
||||
root_path = self.root
|
||||
if root_path:
|
||||
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:
|
||||
root = []
|
||||
|
||||
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]
|
||||
schema = self.schema[path]
|
||||
return schema
|
||||
|
||||
|
||||
@ -411,7 +541,7 @@ class Config:
|
||||
last_body['action'] == 'modify' and action == 'delete':
|
||||
update_last_action = True
|
||||
elif last_body['action'] == 'add' and action == 'delete':
|
||||
del this.updates[-1]
|
||||
del self.updates[-1]
|
||||
|
||||
if update_last_action:
|
||||
if value is None:
|
||||
|
Loading…
Reference in New Issue
Block a user