_validation, _second_level_validation => validation, second_level_validation
This commit is contained in:
parent
5c3a133928
commit
74e604478e
15 changed files with 316 additions and 269 deletions
|
@ -30,9 +30,7 @@ class BoolOption(Option):
|
|||
_type = 'boolean'
|
||||
_display_name = _('boolean')
|
||||
|
||||
def _validate(self,
|
||||
value: bool,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def validate(self,
|
||||
value: bool) -> None:
|
||||
if not isinstance(value, bool):
|
||||
raise ValueError()
|
||||
|
|
|
@ -31,10 +31,8 @@ class BroadcastOption(Option):
|
|||
_type = 'broadcast_address'
|
||||
_display_name = _('broadcast address')
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
if value.count('.') != 3:
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# 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 .option import Option
|
||||
from ..autolib import carry_out_calculation, Calculation
|
||||
from ..autolib import Calculation
|
||||
from ..error import ConfigError, display_list
|
||||
|
||||
|
||||
|
@ -40,12 +40,8 @@ class ChoiceOption(Option):
|
|||
name,
|
||||
doc,
|
||||
values,
|
||||
default=None,
|
||||
default_multi=None,
|
||||
multi=False,
|
||||
validators=None,
|
||||
properties=None,
|
||||
warnings_only=False):
|
||||
*args,
|
||||
**kwargs):
|
||||
|
||||
"""
|
||||
:param values: is a list of values the option can possibly take
|
||||
|
@ -56,12 +52,8 @@ class ChoiceOption(Option):
|
|||
self._choice_values = values
|
||||
super(ChoiceOption, self).__init__(name,
|
||||
doc,
|
||||
default=default,
|
||||
default_multi=default_multi,
|
||||
multi=multi,
|
||||
validators=validators,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only)
|
||||
*args,
|
||||
**kwargs)
|
||||
|
||||
def impl_get_values(self,
|
||||
option_bag):
|
||||
|
@ -74,15 +66,17 @@ class ChoiceOption(Option):
|
|||
values = self._choice_values
|
||||
return values
|
||||
|
||||
def _validate(self,
|
||||
value,
|
||||
option_bag,
|
||||
current_opt=undefined):
|
||||
def validate(self,
|
||||
value: Any) -> None:
|
||||
pass
|
||||
|
||||
def validate_with_option(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag) -> None:
|
||||
values = self.impl_get_values(option_bag)
|
||||
if values is not undefined and value not in values:
|
||||
if len(values) == 1:
|
||||
raise ValueError(_('only "{0}" is allowed'
|
||||
'').format(values[0]))
|
||||
else:
|
||||
raise ValueError(_('only {0} are allowed'
|
||||
'').format(display_list(values, add_quote=True)))
|
||||
|
|
|
@ -22,20 +22,17 @@ from datetime import datetime
|
|||
|
||||
from ..setting import undefined, Undefined, OptionBag
|
||||
from ..i18n import _
|
||||
from .option import Option
|
||||
from .stroption import StrOption
|
||||
|
||||
|
||||
class DateOption(Option):
|
||||
class DateOption(StrOption):
|
||||
__slots__ = tuple()
|
||||
_type = 'date'
|
||||
_display_name = _('date')
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
super().validate(value)
|
||||
try:
|
||||
datetime.strptime(value, "%Y-%m-%d")
|
||||
except ValueError:
|
||||
|
|
|
@ -19,14 +19,18 @@
|
|||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
import re
|
||||
from ipaddress import ip_address
|
||||
from ..setting import undefined, Undefined, OptionBag
|
||||
from ipaddress import ip_interface
|
||||
from typing import Any, Optional, List
|
||||
|
||||
from ..i18n import _
|
||||
from .option import Option
|
||||
from ..setting import undefined
|
||||
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
|
||||
netbios: for MS domain
|
||||
hostname: to identify the device
|
||||
|
@ -38,53 +42,63 @@ class DomainnameOption(IPOption):
|
|||
_display_name = _('domain name')
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
default=None,
|
||||
default_multi=None,
|
||||
name: str,
|
||||
doc: str,
|
||||
default: Any=undefined,
|
||||
default_multi: Any=None,
|
||||
multi: bool=False,
|
||||
validators=None,
|
||||
properties=None,
|
||||
allow_ip: bool=False,
|
||||
cidr: bool=False,
|
||||
type_: str='domainname',
|
||||
validators: Optional[List[Calculation]]=None,
|
||||
properties: Optional[List[str]]=None,
|
||||
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']:
|
||||
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
||||
extra = {'_dom_type': type_}
|
||||
if allow_ip not in [True, False]:
|
||||
if type not in ['netbios', 'hostname', 'domainname']:
|
||||
raise ValueError(_('unknown type {0} for hostname').format(type))
|
||||
extra = {'_dom_type': type}
|
||||
if not isinstance(allow_ip, bool):
|
||||
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'))
|
||||
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
|
||||
if type_ == 'domainname':
|
||||
if type == 'domainname':
|
||||
if allow_without_dot:
|
||||
min_time = 0
|
||||
else:
|
||||
min_time = 1
|
||||
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_warning = _('only lowercase, number, "-" and "." are characters are recommanded')
|
||||
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 "." characters are allowed')
|
||||
msg_warning = _('only lowercase, number, "-" and "." characters are recommanded')
|
||||
else:
|
||||
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type_))
|
||||
msg = _('only lowercase, number and - are characters are allowed')
|
||||
msg_warning = _('only lowercase, number and "-" are characters are recommanded')
|
||||
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type))
|
||||
msg = _('only lowercase, number and "-" characters are allowed')
|
||||
msg_warning = _('only lowercase, number and "-" characters are recommanded')
|
||||
if allow_ip:
|
||||
msg = _('could be a IP, otherwise {}').format(msg)
|
||||
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
||||
if not cidr:
|
||||
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_message'] = msg
|
||||
extra['_domain_re_message_warning'] = msg_warning
|
||||
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,
|
||||
doc,
|
||||
|
@ -94,19 +108,16 @@ class DomainnameOption(IPOption):
|
|||
validators=validators,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only,
|
||||
cidr=cidr,
|
||||
_extra=extra)
|
||||
extra=extra)
|
||||
|
||||
def _get_len(self, type_):
|
||||
if type_ == 'netbios':
|
||||
def _get_len(self, type):
|
||||
if type == 'netbios':
|
||||
return 15
|
||||
else:
|
||||
return 63
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def _validate_domain(self,
|
||||
value: str) -> None:
|
||||
def _valid_length(val):
|
||||
if len(val) < 1:
|
||||
raise ValueError(_("invalid length (min 1)"))
|
||||
|
@ -114,33 +125,83 @@ class DomainnameOption(IPOption):
|
|||
raise ValueError(_("invalid length (max {0})"
|
||||
"").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'))
|
||||
if self.impl_get_extra('_dom_type') == 'domainname':
|
||||
if not self.impl_get_extra('_allow_without_dot') and not "." in value:
|
||||
raise ValueError(_("must have dot"))
|
||||
if len(value) > 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)
|
||||
else:
|
||||
_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):
|
||||
raise ValueError(_('some characters are uppercase'))
|
||||
if not self.impl_get_extra('_domain_re').search(value):
|
||||
if warnings_only:
|
||||
raise ValueError(self.impl_get_extra('_domain_re_message_warning'))
|
||||
else:
|
||||
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):
|
||||
__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-]+)*$")
|
||||
_type = 'email'
|
||||
_display_name = _('email address')
|
||||
|
|
|
@ -30,9 +30,7 @@ class FloatOption(Option):
|
|||
_type = 'float'
|
||||
_display_name = _('float')
|
||||
|
||||
def _validate(self,
|
||||
value: float,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def validate(self,
|
||||
value: float) -> None:
|
||||
if not isinstance(value, float):
|
||||
raise ValueError()
|
||||
|
|
|
@ -31,7 +31,6 @@ class IntOption(Option):
|
|||
_display_name = _('integer')
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
*args,
|
||||
min_number=None,
|
||||
max_number=None,
|
||||
|
@ -41,18 +40,27 @@ class IntOption(Option):
|
|||
extra['min_number'] = min_number
|
||||
if max_number is not None:
|
||||
extra['max_number'] = max_number
|
||||
super().__init__(name, extra=extra, *args, **kwargs)
|
||||
super().__init__(*args, extra=extra, **kwargs)
|
||||
|
||||
|
||||
def _validate(self,
|
||||
value: int,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def validate(self,
|
||||
value: int) -> None:
|
||||
if not isinstance(value, int):
|
||||
raise ValueError()
|
||||
|
||||
def second_level_validation(self,
|
||||
value,
|
||||
warnings_only):
|
||||
min_number = self.impl_get_extra('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')
|
||||
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')
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
default=None,
|
||||
default_multi=None,
|
||||
multi=False,
|
||||
validators=None,
|
||||
properties=None,
|
||||
*args,
|
||||
private_only=False,
|
||||
allow_reserved=False,
|
||||
warnings_only=False,
|
||||
cidr=False,
|
||||
_extra=None):
|
||||
if _extra is None:
|
||||
extra=None,
|
||||
**kwargs):
|
||||
if extra is None:
|
||||
extra = {}
|
||||
else:
|
||||
extra = _extra
|
||||
extra['_private_only'] = private_only
|
||||
extra['_allow_reserved'] = allow_reserved
|
||||
extra['_cidr'] = cidr
|
||||
super().__init__(name,
|
||||
doc,
|
||||
default=default,
|
||||
default_multi=default_multi,
|
||||
multi=multi,
|
||||
validators=validators,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only,
|
||||
extra=extra)
|
||||
super().__init__(*args,
|
||||
extra=extra,
|
||||
**kwargs)
|
||||
|
||||
def _validate(self,
|
||||
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
|
||||
def _validate_cidr(self, value):
|
||||
try:
|
||||
if not cidr:
|
||||
ip_address(value)
|
||||
else:
|
||||
ip = ip_interface(value)
|
||||
except ValueError:
|
||||
raise ValueError()
|
||||
if cidr:
|
||||
valid_ip_netmask(str(ip.ip), str(ip.netmask))
|
||||
if ip.ip == ip.network.network_address:
|
||||
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,
|
||||
value,
|
||||
warnings_only):
|
||||
def _validate_ip(self, value):
|
||||
try:
|
||||
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)
|
||||
if not self.impl_get_extra('_allow_reserved') and ip.is_reserved:
|
||||
if warnings_only:
|
||||
|
|
|
@ -34,14 +34,9 @@ class NetmaskOption(StrOption):
|
|||
_type = 'netmask'
|
||||
_display_name = _('netmask address')
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
if value.count('.') != 3:
|
||||
raise ValueError()
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
super().validate(value)
|
||||
for val in value.split('.'):
|
||||
if val.startswith("0") and len(val) > 1:
|
||||
raise ValueError()
|
||||
|
|
|
@ -20,44 +20,28 @@
|
|||
# ____________________________________________________________
|
||||
from ipaddress import ip_address, ip_network
|
||||
|
||||
from ..setting import undefined
|
||||
from ..i18n import _
|
||||
from .option import Option
|
||||
from .stroption import StrOption
|
||||
|
||||
|
||||
class NetworkOption(Option):
|
||||
class NetworkOption(StrOption):
|
||||
"represents the choice of a network"
|
||||
__slots__ = tuple()
|
||||
_type = 'network'
|
||||
_display_name = _('network address')
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
default=None,
|
||||
default_multi=None,
|
||||
multi=False,
|
||||
validators=None,
|
||||
properties=None,
|
||||
warnings_only=False,
|
||||
cidr=False):
|
||||
extra = {'_cidr': cidr}
|
||||
super().__init__(name,
|
||||
doc,
|
||||
default=default,
|
||||
default_multi=default_multi,
|
||||
multi=multi,
|
||||
validators=validators,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only,
|
||||
extra=extra)
|
||||
|
||||
def _validate(self,
|
||||
value,
|
||||
*args,
|
||||
cidr=False,
|
||||
**kwargs):
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
extra = {'_cidr': cidr}
|
||||
super().__init__(*args,
|
||||
extra=extra,
|
||||
**kwargs)
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
super().validate(value)
|
||||
if value.count('.') != 3:
|
||||
raise ValueError()
|
||||
cidr = self.impl_get_extra('_cidr')
|
||||
|
@ -75,9 +59,9 @@ class NetworkOption(Option):
|
|||
except ValueError:
|
||||
raise ValueError()
|
||||
|
||||
def _second_level_validation(self,
|
||||
value,
|
||||
warnings_only):
|
||||
def second_level_validation(self,
|
||||
value: str,
|
||||
warnings_only: bool) -> None:
|
||||
if ip_network(value).network_address.is_reserved:
|
||||
if warnings_only:
|
||||
msg = _("shouldn't be reserved network")
|
||||
|
|
|
@ -30,10 +30,3 @@ class PasswordOption(StrOption):
|
|||
__slots__ = tuple()
|
||||
_type = '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 sys
|
||||
from typing import Union
|
||||
|
||||
from ..setting import undefined, Undefined, OptionBag
|
||||
from ..i18n import _
|
||||
|
@ -44,19 +43,13 @@ class PortOption(StrOption):
|
|||
_display_name = _('port')
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
default=None,
|
||||
default_multi=None,
|
||||
multi=False,
|
||||
validators=None,
|
||||
properties=None,
|
||||
allow_range=False,
|
||||
allow_zero=False,
|
||||
allow_wellknown=True,
|
||||
allow_registred=True,
|
||||
allow_private=False,
|
||||
warnings_only=False):
|
||||
*args,
|
||||
allow_range: bool=False,
|
||||
allow_zero: bool=False,
|
||||
allow_wellknown: bool=True,
|
||||
allow_registred: bool=True,
|
||||
allow_private: bool=False,
|
||||
**kwargs) -> None:
|
||||
|
||||
extra = {'_allow_range': allow_range,
|
||||
'_min_value': None,
|
||||
|
@ -81,24 +74,15 @@ class PortOption(StrOption):
|
|||
if extra['_max_value'] is None:
|
||||
raise ValueError(_('max value is empty'))
|
||||
|
||||
super(PortOption, self).__init__(name,
|
||||
doc,
|
||||
default=default,
|
||||
default_multi=default_multi,
|
||||
multi=multi,
|
||||
validators=validators,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only,
|
||||
extra=extra)
|
||||
super().__init__(*args,
|
||||
extra=extra,
|
||||
**kwargs)
|
||||
|
||||
def _validate(self,
|
||||
value: Union[int,str],
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
super().validate(value)
|
||||
if self.impl_get_extra('_allow_range') and ":" in str(value):
|
||||
value = str(value).split(':')
|
||||
value = value.split(':')
|
||||
if len(value) != 2:
|
||||
raise ValueError(_('range must have two values only'))
|
||||
if not value[0] < value[1]:
|
||||
|
@ -110,8 +94,16 @@ class PortOption(StrOption):
|
|||
for val in value:
|
||||
if not self.port_re.search(val):
|
||||
raise ValueError()
|
||||
|
||||
def second_level_validation(self,
|
||||
value: str,
|
||||
warnings_only: bool) -> None:
|
||||
for val in value.split(':'):
|
||||
val = int(val)
|
||||
if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'):
|
||||
raise ValueError(_('must be an integer between {0} '
|
||||
'and {1}').format(self.impl_get_extra('_min_value'),
|
||||
if warnings_only:
|
||||
msg = 'should be between {0} and {1}'
|
||||
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'
|
||||
_display_name = _('string')
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError()
|
||||
|
||||
|
@ -47,11 +45,9 @@ UnicodeOption = StrOption
|
|||
class RegexpOption(StrOption):
|
||||
__slots__ = tuple()
|
||||
|
||||
def _validate(self,
|
||||
value: Any,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
super()._validate(value, option_bag, current_opt)
|
||||
def validate(self,
|
||||
value: Any) -> None:
|
||||
super().validate(value)
|
||||
match = self._regexp.search(value)
|
||||
if not match:
|
||||
raise ValueError()
|
||||
|
|
|
@ -19,31 +19,75 @@
|
|||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
import re
|
||||
from typing import Any, Optional, List, Dict
|
||||
|
||||
from ..setting import undefined, Undefined, OptionBag
|
||||
from ..i18n import _
|
||||
from .option import Option
|
||||
from .option import Option, Calculation
|
||||
from .stroption import StrOption
|
||||
from .domainnameoption import DomainnameOption
|
||||
from .portoption import PortOption
|
||||
|
||||
|
||||
class URLOption(DomainnameOption):
|
||||
class URLOption(StrOption):
|
||||
__slots__ = tuple()
|
||||
proto_re = re.compile(r'(http|https)://')
|
||||
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||
_type = 'url'
|
||||
_display_name = _('URL')
|
||||
|
||||
def _validate(self,
|
||||
value: str,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
match = self.proto_re.search(value)
|
||||
if not match:
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
default: Any=undefined,
|
||||
default_multi: Any=None,
|
||||
multi: bool=False,
|
||||
validators: Optional[List[Calculation]]=None,
|
||||
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 '
|
||||
'https://'))
|
||||
value = value[len(match.group(0)):]
|
||||
# get domain/files
|
||||
splitted = value.split('/', 1)
|
||||
if len(splitted) == 1:
|
||||
|
@ -55,20 +99,31 @@ class URLOption(DomainnameOption):
|
|||
splitted = domain.split(':', 1)
|
||||
if len(splitted) == 1:
|
||||
domain = splitted[0]
|
||||
port = 0
|
||||
port = {'http': '80',
|
||||
'https': '443'}[type]
|
||||
else:
|
||||
domain, port = splitted
|
||||
if not 0 <= int(port) <= 65535:
|
||||
raise ValueError(_('port must be an between 0 and '
|
||||
'65536'))
|
||||
return domain, port, files
|
||||
|
||||
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
|
||||
super(URLOption, self)._validate(domain,
|
||||
option_bag,
|
||||
current_opt)
|
||||
super(URLOption, self)._second_level_validation(domain, False)
|
||||
# validate file
|
||||
domainnameoption = self.impl_get_extra('_domainname')
|
||||
domainnameoption.validate(domain)
|
||||
# validate files
|
||||
if files is not None and files != '' and not self.path_re.search(files):
|
||||
raise ValueError(_('must ends with a valid resource name'))
|
||||
|
||||
def _second_level_validation(self, value, warnings_only):
|
||||
pass
|
||||
def second_level_validation(self, value, warnings_only):
|
||||
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 a new issue