_validation, _second_level_validation => validation, second_level_validation
This commit is contained in:
parent
5c3a133928
commit
74e604478e
|
@ -30,9 +30,7 @@ class BoolOption(Option):
|
||||||
_type = 'boolean'
|
_type = 'boolean'
|
||||||
_display_name = _('boolean')
|
_display_name = _('boolean')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: bool,
|
value: bool) -> None:
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, bool):
|
if not isinstance(value, bool):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -31,10 +31,8 @@ class BroadcastOption(Option):
|
||||||
_type = 'broadcast_address'
|
_type = 'broadcast_address'
|
||||||
_display_name = _('broadcast address')
|
_display_name = _('broadcast address')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: str,
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise ValueError(_('invalid string'))
|
raise ValueError(_('invalid string'))
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from types import FunctionType
|
from typing import Any
|
||||||
|
|
||||||
from ..setting import undefined
|
from ..setting import undefined, OptionBag
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from ..autolib import carry_out_calculation, Calculation
|
from ..autolib import Calculation
|
||||||
from ..error import ConfigError, display_list
|
from ..error import ConfigError, display_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,12 +40,8 @@ class ChoiceOption(Option):
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
values,
|
values,
|
||||||
default=None,
|
*args,
|
||||||
default_multi=None,
|
**kwargs):
|
||||||
multi=False,
|
|
||||||
validators=None,
|
|
||||||
properties=None,
|
|
||||||
warnings_only=False):
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
|
@ -56,12 +52,8 @@ class ChoiceOption(Option):
|
||||||
self._choice_values = values
|
self._choice_values = values
|
||||||
super(ChoiceOption, self).__init__(name,
|
super(ChoiceOption, self).__init__(name,
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
*args,
|
||||||
default_multi=default_multi,
|
**kwargs)
|
||||||
multi=multi,
|
|
||||||
validators=validators,
|
|
||||||
properties=properties,
|
|
||||||
warnings_only=warnings_only)
|
|
||||||
|
|
||||||
def impl_get_values(self,
|
def impl_get_values(self,
|
||||||
option_bag):
|
option_bag):
|
||||||
|
@ -74,15 +66,17 @@ class ChoiceOption(Option):
|
||||||
values = self._choice_values
|
values = self._choice_values
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value,
|
value: Any) -> None:
|
||||||
option_bag,
|
pass
|
||||||
current_opt=undefined):
|
|
||||||
|
def validate_with_option(self,
|
||||||
|
value: Any,
|
||||||
|
option_bag: OptionBag) -> None:
|
||||||
values = self.impl_get_values(option_bag)
|
values = self.impl_get_values(option_bag)
|
||||||
if values is not undefined and value not in values:
|
if values is not undefined and value not in values:
|
||||||
if len(values) == 1:
|
if len(values) == 1:
|
||||||
raise ValueError(_('only "{0}" is allowed'
|
raise ValueError(_('only "{0}" is allowed'
|
||||||
'').format(values[0]))
|
'').format(values[0]))
|
||||||
else:
|
raise ValueError(_('only {0} are allowed'
|
||||||
raise ValueError(_('only {0} are allowed'
|
'').format(display_list(values, add_quote=True)))
|
||||||
'').format(display_list(values, add_quote=True)))
|
|
||||||
|
|
|
@ -22,20 +22,17 @@ from datetime import datetime
|
||||||
|
|
||||||
from ..setting import undefined, Undefined, OptionBag
|
from ..setting import undefined, Undefined, OptionBag
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class DateOption(Option):
|
class DateOption(StrOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = 'date'
|
_type = 'date'
|
||||||
_display_name = _('date')
|
_display_name = _('date')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: str,
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
super().validate(value)
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
try:
|
try:
|
||||||
datetime.strptime(value, "%Y-%m-%d")
|
datetime.strptime(value, "%Y-%m-%d")
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
|
@ -19,14 +19,18 @@
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import re
|
import re
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_interface
|
||||||
from ..setting import undefined, Undefined, OptionBag
|
from typing import Any, Optional, List
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from ..setting import undefined
|
||||||
from .ipoption import IPOption
|
from .ipoption import IPOption
|
||||||
|
from .stroption import StrOption
|
||||||
|
from .networkoption import NetworkOption
|
||||||
|
from .option import Calculation
|
||||||
|
|
||||||
|
|
||||||
class DomainnameOption(IPOption):
|
class DomainnameOption(StrOption):
|
||||||
"""represents the choice of a domain name
|
"""represents the choice of a domain name
|
||||||
netbios: for MS domain
|
netbios: for MS domain
|
||||||
hostname: to identify the device
|
hostname: to identify the device
|
||||||
|
@ -38,53 +42,63 @@ class DomainnameOption(IPOption):
|
||||||
_display_name = _('domain name')
|
_display_name = _('domain name')
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
name: str,
|
||||||
doc,
|
doc: str,
|
||||||
default=None,
|
default: Any=undefined,
|
||||||
default_multi=None,
|
default_multi: Any=None,
|
||||||
multi: bool=False,
|
multi: bool=False,
|
||||||
validators=None,
|
validators: Optional[List[Calculation]]=None,
|
||||||
properties=None,
|
properties: Optional[List[str]]=None,
|
||||||
allow_ip: bool=False,
|
|
||||||
cidr: bool=False,
|
|
||||||
type_: str='domainname',
|
|
||||||
warnings_only: bool=False,
|
warnings_only: bool=False,
|
||||||
allow_without_dot=False) -> None:
|
allow_ip: bool=False,
|
||||||
|
allow_network: bool=False,
|
||||||
|
network_cidr: bool=False,
|
||||||
|
type: str='domainname',
|
||||||
|
allow_without_dot: bool=False,
|
||||||
|
allow_startswith_dot: bool=False) -> None:
|
||||||
|
|
||||||
if type_ not in ['netbios', 'hostname', 'domainname']:
|
if type not in ['netbios', 'hostname', 'domainname']:
|
||||||
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
raise ValueError(_('unknown type {0} for hostname').format(type))
|
||||||
extra = {'_dom_type': type_}
|
extra = {'_dom_type': type}
|
||||||
if allow_ip not in [True, False]:
|
if not isinstance(allow_ip, bool):
|
||||||
raise ValueError(_('allow_ip must be a boolean'))
|
raise ValueError(_('allow_ip must be a boolean'))
|
||||||
if allow_without_dot not in [True, False]:
|
if not isinstance(allow_network, bool):
|
||||||
|
raise ValueError(_('allow_network must be a boolean'))
|
||||||
|
if not isinstance(allow_without_dot, bool):
|
||||||
raise ValueError(_('allow_without_dot must be a boolean'))
|
raise ValueError(_('allow_without_dot must be a boolean'))
|
||||||
extra['_allow_ip'] = allow_ip
|
if not isinstance(allow_startswith_dot, bool):
|
||||||
|
raise ValueError(_('allow_startswith_dot must be a boolean'))
|
||||||
extra['_allow_without_dot'] = allow_without_dot
|
extra['_allow_without_dot'] = allow_without_dot
|
||||||
if type_ == 'domainname':
|
if type == 'domainname':
|
||||||
if allow_without_dot:
|
if allow_without_dot:
|
||||||
min_time = 0
|
min_time = 0
|
||||||
else:
|
else:
|
||||||
min_time = 1
|
min_time = 1
|
||||||
regexp = r'((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}'.format(self._get_len(type_), min_time)
|
regexp = r'((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}'.format(self._get_len(type), min_time)
|
||||||
msg = _('only lowercase, number, "-" and "." are characters are allowed')
|
msg = _('only lowercase, number, "-" and "." characters are allowed')
|
||||||
msg_warning = _('only lowercase, number, "-" and "." are characters are recommanded')
|
msg_warning = _('only lowercase, number, "-" and "." characters are recommanded')
|
||||||
else:
|
else:
|
||||||
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type_))
|
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type))
|
||||||
msg = _('only lowercase, number and - are characters are allowed')
|
msg = _('only lowercase, number and "-" characters are allowed')
|
||||||
msg_warning = _('only lowercase, number and "-" are characters are recommanded')
|
msg_warning = _('only lowercase, number and "-" characters are recommanded')
|
||||||
if allow_ip:
|
if allow_ip:
|
||||||
msg = _('could be a IP, otherwise {}').format(msg)
|
msg = _('could be a IP, otherwise {}').format(msg)
|
||||||
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
||||||
if not cidr:
|
regexp = r'^{0}$'.format(regexp)
|
||||||
regexp = r'^(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))$'.format(regexp)
|
|
||||||
else:
|
|
||||||
regexp = r'^(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[0-9][0-9]))$'.format(regexp)
|
|
||||||
else:
|
|
||||||
regexp = r'^{0}$'.format(regexp)
|
|
||||||
extra['_domain_re'] = re.compile(regexp)
|
extra['_domain_re'] = re.compile(regexp)
|
||||||
extra['_domain_re_message'] = msg
|
extra['_domain_re_message'] = msg
|
||||||
extra['_domain_re_message_warning'] = msg_warning
|
extra['_domain_re_message_warning'] = msg_warning
|
||||||
extra['_has_upper'] = re.compile('[A-Z]')
|
extra['_has_upper'] = re.compile('[A-Z]')
|
||||||
|
if allow_ip:
|
||||||
|
extra['_ip'] = IPOption(name,
|
||||||
|
doc)
|
||||||
|
extra['_allow_ip'] = allow_ip
|
||||||
|
if allow_network:
|
||||||
|
extra['_network'] = NetworkOption(name,
|
||||||
|
doc,
|
||||||
|
cidr=network_cidr)
|
||||||
|
extra['_allow_network'] = allow_network
|
||||||
|
extra['_allow_startswith_dot'] = allow_startswith_dot
|
||||||
|
|
||||||
super().__init__(name,
|
super().__init__(name,
|
||||||
doc,
|
doc,
|
||||||
|
@ -94,19 +108,16 @@ class DomainnameOption(IPOption):
|
||||||
validators=validators,
|
validators=validators,
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only,
|
||||||
cidr=cidr,
|
extra=extra)
|
||||||
_extra=extra)
|
|
||||||
|
|
||||||
def _get_len(self, type_):
|
def _get_len(self, type):
|
||||||
if type_ == 'netbios':
|
if type == 'netbios':
|
||||||
return 15
|
return 15
|
||||||
else:
|
else:
|
||||||
return 63
|
return 63
|
||||||
|
|
||||||
def _validate(self,
|
def _validate_domain(self,
|
||||||
value: str,
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
def _valid_length(val):
|
def _valid_length(val):
|
||||||
if len(val) < 1:
|
if len(val) < 1:
|
||||||
raise ValueError(_("invalid length (min 1)"))
|
raise ValueError(_("invalid length (min 1)"))
|
||||||
|
@ -114,33 +125,83 @@ class DomainnameOption(IPOption):
|
||||||
raise ValueError(_("invalid length (max {0})"
|
raise ValueError(_("invalid length (max {0})"
|
||||||
"").format(part_name_length))
|
"").format(part_name_length))
|
||||||
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
try:
|
|
||||||
ip_address(value)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if self.impl_get_extra('_allow_ip') is False:
|
|
||||||
raise ValueError(_('must not be an IP'))
|
|
||||||
# it's an IP so validate with IPOption
|
|
||||||
return super()._validate(value, option_bag, current_opt)
|
|
||||||
part_name_length = self._get_len(self.impl_get_extra('_dom_type'))
|
part_name_length = self._get_len(self.impl_get_extra('_dom_type'))
|
||||||
if self.impl_get_extra('_dom_type') == 'domainname':
|
if self.impl_get_extra('_dom_type') == 'domainname':
|
||||||
if not self.impl_get_extra('_allow_without_dot') and not "." in value:
|
if not self.impl_get_extra('_allow_without_dot') and not "." in value:
|
||||||
raise ValueError(_("must have dot"))
|
raise ValueError(_("must have dot"))
|
||||||
if len(value) > 255:
|
if len(value) > 255:
|
||||||
raise ValueError(_("invalid length (max 255)"))
|
raise ValueError(_("invalid length (max 255)"))
|
||||||
for dom in value.split('.'):
|
if self.impl_get_extra('_allow_startswith_dot') and value.startswith('.'):
|
||||||
|
val = value[1:]
|
||||||
|
else:
|
||||||
|
val = value
|
||||||
|
for dom in val.split('.'):
|
||||||
_valid_length(dom)
|
_valid_length(dom)
|
||||||
else:
|
else:
|
||||||
_valid_length(value)
|
_valid_length(value)
|
||||||
|
|
||||||
def _second_level_validation(self, value, warnings_only):
|
def _validate_ip_network(self,
|
||||||
|
value: str) -> None:
|
||||||
|
allow_ip = self.impl_get_extra('_allow_ip')
|
||||||
|
allow_network = self.impl_get_extra('_allow_network')
|
||||||
|
if allow_ip is False and allow_network is False:
|
||||||
|
raise ValueError(_('must not be an IP'))
|
||||||
|
if allow_ip is True:
|
||||||
|
try:
|
||||||
|
self.impl_get_extra('_ip').validate(value)
|
||||||
|
return
|
||||||
|
except ValueError as err:
|
||||||
|
if allow_network is False:
|
||||||
|
raise err
|
||||||
|
if allow_network is True:
|
||||||
|
self.impl_get_extra('_network').validate(value)
|
||||||
|
|
||||||
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
|
super().validate(value)
|
||||||
|
try:
|
||||||
|
# check if it's an IP or network
|
||||||
|
ip_interface(value)
|
||||||
|
except ValueError:
|
||||||
|
self._validate_domain(value)
|
||||||
|
else:
|
||||||
|
self._validate_ip_network(value)
|
||||||
|
|
||||||
|
def _second_level_validation_domain(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
if self.impl_get_extra('_has_upper').search(value):
|
if self.impl_get_extra('_has_upper').search(value):
|
||||||
raise ValueError(_('some characters are uppercase'))
|
raise ValueError(_('some characters are uppercase'))
|
||||||
if not self.impl_get_extra('_domain_re').search(value):
|
if not self.impl_get_extra('_domain_re').search(value):
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
raise ValueError(self.impl_get_extra('_domain_re_message_warning'))
|
raise ValueError(self.impl_get_extra('_domain_re_message_warning'))
|
||||||
else:
|
raise ValueError(self.impl_get_extra('_domain_re_message'))
|
||||||
raise ValueError(self.impl_get_extra('_domain_re_message'))
|
|
||||||
|
def _second_level_validation_ip_network(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
|
allow_ip = self.impl_get_extra('_allow_ip')
|
||||||
|
allow_network = self.impl_get_extra('_allow_network')
|
||||||
|
# it's an IP so validate with IPOption
|
||||||
|
if allow_ip is False and allow_network is False:
|
||||||
|
raise ValueError(_('must not be an IP'))
|
||||||
|
if allow_ip is True:
|
||||||
|
try:
|
||||||
|
self.impl_get_extra('_ip').second_level_validation(value, warnings_only)
|
||||||
|
return
|
||||||
|
except ValueError as err:
|
||||||
|
if allow_network is False:
|
||||||
|
raise err
|
||||||
|
if allow_network is True:
|
||||||
|
self.impl_get_extra('_network').second_level_validation(value, warnings_only)
|
||||||
|
|
||||||
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
|
try:
|
||||||
|
# check if it's an IP or network
|
||||||
|
ip_interface(value)
|
||||||
|
except ValueError:
|
||||||
|
self._second_level_validation_domain(value, warnings_only)
|
||||||
|
else:
|
||||||
|
self._second_level_validation_ip_network(value, warnings_only)
|
||||||
|
|
|
@ -26,7 +26,6 @@ from .stroption import RegexpOption
|
||||||
|
|
||||||
class EmailOption(RegexpOption):
|
class EmailOption(RegexpOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
#https://www.w3.org/TR/html-markup/input.email.html#input.email.attrs.value.single.
|
|
||||||
_regexp = re.compile(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
_regexp = re.compile(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||||
_type = 'email'
|
_type = 'email'
|
||||||
_display_name = _('email address')
|
_display_name = _('email address')
|
||||||
|
|
|
@ -30,9 +30,7 @@ class FloatOption(Option):
|
||||||
_type = 'float'
|
_type = 'float'
|
||||||
_display_name = _('float')
|
_display_name = _('float')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: float,
|
value: float) -> None:
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, float):
|
if not isinstance(value, float):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -31,7 +31,6 @@ class IntOption(Option):
|
||||||
_display_name = _('integer')
|
_display_name = _('integer')
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
|
||||||
*args,
|
*args,
|
||||||
min_number=None,
|
min_number=None,
|
||||||
max_number=None,
|
max_number=None,
|
||||||
|
@ -41,18 +40,27 @@ class IntOption(Option):
|
||||||
extra['min_number'] = min_number
|
extra['min_number'] = min_number
|
||||||
if max_number is not None:
|
if max_number is not None:
|
||||||
extra['max_number'] = max_number
|
extra['max_number'] = max_number
|
||||||
super().__init__(name, extra=extra, *args, **kwargs)
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
|
def validate(self,
|
||||||
def _validate(self,
|
value: int) -> None:
|
||||||
value: int,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
|
def second_level_validation(self,
|
||||||
|
value,
|
||||||
|
warnings_only):
|
||||||
min_number = self.impl_get_extra('min_number')
|
min_number = self.impl_get_extra('min_number')
|
||||||
if min_number is not None and value < min_number:
|
if min_number is not None and value < min_number:
|
||||||
raise ValueError(_('value must be greater than "{0}"').format(min_number))
|
if warnings_only:
|
||||||
|
msg = 'value should be greater than "{0}"'
|
||||||
|
else:
|
||||||
|
msg = 'value must be greater than "{0}"'
|
||||||
|
raise ValueError(_(msg).format(min_number))
|
||||||
max_number = self.impl_get_extra('max_number')
|
max_number = self.impl_get_extra('max_number')
|
||||||
if max_number is not None and value > max_number:
|
if max_number is not None and value > max_number:
|
||||||
raise ValueError(_('value must be less than "{0}"').format(max_number))
|
if warnings_only:
|
||||||
|
msg = 'value should be less than "{0}"'
|
||||||
|
else:
|
||||||
|
msg = 'value must be less than "{0}"'
|
||||||
|
raise ValueError(_(msg).format(max_number))
|
||||||
|
|
|
@ -35,69 +35,48 @@ class IPOption(StrOption):
|
||||||
_display_name = _('IP')
|
_display_name = _('IP')
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
*args,
|
||||||
doc,
|
|
||||||
default=None,
|
|
||||||
default_multi=None,
|
|
||||||
multi=False,
|
|
||||||
validators=None,
|
|
||||||
properties=None,
|
|
||||||
private_only=False,
|
private_only=False,
|
||||||
allow_reserved=False,
|
allow_reserved=False,
|
||||||
warnings_only=False,
|
|
||||||
cidr=False,
|
cidr=False,
|
||||||
_extra=None):
|
extra=None,
|
||||||
if _extra is None:
|
**kwargs):
|
||||||
|
if extra is None:
|
||||||
extra = {}
|
extra = {}
|
||||||
else:
|
|
||||||
extra = _extra
|
|
||||||
extra['_private_only'] = private_only
|
extra['_private_only'] = private_only
|
||||||
extra['_allow_reserved'] = allow_reserved
|
extra['_allow_reserved'] = allow_reserved
|
||||||
extra['_cidr'] = cidr
|
extra['_cidr'] = cidr
|
||||||
super().__init__(name,
|
super().__init__(*args,
|
||||||
doc,
|
extra=extra,
|
||||||
default=default,
|
**kwargs)
|
||||||
default_multi=default_multi,
|
|
||||||
multi=multi,
|
|
||||||
validators=validators,
|
|
||||||
properties=properties,
|
|
||||||
warnings_only=warnings_only,
|
|
||||||
extra=extra)
|
|
||||||
|
|
||||||
def _validate(self,
|
def _validate_cidr(self, value):
|
||||||
value: str,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
# sometimes an ip term starts with a zero
|
|
||||||
# but this does not fit in some case, for example bind does not like it
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
if value.count('.') != 3:
|
|
||||||
raise ValueError()
|
|
||||||
cidr = self.impl_get_extra('_cidr')
|
|
||||||
if cidr:
|
|
||||||
if '/' not in value:
|
|
||||||
raise ValueError(_('must use CIDR notation'))
|
|
||||||
value_ = value.split('/')[0]
|
|
||||||
else:
|
|
||||||
value_ = value
|
|
||||||
for val in value_.split('.'):
|
|
||||||
if val.startswith("0") and len(val) > 1:
|
|
||||||
raise ValueError()
|
|
||||||
# 'standard' validation
|
|
||||||
try:
|
try:
|
||||||
if not cidr:
|
ip = ip_interface(value)
|
||||||
ip_address(value)
|
|
||||||
else:
|
|
||||||
ip = ip_interface(value)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
if cidr:
|
if ip.ip == ip.network.network_address:
|
||||||
valid_ip_netmask(str(ip.ip), str(ip.netmask))
|
raise ValueError(_("it's in fact a network address"))
|
||||||
|
elif ip.ip == ip.network.broadcast_address:
|
||||||
|
raise ValueError(_("it's in fact a broacast address"))
|
||||||
|
|
||||||
def _second_level_validation(self,
|
def _validate_ip(self, value):
|
||||||
value,
|
try:
|
||||||
warnings_only):
|
ip_address(value)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError()
|
||||||
|
|
||||||
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
|
super().validate(value)
|
||||||
|
if self.impl_get_extra('_cidr'):
|
||||||
|
self._validate_cidr(value)
|
||||||
|
else:
|
||||||
|
self._validate_ip(value)
|
||||||
|
|
||||||
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
ip = ip_interface(value)
|
ip = ip_interface(value)
|
||||||
if not self.impl_get_extra('_allow_reserved') and ip.is_reserved:
|
if not self.impl_get_extra('_allow_reserved') and ip.is_reserved:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
|
|
|
@ -34,14 +34,9 @@ class NetmaskOption(StrOption):
|
||||||
_type = 'netmask'
|
_type = 'netmask'
|
||||||
_display_name = _('netmask address')
|
_display_name = _('netmask address')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: str,
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
super().validate(value)
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
if value.count('.') != 3:
|
|
||||||
raise ValueError()
|
|
||||||
for val in value.split('.'):
|
for val in value.split('.'):
|
||||||
if val.startswith("0") and len(val) > 1:
|
if val.startswith("0") and len(val) > 1:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -20,44 +20,28 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from ipaddress import ip_address, ip_network
|
from ipaddress import ip_address, ip_network
|
||||||
|
|
||||||
from ..setting import undefined
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class NetworkOption(Option):
|
class NetworkOption(StrOption):
|
||||||
"represents the choice of a network"
|
"represents the choice of a network"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = 'network'
|
_type = 'network'
|
||||||
_display_name = _('network address')
|
_display_name = _('network address')
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
*args,
|
||||||
doc,
|
cidr=False,
|
||||||
default=None,
|
**kwargs):
|
||||||
default_multi=None,
|
|
||||||
multi=False,
|
|
||||||
validators=None,
|
|
||||||
properties=None,
|
|
||||||
warnings_only=False,
|
|
||||||
cidr=False):
|
|
||||||
extra = {'_cidr': cidr}
|
extra = {'_cidr': cidr}
|
||||||
super().__init__(name,
|
super().__init__(*args,
|
||||||
doc,
|
extra=extra,
|
||||||
default=default,
|
**kwargs)
|
||||||
default_multi=default_multi,
|
|
||||||
multi=multi,
|
|
||||||
validators=validators,
|
|
||||||
properties=properties,
|
|
||||||
warnings_only=warnings_only,
|
|
||||||
extra=extra)
|
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value,
|
value: str) -> None:
|
||||||
*args,
|
super().validate(value)
|
||||||
**kwargs):
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
if value.count('.') != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
cidr = self.impl_get_extra('_cidr')
|
cidr = self.impl_get_extra('_cidr')
|
||||||
|
@ -75,9 +59,9 @@ class NetworkOption(Option):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def _second_level_validation(self,
|
def second_level_validation(self,
|
||||||
value,
|
value: str,
|
||||||
warnings_only):
|
warnings_only: bool) -> None:
|
||||||
if ip_network(value).network_address.is_reserved:
|
if ip_network(value).network_address.is_reserved:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("shouldn't be reserved network")
|
msg = _("shouldn't be reserved network")
|
||||||
|
|
|
@ -30,10 +30,3 @@ class PasswordOption(StrOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = 'password'
|
_type = 'password'
|
||||||
_display_name = _('password')
|
_display_name = _('password')
|
||||||
|
|
||||||
def _validate(self,
|
|
||||||
value: str,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from ..setting import undefined, Undefined, OptionBag
|
from ..setting import undefined, Undefined, OptionBag
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
|
@ -44,19 +43,13 @@ class PortOption(StrOption):
|
||||||
_display_name = _('port')
|
_display_name = _('port')
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name,
|
*args,
|
||||||
doc,
|
allow_range: bool=False,
|
||||||
default=None,
|
allow_zero: bool=False,
|
||||||
default_multi=None,
|
allow_wellknown: bool=True,
|
||||||
multi=False,
|
allow_registred: bool=True,
|
||||||
validators=None,
|
allow_private: bool=False,
|
||||||
properties=None,
|
**kwargs) -> None:
|
||||||
allow_range=False,
|
|
||||||
allow_zero=False,
|
|
||||||
allow_wellknown=True,
|
|
||||||
allow_registred=True,
|
|
||||||
allow_private=False,
|
|
||||||
warnings_only=False):
|
|
||||||
|
|
||||||
extra = {'_allow_range': allow_range,
|
extra = {'_allow_range': allow_range,
|
||||||
'_min_value': None,
|
'_min_value': None,
|
||||||
|
@ -81,24 +74,15 @@ class PortOption(StrOption):
|
||||||
if extra['_max_value'] is None:
|
if extra['_max_value'] is None:
|
||||||
raise ValueError(_('max value is empty'))
|
raise ValueError(_('max value is empty'))
|
||||||
|
|
||||||
super(PortOption, self).__init__(name,
|
super().__init__(*args,
|
||||||
doc,
|
extra=extra,
|
||||||
default=default,
|
**kwargs)
|
||||||
default_multi=default_multi,
|
|
||||||
multi=multi,
|
|
||||||
validators=validators,
|
|
||||||
properties=properties,
|
|
||||||
warnings_only=warnings_only,
|
|
||||||
extra=extra)
|
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: Union[int,str],
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
super().validate(value)
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
|
||||||
raise ValueError(_('invalid string'))
|
|
||||||
if self.impl_get_extra('_allow_range') and ":" in str(value):
|
if self.impl_get_extra('_allow_range') and ":" in str(value):
|
||||||
value = str(value).split(':')
|
value = value.split(':')
|
||||||
if len(value) != 2:
|
if len(value) != 2:
|
||||||
raise ValueError(_('range must have two values only'))
|
raise ValueError(_('range must have two values only'))
|
||||||
if not value[0] < value[1]:
|
if not value[0] < value[1]:
|
||||||
|
@ -110,8 +94,16 @@ class PortOption(StrOption):
|
||||||
for val in value:
|
for val in value:
|
||||||
if not self.port_re.search(val):
|
if not self.port_re.search(val):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
|
for val in value.split(':'):
|
||||||
val = int(val)
|
val = int(val)
|
||||||
if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'):
|
if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'):
|
||||||
raise ValueError(_('must be an integer between {0} '
|
if warnings_only:
|
||||||
'and {1}').format(self.impl_get_extra('_min_value'),
|
msg = 'should be between {0} and {1}'
|
||||||
self.impl_get_extra('_max_value')))
|
else:
|
||||||
|
msg = 'must be between {0} and {1}'
|
||||||
|
raise ValueError(_(msg).format(self.impl_get_extra('_min_value'),
|
||||||
|
self.impl_get_extra('_max_value')))
|
||||||
|
|
|
@ -32,10 +32,8 @@ class StrOption(Option):
|
||||||
_type = 'string'
|
_type = 'string'
|
||||||
_display_name = _('string')
|
_display_name = _('string')
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: str,
|
value: str) -> None:
|
||||||
option_bag: OptionBag,
|
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
|
@ -47,11 +45,9 @@ UnicodeOption = StrOption
|
||||||
class RegexpOption(StrOption):
|
class RegexpOption(StrOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def _validate(self,
|
def validate(self,
|
||||||
value: Any,
|
value: Any) -> None:
|
||||||
option_bag: OptionBag,
|
super().validate(value)
|
||||||
current_opt: Option=Undefined) -> None:
|
|
||||||
super()._validate(value, option_bag, current_opt)
|
|
||||||
match = self._regexp.search(value)
|
match = self._regexp.search(value)
|
||||||
if not match:
|
if not match:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -19,31 +19,75 @@
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import re
|
import re
|
||||||
|
from typing import Any, Optional, List, Dict
|
||||||
|
|
||||||
from ..setting import undefined, Undefined, OptionBag
|
from ..setting import undefined, Undefined, OptionBag
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option, Calculation
|
||||||
|
from .stroption import StrOption
|
||||||
from .domainnameoption import DomainnameOption
|
from .domainnameoption import DomainnameOption
|
||||||
|
from .portoption import PortOption
|
||||||
|
|
||||||
|
|
||||||
class URLOption(DomainnameOption):
|
class URLOption(StrOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
proto_re = re.compile(r'(http|https)://')
|
|
||||||
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||||
_type = 'url'
|
_type = 'url'
|
||||||
_display_name = _('URL')
|
_display_name = _('URL')
|
||||||
|
|
||||||
def _validate(self,
|
def __init__(self,
|
||||||
value: str,
|
name: str,
|
||||||
option_bag: OptionBag,
|
doc: str,
|
||||||
current_opt: Option=Undefined) -> None:
|
default: Any=undefined,
|
||||||
if not isinstance(value, str):
|
default_multi: Any=None,
|
||||||
raise ValueError(_('invalid string'))
|
multi: bool=False,
|
||||||
match = self.proto_re.search(value)
|
validators: Optional[List[Calculation]]=None,
|
||||||
if not match:
|
properties: Optional[List[str]]=None,
|
||||||
|
warnings_only: bool=False,
|
||||||
|
extra: Optional[Dict]=None,
|
||||||
|
allow_ip: bool=False,
|
||||||
|
type: str='domainname',
|
||||||
|
allow_without_dot=False,
|
||||||
|
allow_range: bool=False,
|
||||||
|
allow_zero: bool=False,
|
||||||
|
allow_wellknown: bool=True,
|
||||||
|
allow_registred: bool=True,
|
||||||
|
allow_private: bool=False) -> None:
|
||||||
|
|
||||||
|
|
||||||
|
extra = {'_domainname': DomainnameOption(name,
|
||||||
|
doc,
|
||||||
|
allow_ip=allow_ip,
|
||||||
|
type=type,
|
||||||
|
allow_without_dot=allow_without_dot),
|
||||||
|
'_port': PortOption(name,
|
||||||
|
doc,
|
||||||
|
allow_range=allow_range,
|
||||||
|
allow_zero=allow_zero,
|
||||||
|
allow_wellknown=allow_wellknown,
|
||||||
|
allow_registred=allow_registred,
|
||||||
|
allow_private=allow_private)}
|
||||||
|
super().__init__(name,
|
||||||
|
doc,
|
||||||
|
default=default,
|
||||||
|
default_multi=default_multi,
|
||||||
|
multi=multi,
|
||||||
|
validators=validators,
|
||||||
|
properties=properties,
|
||||||
|
warnings_only=warnings_only,
|
||||||
|
extra=extra)
|
||||||
|
|
||||||
|
def _get_domain_port_files(self,
|
||||||
|
value: str) -> (str, str):
|
||||||
|
if value.startswith('http://'):
|
||||||
|
type = 'http'
|
||||||
|
value = value[7:]
|
||||||
|
elif value.startswith('https://'):
|
||||||
|
type = 'https'
|
||||||
|
value = value[8:]
|
||||||
|
else:
|
||||||
raise ValueError(_('must start with http:// or '
|
raise ValueError(_('must start with http:// or '
|
||||||
'https://'))
|
'https://'))
|
||||||
value = value[len(match.group(0)):]
|
|
||||||
# get domain/files
|
# get domain/files
|
||||||
splitted = value.split('/', 1)
|
splitted = value.split('/', 1)
|
||||||
if len(splitted) == 1:
|
if len(splitted) == 1:
|
||||||
|
@ -55,20 +99,31 @@ class URLOption(DomainnameOption):
|
||||||
splitted = domain.split(':', 1)
|
splitted = domain.split(':', 1)
|
||||||
if len(splitted) == 1:
|
if len(splitted) == 1:
|
||||||
domain = splitted[0]
|
domain = splitted[0]
|
||||||
port = 0
|
port = {'http': '80',
|
||||||
|
'https': '443'}[type]
|
||||||
else:
|
else:
|
||||||
domain, port = splitted
|
domain, port = splitted
|
||||||
if not 0 <= int(port) <= 65535:
|
return domain, port, files
|
||||||
raise ValueError(_('port must be an between 0 and '
|
|
||||||
'65536'))
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
|
super().validate(value)
|
||||||
|
domain, port, files = self._get_domain_port_files(value)
|
||||||
|
# validate port
|
||||||
|
portoption = self.impl_get_extra('_port')
|
||||||
|
portoption.validate(port)
|
||||||
# validate domainname
|
# validate domainname
|
||||||
super(URLOption, self)._validate(domain,
|
domainnameoption = self.impl_get_extra('_domainname')
|
||||||
option_bag,
|
domainnameoption.validate(domain)
|
||||||
current_opt)
|
# validate files
|
||||||
super(URLOption, self)._second_level_validation(domain, False)
|
|
||||||
# validate file
|
|
||||||
if files is not None and files != '' and not self.path_re.search(files):
|
if files is not None and files != '' and not self.path_re.search(files):
|
||||||
raise ValueError(_('must ends with a valid resource name'))
|
raise ValueError(_('must ends with a valid resource name'))
|
||||||
|
|
||||||
def _second_level_validation(self, value, warnings_only):
|
def second_level_validation(self, value, warnings_only):
|
||||||
pass
|
domain, port, files = self._get_domain_port_files(value)
|
||||||
|
# validate port
|
||||||
|
portoption = self.impl_get_extra('_port')
|
||||||
|
portoption.second_level_validation(port, warnings_only)
|
||||||
|
# validate domainname
|
||||||
|
domainnameoption = self.impl_get_extra('_domainname')
|
||||||
|
domainnameoption.second_level_validation(domain, warnings_only)
|
||||||
|
|
Loading…
Reference in New Issue