From 1c951558da09898b86bb30636d511b1d9974133b Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Thu, 11 Jul 2013 23:05:33 +0200 Subject: [PATCH] add new option's type: PortOption --- test/test_config_ip.py | 167 ++++++++++++++++++++++++++++++++++++++--- tiramisu/option.py | 76 ++++++++++++++++++- 2 files changed, 230 insertions(+), 13 deletions(-) diff --git a/test/test_config_ip.py b/test/test_config_ip.py index 7512384..e889c92 100644 --- a/test/test_config_ip.py +++ b/test/test_config_ip.py @@ -1,10 +1,8 @@ import autopath from py.test import raises - -from tiramisu.setting import owners from tiramisu.config import Config from tiramisu.option import IPOption, NetworkOption, NetmaskOption, \ - OptionDescription + PortOption, OptionDescription def test_ip(): @@ -16,12 +14,19 @@ def test_ip(): c.a = '192.168.1.0' c.a = '88.88.88.88' c.a = '0.0.0.0' - assert(ValueError, "c.a = '255.255.255.0'") + raises(ValueError, "c.a = '255.255.255.0'") c.b = '192.168.1.1' c.b = '192.168.1.0' - assert(ValueError, "c.b = '88.88.88.88'") + raises(ValueError, "c.b = '88.88.88.88'") c.b = '0.0.0.0' - assert(ValueError, "c.b = '255.255.255.0'") + raises(ValueError, "c.b = '255.255.255.0'") + + +def test_ip_default(): + a = IPOption('a', '', '88.88.88.88') + od = OptionDescription('od', '', [a]) + c = Config(od) + c.a == '88.88.88.88' def test_network(): @@ -32,14 +37,156 @@ def test_network(): c.a = '192.168.1.0' c.a = '88.88.88.88' c.a = '0.0.0.0' - assert(ValueError, "c.a = '255.255.255.0'") + raises(ValueError, "c.a = '255.255.255.0'") + def test_netmask(): a = NetmaskOption('a', '') od = OptionDescription('od', '', [a]) c = Config(od) - assert(ValueError, "c.a = '192.168.1.1'") - assert(ValueError, "c.a = '192.168.1.0'") - assert(ValueError, "c.a = '88.88.88.88'") + raises(ValueError, "c.a = '192.168.1.1'") + raises(ValueError, "c.a = '192.168.1.0'") + raises(ValueError, "c.a = '88.88.88.88'") c.a = '0.0.0.0' c.a = '255.255.255.0' + + +def test_port(): + a = PortOption('a', '') + b = PortOption('b', '', allow_zero=True) + c = PortOption('c', '', allow_zero=True, allow_registred=False) + d = PortOption('d', '', allow_zero=True, allow_wellknown=False, allow_registred=False) + e = PortOption('e', '', allow_zero=True, allow_private=True) + f = PortOption('f', '', allow_private=True) + od = OptionDescription('od', '', [a, b, c, d, e, f]) + c = Config(od) + raises(ValueError, "c.a = 0") + c.a = 1 + c.a = 1023 + c.a = 1024 + c.a = 49151 + raises(ValueError, "c.a = 49152") + raises(ValueError, "c.a = 65535") + raises(ValueError, "c.a = 65536") + + c.b = 0 + c.b = 1 + c.b = 1023 + c.b = 1024 + c.b = 49151 + raises(ValueError, "c.b = 49152") + raises(ValueError, "c.b = 65535") + raises(ValueError, "c.b = 65536") + + c.c = 0 + c.c = 1 + c.c = 1023 + raises(ValueError, "c.c = 1024") + raises(ValueError, "c.c = 49151") + raises(ValueError, "c.c = 49152") + raises(ValueError, "c.c = 65535") + raises(ValueError, "c.c = 65536") + + c.d = 0 + raises(ValueError, "c.d = 1") + raises(ValueError, "c.d = 1023") + raises(ValueError, "c.d = 1024") + raises(ValueError, "c.d = 49151") + raises(ValueError, "c.d = 49152") + raises(ValueError, "c.d = 65535") + raises(ValueError, "c.d = 65536") + + c.e = 0 + c.e = 1 + c.e = 1023 + c.e = 1024 + c.e = 49151 + c.e = 49152 + c.e = 65535 + + raises(ValueError, "c.f = 0") + c.f = 1 + c.f = 1023 + c.f = 1024 + c.f = 49151 + c.f = 49152 + c.f = 65535 + raises(ValueError, "c.f = 65536") + + +def test_port_range(): + a = PortOption('a', '', allow_range=True) + b = PortOption('b', '', allow_range=True, allow_zero=True) + c = PortOption('c', '', allow_range=True, allow_zero=True, allow_registred=False) + d = PortOption('d', '', allow_range=True, allow_zero=True, allow_wellknown=False, allow_registred=False) + e = PortOption('e', '', allow_range=True, allow_zero=True, allow_private=True) + f = PortOption('f', '', allow_range=True, allow_private=True) + od = OptionDescription('od', '', [a, b, c, d, e, f]) + c = Config(od) + raises(ValueError, "c.a = 0") + c.a = 1 + c.a = 1023 + c.a = 1024 + c.a = 49151 + raises(ValueError, "c.a = 49152") + raises(ValueError, "c.a = 65535") + raises(ValueError, "c.a = 65536") + c.a = '1:49151' + raises(ValueError, "c.a = '0:49151'") + raises(ValueError, "c.a = '1:49152'") + + c.b = 0 + c.b = 1 + c.b = 1023 + c.b = 1024 + c.b = 49151 + raises(ValueError, "c.b = 49152") + raises(ValueError, "c.b = 65535") + raises(ValueError, "c.b = 65536") + c.b = '0:49151' + raises(ValueError, "c.b = '0:49152'") + + c.c = 0 + c.c = 1 + c.c = 1023 + raises(ValueError, "c.c = 1024") + raises(ValueError, "c.c = 49151") + raises(ValueError, "c.c = 49152") + raises(ValueError, "c.c = 65535") + raises(ValueError, "c.c = 65536") + c.c = '0:1023' + raises(ValueError, "c.c = '0:1024'") + + c.d = 0 + raises(ValueError, "c.d = 1") + raises(ValueError, "c.d = 1023") + raises(ValueError, "c.d = 1024") + raises(ValueError, "c.d = 49151") + raises(ValueError, "c.d = 49152") + raises(ValueError, "c.d = 65535") + raises(ValueError, "c.d = 65536") + raises(ValueError, "c.d = '0:0'") + raises(ValueError, "c.d = '0:1'") + + c.e = 0 + c.e = 1 + c.e = 1023 + c.e = 1024 + c.e = 49151 + c.e = 49152 + c.e = 65535 + c.e = '0:65535' + raises(ValueError, "c.e = '0:65536'") + + raises(ValueError, "c.f = 0") + c.f = 1 + c.f = 1023 + c.f = 1024 + c.f = 49151 + c.f = 49152 + c.f = 65535 + raises(ValueError, "c.f = 65536") + c.f = '1:65535' + c.f = '3:4' + raises(ValueError, "c.f = '0:65535'") + raises(ValueError, "c.f = '4:3'") diff --git a/tiramisu/option.py b/tiramisu/option.py index e645a31..5c8bbda 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -277,8 +277,8 @@ class Option(BaseInformation): if value is not None and ((self._validator is not None and not val_validator()) or not self._validate(value)): - raise ValueError(_("invalid value {0} for option {1}" - "").format(value, self._name)) + raise ValueError(_("invalid value {0} for option {1} (type {2})" + "").format(value, self._name, self.__class__)) if context is not None: descr._valid_consistency(self, value, context, None) else: @@ -478,6 +478,7 @@ class IPOption(Option): requires=None, multi=False, callback=None, callback_params=None, validator=None, validator_args=None, properties=None, only_private=False): + self._only_private = only_private super(IPOption, self).__init__(name, doc, default=default, default_multi=default_multi, callback=callback, @@ -487,7 +488,6 @@ class IPOption(Option): validator=validator, validator_args=validator_args, properties=properties) - self._only_private = only_private def _validate(self, value): try: @@ -499,6 +499,76 @@ class IPOption(Option): return False +class PortOption(Option): + """represents the choice of a port + The port numbers are divided into three ranges: + the well-known ports, + the registered ports, + and the dynamic or private ports. + You can actived this three range. + Port number 0 is reserved and can't be used. + see: http://en.wikipedia.org/wiki/Port_numbers + """ + __slots__ = ('_opt_type', '_allow_range', '_allow_zero', '_min_value', + '_max_value') + _opt_type = 'port' + + def __init__(self, name, doc, default=None, default_multi=None, + requires=None, multi=False, callback=None, + callback_params=None, validator=None, validator_args=None, + properties=None, allow_range=False, allow_zero=False, + allow_wellknown=True, allow_registred=True, + allow_private=False): + self._allow_range = allow_range + self._min_value = None + self._max_value = None + ports_min = [0, 1, 1024, 49152] + ports_max = [0, 1023, 49151, 65535] + is_finally = False + for index, allowed in enumerate([allow_zero, allow_wellknown, allow_registred, allow_private]): + if self._min_value is None: + if allowed: + self._min_value = ports_min[index] + elif not allowed: + is_finally = True + elif allowed and is_finally: + raise ValueError(_('inconsistency in allowed range')) + if allowed: + self._max_value = ports_max[index] + + if self._max_value is None: + raise ValueError(_('max value is empty')) + + super(PortOption, self).__init__(name, doc, default=default, + default_multi=default_multi, + callback=callback, + callback_params=callback_params, + requires=requires, + multi=multi, + validator=validator, + validator_args=validator_args, + properties=properties) + + def _validate(self, value): + try: + if self._allow_range and ":" in str(value): + value = str(value).split(':') + if len(value) != 2: + return False + if not value[0] < value[1]: + return False + else: + value = [value] + + for val in value: + if not self._min_value <= int(val) <= self._max_value: + return False + + return True + except ValueError: + return False + + class NetworkOption(Option): "represents the choice of a network" __slots__ = ('_opt_type',)