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

@ -3,9 +3,10 @@ import autopath
from py.test import raises 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`.