add FileOption

This commit is contained in:
Emmanuel Garette 2013-09-30 21:21:47 +02:00
parent 1a294e3d09
commit cce080cbd3
3 changed files with 55 additions and 5 deletions

View File

@ -4,7 +4,7 @@ from py.test import raises
from tiramisu.config import Config from tiramisu.config import Config
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \ from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, OptionDescription BoolOption, FileOption, OptionDescription
def make_description(): def make_description():
@ -137,3 +137,18 @@ def test_does_not_find_in_config():
descr = make_description() descr = make_description()
conf = Config(descr) conf = Config(descr)
raises(AttributeError, "conf.find(byname='IDontExist')") raises(AttributeError, "conf.find(byname='IDontExist')")
def test_file():
a = FileOption('a', '')
o = OptionDescription('o', '', [a])
c = Config(o)
c.a = u'/'
c.a = u'/tmp'
c.a = u'/tmp/'
c.a = u'/tmp/text.txt'
c.a = u'tmp'
c.a = u'tmp/'
c.a = u'tmp/text.txt'
raises(ValueError, "c.a = u'/tmp/with space.txt'")
raises(ValueError, "c.a = u'/tmp/with$.txt'")

View File

@ -5,7 +5,8 @@ from py.test import raises
from tiramisu.config import Config, SubConfig from tiramisu.config import Config, SubConfig
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\ from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \ StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \
PortOption, NetworkOption, NetmaskOption, DomainnameOption PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \
URLOption, FileOption
def test_slots_option(): def test_slots_option():
@ -35,6 +36,12 @@ def test_slots_option():
raises(AttributeError, "c.x = 1") raises(AttributeError, "c.x = 1")
c = DomainnameOption('a', '') c = DomainnameOption('a', '')
raises(AttributeError, "c.x = 1") raises(AttributeError, "c.x = 1")
c = EmailOption('a', '')
raises(AttributeError, "c.x = 1")
c = URLOption('a', '')
raises(AttributeError, "c.x = 1")
c = FileOption('a', '')
raises(AttributeError, "c.x = 1")
def test_slots_option_readonly(): def test_slots_option_readonly():
@ -49,7 +56,10 @@ def test_slots_option_readonly():
j = NetworkOption('j', '') j = NetworkOption('j', '')
k = NetmaskOption('k', '') k = NetmaskOption('k', '')
l = DomainnameOption('l', '') l = DomainnameOption('l', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l]) o = EmailOption('o', '')
p = URLOption('p', '')
q = FileOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
a._requires = 'a' a._requires = 'a'
b._requires = 'b' b._requires = 'b'
c._requires = 'c' c._requires = 'c'
@ -62,6 +72,9 @@ def test_slots_option_readonly():
k._requires = 'k' k._requires = 'k'
l._requires = 'l' l._requires = 'l'
m._requires = 'm' m._requires = 'm'
o._requires = 'o'
p._requires = 'p'
q._requires = 'q'
Config(m) Config(m)
raises(AttributeError, "a._requires = 'a'") raises(AttributeError, "a._requires = 'a'")
raises(AttributeError, "b._requires = 'b'") raises(AttributeError, "b._requires = 'b'")
@ -75,6 +88,9 @@ def test_slots_option_readonly():
raises(AttributeError, "k._requires = 'k'") raises(AttributeError, "k._requires = 'k'")
raises(AttributeError, "l._requires = 'l'") raises(AttributeError, "l._requires = 'l'")
raises(AttributeError, "m._requires = 'm'") raises(AttributeError, "m._requires = 'm'")
raises(AttributeError, "o._requires = 'o'")
raises(AttributeError, "p._requires = 'p'")
raises(AttributeError, "q._requires = 'q'")
def test_slots_option_readonly_name(): def test_slots_option_readonly_name():
@ -90,7 +106,10 @@ def test_slots_option_readonly_name():
j = NetworkOption('j', '') j = NetworkOption('j', '')
k = NetmaskOption('k', '') k = NetmaskOption('k', '')
l = DomainnameOption('l', '') l = DomainnameOption('l', '')
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l]) o = DomainnameOption('o', '')
p = DomainnameOption('p', '')
q = DomainnameOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l, o, p, q])
raises(AttributeError, "a._name = 'a'") raises(AttributeError, "a._name = 'a'")
raises(AttributeError, "b._name = 'b'") raises(AttributeError, "b._name = 'b'")
raises(AttributeError, "c._name = 'c'") raises(AttributeError, "c._name = 'c'")
@ -104,6 +123,9 @@ def test_slots_option_readonly_name():
raises(AttributeError, "k._name = 'k'") raises(AttributeError, "k._name = 'k'")
raises(AttributeError, "l._name = 'l'") raises(AttributeError, "l._name = 'l'")
raises(AttributeError, "m._name = 'm'") raises(AttributeError, "m._name = 'm'")
raises(AttributeError, "o._name = 'o'")
raises(AttributeError, "p._name = 'p'")
raises(AttributeError, "q._name = 'q'")
def test_slots_description(): def test_slots_description():

View File

@ -1031,6 +1031,7 @@ class DomainnameOption(Option):
class EmailOption(DomainnameOption): class EmailOption(DomainnameOption):
__slots__ = tuple() __slots__ = tuple()
_opt_type = 'email'
username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$") username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -1053,6 +1054,7 @@ class EmailOption(DomainnameOption):
class URLOption(DomainnameOption): class URLOption(DomainnameOption):
__slots__ = tuple() __slots__ = tuple()
_opt_type = 'url'
proto_re = re.compile(r'(http|https)://') proto_re = re.compile(r'(http|https)://')
path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$") path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
@ -1093,6 +1095,17 @@ class URLOption(DomainnameOption):
' {0}').format(self._name)) ' {0}').format(self._name))
class FileOption(Option):
__slots__ = tuple()
_opt_type = 'file'
path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
def _validate(self, value):
match = self.path_re.search(value)
if not match:
raise ValueError(_('invalid filename for {0}').format(self._name))
class OptionDescription(BaseOption): class OptionDescription(BaseOption):
"""Config's schema (organisation, group) and container of Options """Config's schema (organisation, group) and container of Options
The `OptionsDescription` objects lives in the `tiramisu.config.Config`. The `OptionsDescription` objects lives in the `tiramisu.config.Config`.