|
@@ -1,6 +1,9 @@
|
|
|
|
+import json
|
|
|
|
+import pickle
|
|
from pathlib import Path
|
|
from pathlib import Path
|
|
|
|
|
|
from metadocker.common.errors import MetadockerError
|
|
from metadocker.common.errors import MetadockerError
|
|
|
|
+from metadocker.common.misc import flatten
|
|
|
|
|
|
NoneType=None.__class__
|
|
NoneType=None.__class__
|
|
|
|
|
|
@@ -13,12 +16,10 @@ def NotEmpty(x):
|
|
raise Var.ValidationException(None, f"doit être non vide")
|
|
raise Var.ValidationException(None, f"doit être non vide")
|
|
return x
|
|
return x
|
|
|
|
|
|
-def get_types(x):
|
|
|
|
- if x is None:
|
|
|
|
- return tuple()
|
|
|
|
- if not isinstance(x, (list, tuple, set)):
|
|
|
|
- return (x,)
|
|
|
|
- return x
|
|
|
|
|
|
+def get_types(types):
|
|
|
|
+ if not isinstance(types, (tuple, list, set)):
|
|
|
|
+ types = [types]
|
|
|
|
+ return tuple([x.__class__ if not isinstance(x, type) else x for x in types])
|
|
|
|
|
|
class EmptyObject:
|
|
class EmptyObject:
|
|
def __init__(self, **kwargs):
|
|
def __init__(self, **kwargs):
|
|
@@ -26,7 +27,9 @@ class EmptyObject:
|
|
setattr(self, k, v)
|
|
setattr(self, k, v)
|
|
|
|
|
|
class Var:
|
|
class Var:
|
|
-
|
|
|
|
|
|
+ _expected_types_ = []
|
|
|
|
+ def _validate(self, value):
|
|
|
|
+ return value
|
|
class VarException(MetadockerError):
|
|
class VarException(MetadockerError):
|
|
def get_error(self):
|
|
def get_error(self):
|
|
raise NotImplementedError()
|
|
raise NotImplementedError()
|
|
@@ -39,7 +42,7 @@ class Var:
|
|
def get_error(self):
|
|
def get_error(self):
|
|
return f"La variable {self.name} est requise"
|
|
return f"La variable {self.name} est requise"
|
|
|
|
|
|
- class ByPassException(Exception):
|
|
|
|
|
|
+ class ByPassException(MetadockerError):
|
|
pass
|
|
pass
|
|
|
|
|
|
class ValidationException(VarException):
|
|
class ValidationException(VarException):
|
|
@@ -66,22 +69,30 @@ class Var:
|
|
return f"La variable {self.name} doit être de type {'('+', '.join(self.types)+')'}. Type trouvé {self.found.__class__.__name__}"
|
|
return f"La variable {self.name} doit être de type {'('+', '.join(self.types)+')'}. Type trouvé {self.found.__class__.__name__}"
|
|
|
|
|
|
def __init__(self, name, default_value=EmptyValue, required=False, validate=None,
|
|
def __init__(self, name, default_value=EmptyValue, required=False, validate=None,
|
|
- expected_types=None, help=None, is_meta=False, null=False, ask=False):
|
|
|
|
|
|
+ expected_types=None, help=None, is_meta=False, null=False, ask=False, **kwargs):
|
|
self.name = name
|
|
self.name = name
|
|
self.default_value = default_value
|
|
self.default_value = default_value
|
|
self.required = required
|
|
self.required = required
|
|
- self._validate = validate if validate else lambda x: x
|
|
|
|
- self.expected_types = expected_types
|
|
|
|
|
|
+ if validate:
|
|
|
|
+ self._validate = validate
|
|
|
|
+ self.expected_types = get_types(flatten(self._expected_types_ or [], expected_types or []))
|
|
self.help = help
|
|
self.help = help
|
|
- self.null = null
|
|
|
|
|
|
+ self.null = null or self.default_value is None
|
|
self.is_meta = is_meta
|
|
self.is_meta = is_meta
|
|
self.ask = ask
|
|
self.ask = ask
|
|
|
|
+ self.kwargs = kwargs
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def on_error(self, obj, err):
|
|
|
|
+ raise err
|
|
|
|
|
|
@property
|
|
@property
|
|
def has_default(self):
|
|
def has_default(self):
|
|
return self.default_value is not EmptyValue
|
|
return self.default_value is not EmptyValue
|
|
|
|
|
|
- def validate(self, obj):
|
|
|
|
|
|
+ def run_validation(self, obj, is_parent = True):
|
|
|
|
+ if not is_parent:
|
|
|
|
+ obj = EmptyObject(**{self.name : obj})
|
|
if not hasattr(obj, self.name):
|
|
if not hasattr(obj, self.name):
|
|
if self.default_value is EmptyValue:
|
|
if self.default_value is EmptyValue:
|
|
if self.required:
|
|
if self.required:
|
|
@@ -105,12 +116,29 @@ class Var:
|
|
def __repr__(self):
|
|
def __repr__(self):
|
|
return f"<{self.__class__.__name__} {self.name}>"
|
|
return f"<{self.__class__.__name__} {self.name}>"
|
|
|
|
|
|
- def _parse(self, type, value):
|
|
|
|
|
|
+
|
|
|
|
+ def run_to_python(self, value):
|
|
if self.null and value == "None":
|
|
if self.null and value == "None":
|
|
return None
|
|
return None
|
|
- return type(value)
|
|
|
|
|
|
+ return self.to_python(value)
|
|
|
|
+
|
|
|
|
+ def to_python(self, value):
|
|
|
|
+ if not self.expected_types:
|
|
|
|
+ return value
|
|
|
|
+ for t in self.expected_types:
|
|
|
|
+ try:
|
|
|
|
+ v = t(value)
|
|
|
|
+ return self.run_validation(v, is_parent=False)
|
|
|
|
+ except Exception as err:
|
|
|
|
+ continue
|
|
|
|
+
|
|
|
|
+ if self.null and not value:
|
|
|
|
+ return self.default_value
|
|
|
|
+ raise self.ValidationException(self.name, f"Impossible de parser '{value}'")
|
|
|
|
|
|
- def ask_value(self):
|
|
|
|
|
|
+ def ask_value(self, **kwargs):
|
|
|
|
+ has_value = "value" in kwargs
|
|
|
|
+ value = kwargs.get("value")
|
|
while True:
|
|
while True:
|
|
print(self.help)
|
|
print(self.help)
|
|
prompt = [self.name]
|
|
prompt = [self.name]
|
|
@@ -119,24 +147,22 @@ class Var:
|
|
if has_default:
|
|
if has_default:
|
|
prompt.append(f" [{self.default_value}]")
|
|
prompt.append(f" [{self.default_value}]")
|
|
|
|
|
|
- value = input("".join(prompt)+": ")
|
|
|
|
|
|
+ if not has_value:
|
|
|
|
+ value = input("".join(prompt)+": ")
|
|
|
|
+ else:
|
|
|
|
+ print("".join(prompt) + ":", value)
|
|
|
|
+ has_value = False
|
|
|
|
+
|
|
|
|
|
|
if not has_default and not value:
|
|
if not has_default and not value:
|
|
print(f"Merci de donner une réponse")
|
|
print(f"Merci de donner une réponse")
|
|
continue
|
|
continue
|
|
|
|
|
|
- try:
|
|
|
|
- parsed_value = None
|
|
|
|
- for x in self.expected_types or []:
|
|
|
|
- try:
|
|
|
|
- parsed_value = self._parse(x, value)
|
|
|
|
- return self.validate(EmptyObject(**{self.name: parsed_value}))
|
|
|
|
- except: pass
|
|
|
|
- else:
|
|
|
|
- if self.null and not value:
|
|
|
|
- return self.default_value
|
|
|
|
- raise Var.RequiredException(self.name)
|
|
|
|
|
|
+ if value=="":
|
|
|
|
+ return self.default_value
|
|
|
|
|
|
|
|
+ try:
|
|
|
|
+ return self.run_to_python(value)
|
|
except MetadockerError as err:
|
|
except MetadockerError as err:
|
|
if isinstance(err, self.ValidationException):
|
|
if isinstance(err, self.ValidationException):
|
|
err.name = self.name
|
|
err.name = self.name
|
|
@@ -144,35 +170,33 @@ class Var:
|
|
|
|
|
|
|
|
|
|
class VarStr(Var):
|
|
class VarStr(Var):
|
|
- def __init__(self, name, default_value=EmptyValue, required=False, validate=NotEmpty, help=None,
|
|
|
|
- is_meta=False, expected_types=None, null=False, ask=False):
|
|
|
|
- super().__init__(name, default_value, required, validate, help=help,
|
|
|
|
- expected_types=(str, *get_types(expected_types)), is_meta=is_meta,
|
|
|
|
- null=null or default_value is None, ask=ask)
|
|
|
|
|
|
+ _expected_types_ = (str, )
|
|
|
|
|
|
class VarPath(Var):
|
|
class VarPath(Var):
|
|
- def __init__(self, name, default_value=EmptyValue, required=False, validate=None, help=None,
|
|
|
|
- is_meta=False, expected_types=None, null=False, ask=False):
|
|
|
|
- super().__init__(name, default_value, required, help=help, is_meta=is_meta,
|
|
|
|
- validate=validate or (lambda x: Path(x)),
|
|
|
|
- expected_types=(str, Path, *get_types(expected_types)), null=null, ask=ask)
|
|
|
|
-
|
|
|
|
|
|
+ _expected_types_ = (Path, str,)
|
|
|
|
|
|
class VarInt(Var):
|
|
class VarInt(Var):
|
|
- def __init__(self, name, default_value=EmptyValue, required=False, validate=None, help=None,
|
|
|
|
- is_meta=False, expected_types=None, null=False, ask=False):
|
|
|
|
- super().__init__(name, default_value, required, validate, help=help, is_meta=is_meta,
|
|
|
|
- expected_types=(int, *get_types(expected_types)), null=null, ask=ask)
|
|
|
|
|
|
+ _expected_types_ = (int,)
|
|
|
|
|
|
class VarNumber(Var):
|
|
class VarNumber(Var):
|
|
- def __init__(self, name, default_value=EmptyValue, required=False, validate=None, help=None,
|
|
|
|
- is_meta=False, expected_types=None, null=False, ask=False):
|
|
|
|
- super().__init__(name, default_value, required, validate, help=help, is_meta=is_meta,
|
|
|
|
- expected_types=(float, int, *get_types(expected_types)), null=null, ask=ask)
|
|
|
|
|
|
+ _expected_types_ = (float, int,)
|
|
|
|
|
|
class VarDict(Var):
|
|
class VarDict(Var):
|
|
- def __init__(self, name, default_value=EmptyValue, required=False, validate=None, help=None,
|
|
|
|
- is_meta=False, expected_types=None, null=False, ask=False):
|
|
|
|
- super().__init__(name, default_value, required, validate, help=help, is_meta=is_meta,
|
|
|
|
- expected_types=(dict, *get_types(expected_types)), null=null, ask=ask)
|
|
|
|
|
|
+ _expected_types_ = (dict,)
|
|
|
|
+ def to_python(self, value):
|
|
|
|
+ if isinstance(value, (bytes, str)):
|
|
|
|
+ try:
|
|
|
|
+ return self.run_validation(json.loads(value))
|
|
|
|
+ except:
|
|
|
|
+ pass
|
|
|
|
+ if isinstance(value, bytes):
|
|
|
|
+ try:
|
|
|
|
+ return self.run_validation(pickle.loads(value))
|
|
|
|
+ except:
|
|
|
|
+ pass
|
|
|
|
+ return super().to_python(value)
|
|
|
|
+
|
|
|
|
+class VarList(Var):
|
|
|
|
+ _expected_types_ = (list,)
|
|
|
|
+
|
|
|
|
|