Merge branch 'master' into metaconfig
This commit is contained in:
commit
6b7db20716
4
Makefile
4
Makefile
|
@ -24,13 +24,13 @@ define gettext
|
|||
P="pygettext.py" ; \
|
||||
fi ; \
|
||||
$$P -p translations/ -o $(PACKAGE).pot `find $(PACKAGE)/ -name "*.py"`
|
||||
endef
|
||||
endef
|
||||
|
||||
# Build translation files
|
||||
define build_translation
|
||||
if [ -d ${1} ]; then \
|
||||
for f in `find ${1} -name "*.po"`; do \
|
||||
msgfmt -o `dirname $$f`/`basename -s ".po" $$f`.mo $$f || true; \
|
||||
msgfmt -o `dirname $$f`/`basename $$f ".po"`.mo $$f || true; \
|
||||
done; \
|
||||
fi
|
||||
endef
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
tiramisu.storage
|
||||
================
|
||||
|
||||
.. automodule:: tiramisu.storage
|
||||
:members:
|
||||
:noindex:
|
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1,257 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="400"
|
||||
height="200"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.4 r9939"
|
||||
sodipodi:docname="test.svg"
|
||||
inkscape:export-filename="/home/gnunux/git/tiramisu/doc/storage.png"
|
||||
inkscape:export-xdpi="135"
|
||||
inkscape:export-ydpi="135">
|
||||
<defs
|
||||
id="defs4">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3827" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="73.881208"
|
||||
inkscape:cy="154.11692"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1600"
|
||||
inkscape:window-height="841"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-852.36218)">
|
||||
<g
|
||||
id="g4206"
|
||||
transform="translate(32.34835,646.56497)">
|
||||
<text
|
||||
sodipodi:linespacing="686.00001%"
|
||||
id="text2985"
|
||||
y="368.36218"
|
||||
x="98"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;line-height:686.00001335%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="368.36218"
|
||||
x="98"
|
||||
id="tspan2987"
|
||||
sodipodi:role="line">Config</tspan></text>
|
||||
<rect
|
||||
y="351.36218"
|
||||
x="81"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g4211"
|
||||
transform="translate(-21.922096,643.64303)">
|
||||
<rect
|
||||
y="312.36218"
|
||||
x="189.5"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757-2"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text3777"
|
||||
y="325.76599"
|
||||
x="220.51762"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="325.76599"
|
||||
x="220.51762"
|
||||
id="tspan3779"
|
||||
sodipodi:role="line">Option</tspan><tspan
|
||||
y="335.76599"
|
||||
x="220.51762"
|
||||
sodipodi:role="line"
|
||||
id="tspan3022">Description</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4201"
|
||||
transform="translate(11,622)">
|
||||
<rect
|
||||
y="293.42468"
|
||||
x="81"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757-5"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text4190"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4194"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
sodipodi:role="line">Option</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4201-9"
|
||||
transform="translate(85.749784,621.95117)">
|
||||
<rect
|
||||
y="293.42468"
|
||||
x="81"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757-5-1"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text4190-0"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4194-2"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
sodipodi:role="line">Option</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4211-4"
|
||||
transform="translate(52.525433,602.85429)">
|
||||
<rect
|
||||
y="312.36218"
|
||||
x="189.5"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757-2-3"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text3777-0"
|
||||
y="325.76599"
|
||||
x="220.51762"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
y="325.76599"
|
||||
x="220.51762"
|
||||
id="tspan3779-1"
|
||||
sodipodi:role="line">Option</tspan><tspan
|
||||
y="335.76599"
|
||||
x="220.51762"
|
||||
sodipodi:role="line"
|
||||
id="tspan3022-7">Description</tspan></text>
|
||||
</g>
|
||||
<g
|
||||
id="g4201-1"
|
||||
transform="translate(123.6527,582.89051)">
|
||||
<rect
|
||||
y="293.42468"
|
||||
x="81"
|
||||
height="30"
|
||||
width="63"
|
||||
id="rect3757-5-7"
|
||||
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<text
|
||||
sodipodi:linespacing="100%"
|
||||
id="text4190-2"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
style="font-size:10px;font-style:normal;font-weight:normal;text-align:center;line-height:100%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
|
||||
xml:space="preserve"><tspan
|
||||
id="tspan4194-8"
|
||||
y="309.42468"
|
||||
x="110.27588"
|
||||
sodipodi:role="line">Option</tspan></text>
|
||||
</g>
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 151.43627,945.42468 19.70537,10.58053"
|
||||
id="path3110"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:connection-start="#g4201"
|
||||
inkscape:connection-start-point="d4"
|
||||
inkscape:connection-end="#g4211"
|
||||
inkscape:connection-end-point="d4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 198.77217,956.00521 -0.21665,-10.62936"
|
||||
id="path3112"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:connection-start="#g4211"
|
||||
inkscape:connection-start-point="d4"
|
||||
inkscape:connection-end="#g4201-9"
|
||||
inkscape:connection-end-point="d4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 226.45587,956.00521 19.69159,-10.78874"
|
||||
id="path3114"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:connection-start="#g4211"
|
||||
inkscape:connection-start-point="d4"
|
||||
inkscape:connection-end="#g4211-4"
|
||||
inkscape:connection-end-point="d4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 259.11483,915.21647 -8.55152,-8.90128"
|
||||
id="path3116"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:connection-start="#g4211-4"
|
||||
inkscape:connection-start-point="d4"
|
||||
inkscape:connection-end="#g4201-1"
|
||||
inkscape:connection-end-point="d4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m 164.25211,997.92715 15.42203,-11.92194"
|
||||
id="path3118"
|
||||
inkscape:connector-type="polyline"
|
||||
inkscape:connector-curvature="0"
|
||||
inkscape:connection-start="#g4206"
|
||||
inkscape:connection-start-point="d4"
|
||||
inkscape:connection-end="#g4211"
|
||||
inkscape:connection-end-point="d4" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 9.0 KiB |
13
setup.py
13
setup.py
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from distutils.core import setup
|
||||
from os.path import dirname, abspath, join, normpath, isdir, basename
|
||||
from os.path import dirname, abspath, join, normpath, isdir
|
||||
from os import listdir
|
||||
|
||||
|
||||
|
@ -9,15 +9,16 @@ def fetch_version():
|
|||
"""Get version from version.in"""
|
||||
return file('VERSION', 'r').readline().strip()
|
||||
|
||||
|
||||
def return_storages():
|
||||
"returns all the storage plugins that are living in tiramisu/storage"
|
||||
here = dirname(abspath(__file__))
|
||||
storages_path = normpath(join(here, 'tiramisu', 'storage'))
|
||||
dir_content = [ content for content in listdir(storages_path) \
|
||||
if not content =='__pycache__']
|
||||
storages = filter(isdir, [join(storages_path, content) \
|
||||
dir_content = [content for content in listdir(storages_path)
|
||||
if not content == '__pycache__']
|
||||
storages = filter(isdir, [join(storages_path, content)
|
||||
for content in dir_content])
|
||||
storage_list = [basename(storage) for storage in storages]
|
||||
storage_list = ['.'.join(storage.split('/')[-3:]) for storage in storages]
|
||||
return storage_list
|
||||
|
||||
packages = ['tiramisu', 'tiramisu.storage']
|
||||
|
@ -58,6 +59,6 @@ producing flexible and fast options access.
|
|||
|
||||
|
||||
This version requires Python 2.6 or later.
|
||||
"""
|
||||
""",
|
||||
packages=packages
|
||||
)
|
||||
|
|
|
@ -230,3 +230,9 @@ def test_duplicated_option():
|
|||
root = OptionDescription('root', '', [d1, d2])
|
||||
#in different OptionDescription
|
||||
raises(ConflictError, "config = Config(root)")
|
||||
|
||||
def test_cannot_assign_value_to_option_description():
|
||||
descr = make_description()
|
||||
cfg = Config(descr)
|
||||
raises(TypeError, "cfg.gc = 3")
|
||||
|
||||
|
|
|
@ -116,6 +116,23 @@ def test_find_in_config():
|
|||
#assert conf.find_first(byvalue=False, byname='dummy', byattrs=dict(default=False)) == conf.unwrap_from_path('gc.dummy')
|
||||
|
||||
|
||||
def test_find_multi():
|
||||
b = BoolOption('bool', '', multi=True)
|
||||
o = OptionDescription('od', '', [b])
|
||||
conf = Config(o)
|
||||
raises(AttributeError, "conf.find(byvalue=True)")
|
||||
raises(AttributeError, "conf.find_first(byvalue=True)")
|
||||
conf.bool.append(False)
|
||||
raises(AttributeError, "conf.find(byvalue=True)")
|
||||
raises(AttributeError, "conf.find_first(byvalue=True)")
|
||||
conf.bool.append(False)
|
||||
raises(AttributeError, "conf.find(byvalue=True)")
|
||||
raises(AttributeError, "conf.find_first(byvalue=True)")
|
||||
conf.bool.append(True)
|
||||
assert conf.find(byvalue=True) == [b]
|
||||
assert conf.find_first(byvalue=True) == b
|
||||
|
||||
|
||||
def test_does_not_find_in_config():
|
||||
descr = make_description()
|
||||
conf = Config(descr)
|
||||
|
|
|
@ -7,7 +7,7 @@ from tiramisu.option import IPOption, NetworkOption, NetmaskOption, \
|
|||
|
||||
def test_ip():
|
||||
a = IPOption('a', '')
|
||||
b = IPOption('b', '', only_private=True)
|
||||
b = IPOption('b', '', private_only=True)
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
c = Config(od)
|
||||
c.a = '192.168.1.1'
|
||||
|
@ -29,6 +29,15 @@ def test_ip_default():
|
|||
c.a == '88.88.88.88'
|
||||
|
||||
|
||||
def test_ip_reserved():
|
||||
a = IPOption('a', '')
|
||||
b = IPOption('b', '', allow_reserved=True)
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
c = Config(od)
|
||||
raises(ValueError, "c.a = '226.94.1.1'")
|
||||
c.b = '226.94.1.1'
|
||||
|
||||
|
||||
def test_network():
|
||||
a = NetworkOption('a', '')
|
||||
od = OptionDescription('od', '', [a])
|
||||
|
|
|
@ -4,19 +4,33 @@ from py.test import raises
|
|||
from tiramisu.setting import groups
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||
StrOption, OptionDescription
|
||||
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError
|
||||
StrOption, OptionDescription, SymLinkOption
|
||||
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
|
||||
|
||||
|
||||
def return_val():
|
||||
return 'val'
|
||||
|
||||
|
||||
def return_list():
|
||||
def return_concat(*args):
|
||||
return '.'.join(list(args))
|
||||
|
||||
|
||||
def return_list(value=None):
|
||||
return ['val', 'val']
|
||||
|
||||
|
||||
def return_value(value):
|
||||
def return_list2(*args):
|
||||
return list(args)
|
||||
|
||||
|
||||
def return_value(value=None):
|
||||
return value
|
||||
|
||||
|
||||
def return_value2(*args, **kwargs):
|
||||
value = list(args)
|
||||
value.extend(kwargs.values())
|
||||
return value
|
||||
|
||||
|
||||
|
@ -298,18 +312,73 @@ def test_callback():
|
|||
|
||||
def test_callback_value():
|
||||
val1 = StrOption('val1', "", 'val')
|
||||
val2 = StrOption('val2', "", callback=return_value, callback_params={'': (('val1', False),)})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
||||
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
|
||||
val3 = StrOption('val3', "", callback=return_value, callback_params={'': ('yes',)})
|
||||
val4 = StrOption('val4', "", callback=return_value, callback_params={'value': ((val1, False),)})
|
||||
val5 = StrOption('val5', "", callback=return_value, callback_params={'value': ('yes',)})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1 == 'val'
|
||||
assert cfg.val2 == 'val'
|
||||
assert cfg.val4 == 'val'
|
||||
cfg.val1 = 'new-val'
|
||||
assert cfg.val1 == 'new-val'
|
||||
assert cfg.val2 == 'new-val'
|
||||
assert cfg.val4 == 'new-val'
|
||||
del(cfg.val1)
|
||||
assert cfg.val1 == 'val'
|
||||
assert cfg.val2 == 'val'
|
||||
assert cfg.val3 == 'yes'
|
||||
assert cfg.val4 == 'val'
|
||||
assert cfg.val5 == 'yes'
|
||||
|
||||
|
||||
def test_callback_value_tuple():
|
||||
val1 = StrOption('val1', "", 'val1')
|
||||
val2 = StrOption('val2', "", 'val2')
|
||||
val3 = StrOption('val3', "", callback=return_concat, callback_params={'': ((val1, False), (val2, False))})
|
||||
val4 = StrOption('val4', "", callback=return_concat, callback_params={'': ('yes', 'no')})
|
||||
raises(ValueError, "StrOption('val4', '', callback=return_concat, callback_params={'value': ('yes', 'no')})")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1 == 'val1'
|
||||
assert cfg.val2 == 'val2'
|
||||
assert cfg.val3 == 'val1.val2'
|
||||
assert cfg.val4 == 'yes.no'
|
||||
cfg.val1 = 'new-val'
|
||||
assert cfg.val3 == 'new-val.val2'
|
||||
del(cfg.val1)
|
||||
assert cfg.val3 == 'val1.val2'
|
||||
|
||||
|
||||
def test_callback_value_force_permissive():
|
||||
val1 = StrOption('val1', "", 'val', properties=('disabled',))
|
||||
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
|
||||
val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val1, True),)})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_only()
|
||||
raises(ConfigError, "cfg.val2")
|
||||
assert cfg.val3 is None
|
||||
|
||||
|
||||
def test_callback_symlink():
|
||||
val1 = StrOption('val1', "", 'val')
|
||||
val2 = SymLinkOption('val2', val1)
|
||||
val3 = StrOption('val3', "", callback=return_value, callback_params={'': ((val2, False),)})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1 == 'val'
|
||||
assert cfg.val3 == 'val'
|
||||
cfg.val1 = 'new-val'
|
||||
assert cfg.val1 == 'new-val'
|
||||
assert cfg.val3 == 'new-val'
|
||||
del(cfg.val1)
|
||||
assert cfg.val1 == 'val'
|
||||
assert cfg.val3 == 'val'
|
||||
|
||||
|
||||
def test_callback_list():
|
||||
|
@ -336,21 +405,28 @@ def test_callback_multi():
|
|||
|
||||
def test_callback_multi_value():
|
||||
val1 = StrOption('val1', "", ['val'], multi=True)
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1', False),)})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
|
||||
val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
|
||||
val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), 'yes')})
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1 == ['val']
|
||||
assert cfg.val2 == ['val']
|
||||
assert cfg.val4 == ['val', 'yes']
|
||||
cfg.val1 = ['new-val']
|
||||
assert cfg.val1 == ['new-val']
|
||||
assert cfg.val2 == ['new-val']
|
||||
assert cfg.val4 == ['new-val', 'yes']
|
||||
cfg.val1.append('new-val2')
|
||||
assert cfg.val1 == ['new-val', 'new-val2']
|
||||
assert cfg.val2 == ['new-val', 'new-val2']
|
||||
assert cfg.val4 == ['new-val', 'yes', 'new-val2', 'yes']
|
||||
del(cfg.val1)
|
||||
assert cfg.val1 == ['val']
|
||||
assert cfg.val2 == ['val']
|
||||
assert cfg.val3 == ['yes']
|
||||
assert cfg.val4 == ['val', 'yes']
|
||||
|
||||
|
||||
def test_callback_multi_list():
|
||||
|
@ -455,41 +531,67 @@ def test_callback_master_and_slaves_slave_list():
|
|||
|
||||
def test_callback_master_and_slaves_value():
|
||||
val1 = StrOption('val1', "", multi=True)
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1.val1', False),)})
|
||||
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
|
||||
val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
|
||||
val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
|
||||
val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
|
||||
interface1 = OptionDescription('val1', '', [val1, val2, val3, val5])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||
maconfig = OptionDescription('rootconfig', '', [interface1, val4])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val1.val1 == []
|
||||
assert cfg.val1.val2 == []
|
||||
assert cfg.val1.val3 == []
|
||||
assert cfg.val1.val5 == []
|
||||
#
|
||||
cfg.val1.val1 = ['val1']
|
||||
assert cfg.val1.val1 == ['val1']
|
||||
assert cfg.val1.val2 == ['val1']
|
||||
assert cfg.val1.val3 == ['yes']
|
||||
assert cfg.val1.val5 == ['val10']
|
||||
#
|
||||
cfg.val1.val1.append('val2')
|
||||
assert cfg.val1.val1 == ['val1', 'val2']
|
||||
assert cfg.val1.val2 == ['val1', 'val2']
|
||||
assert cfg.val1.val3 == ['yes', 'yes']
|
||||
assert cfg.val1.val5 == ['val10', 'val11']
|
||||
#
|
||||
cfg.val1.val1 = ['val1', 'val2', 'val3']
|
||||
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
|
||||
assert cfg.val1.val2 == ['val1', 'val2', 'val3']
|
||||
assert cfg.val1.val3 == ['yes', 'yes', 'yes']
|
||||
assert cfg.val1.val5 == ['val10', 'val11', None]
|
||||
#
|
||||
cfg.val1.val1.pop(2)
|
||||
assert cfg.val1.val1 == ['val1', 'val2']
|
||||
assert cfg.val1.val2 == ['val1', 'val2']
|
||||
assert cfg.val1.val3 == ['yes', 'yes']
|
||||
assert cfg.val1.val5 == ['val10', 'val11']
|
||||
#
|
||||
cfg.val1.val2 = ['val2', 'val2']
|
||||
cfg.val1.val3 = ['val2', 'val2']
|
||||
cfg.val1.val5 = ['val2', 'val2']
|
||||
assert cfg.val1.val2 == ['val2', 'val2']
|
||||
assert cfg.val1.val3 == ['val2', 'val2']
|
||||
assert cfg.val1.val5 == ['val2', 'val2']
|
||||
#
|
||||
cfg.val1.val1.append('val3')
|
||||
assert cfg.val1.val2 == ['val2', 'val2', 'val3']
|
||||
assert cfg.val1.val3 == ['val2', 'val2', 'yes']
|
||||
assert cfg.val1.val5 == ['val2', 'val2', None]
|
||||
cfg.cfgimpl_get_settings().remove('cache')
|
||||
cfg.val4 = ['val10', 'val11', 'val12']
|
||||
#if value is already set, not updated !
|
||||
cfg.val1.val1.pop(2)
|
||||
cfg.val1.val1.append('val3')
|
||||
cfg.val1.val1 = ['val1', 'val2', 'val3']
|
||||
assert cfg.val1.val5 == ['val2', 'val2', 'val12']
|
||||
|
||||
|
||||
def test_callback_hidden():
|
||||
opt1 = BoolOption('opt1', '')
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': (('od1.opt1', False),)})
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
|
||||
od1 = OptionDescription('od1', '', [opt1], properties=('hidden',))
|
||||
od2 = OptionDescription('od2', '', [opt2])
|
||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||
|
@ -498,3 +600,94 @@ def test_callback_hidden():
|
|||
cfg.read_write()
|
||||
raises(PropertiesOptionError, 'cfg.od1.opt1')
|
||||
cfg.od2.opt2
|
||||
|
||||
|
||||
def test_callback_two_disabled():
|
||||
opt1 = BoolOption('opt1', '', properties=('disabled',))
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',))
|
||||
od1 = OptionDescription('od1', '', [opt1])
|
||||
od2 = OptionDescription('od2', '', [opt2])
|
||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(PropertiesOptionError, 'cfg.od2.opt2')
|
||||
|
||||
|
||||
def test_callback_calculating_disabled():
|
||||
opt1 = BoolOption('opt1', '', properties=('disabled',))
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
|
||||
od1 = OptionDescription('od1', '', [opt1])
|
||||
od2 = OptionDescription('od2', '', [opt2])
|
||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(ConfigError, 'cfg.od2.opt2')
|
||||
|
||||
|
||||
def test_callback_calculating_mandatory():
|
||||
opt1 = BoolOption('opt1', '', properties=('disabled',))
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
|
||||
od1 = OptionDescription('od1', '', [opt1])
|
||||
od2 = OptionDescription('od2', '', [opt2])
|
||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_only()
|
||||
raises(ConfigError, 'cfg.od2.opt2')
|
||||
|
||||
|
||||
def test_callback_two_disabled_multi():
|
||||
opt1 = BoolOption('opt1', '', properties=('disabled',))
|
||||
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',), multi=True)
|
||||
od1 = OptionDescription('od1', '', [opt1])
|
||||
od2 = OptionDescription('od2', '', [opt2])
|
||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(PropertiesOptionError, 'cfg.od2.opt2')
|
||||
|
||||
|
||||
def test_callback_multi_list_params():
|
||||
val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'': ((val1, False),)})
|
||||
oval2 = OptionDescription('val2', '', [val2])
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, oval2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
|
||||
|
||||
|
||||
def test_callback_multi_list_params_key():
|
||||
val1 = StrOption('val1', "", multi=True, default=['val1', 'val2'])
|
||||
val2 = StrOption('val2', "", multi=True, callback=return_list, callback_params={'value': ((val1, False),)})
|
||||
oval2 = OptionDescription('val2', '', [val2])
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, oval2])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
|
||||
|
||||
|
||||
def test_callback_multi_multi():
|
||||
val1 = StrOption('val1', "", multi=True, default=['val1', 'val2', 'val3'])
|
||||
val2 = StrOption('val2', "", multi=True, default=['val11', 'val12'])
|
||||
val3 = StrOption('val3', "", default='val4')
|
||||
val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val2, False))})
|
||||
val5 = StrOption('val5', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val3, False))})
|
||||
val6 = StrOption('val6', "", multi=True, default=['val21', 'val22', 'val23'])
|
||||
val7 = StrOption('val7', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val6, False))})
|
||||
raises(ValueError, "StrOption('val8', '', multi=True, callback=return_list2, callback_params={'value': ((val1, False), (val6, False))})")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5, val6, val7])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
raises(ConfigError, "cfg.val4")
|
||||
assert cfg.val5 == ['val1', 'val4', 'val2', 'val4', 'val3', 'val4']
|
||||
assert cfg.val7 == ['val1', 'val21', 'val2', 'val22', 'val3', 'val23']
|
||||
|
||||
|
||||
def test_multi_with_no_value():
|
||||
#First option return [] (so without value)
|
||||
val1 = StrOption('val1', "", ['val'], multi=True)
|
||||
val2 = StrOption('val2', "", multi=True)
|
||||
val3 = StrOption('val3', '', multi=True, callback=return_value, callback_params={'': ((val2, False),), 'value': ((val1, False),)})
|
||||
od = OptionDescription('od', '', [val1, val2, val3])
|
||||
c = Config(od)
|
||||
raises(ConfigError, "c.val3")
|
||||
|
|
|
@ -4,7 +4,8 @@ from py.test import raises
|
|||
from tiramisu.setting import owners, groups
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
||||
SymLinkOption, OptionDescription
|
||||
BroadcastOption, SymLinkOption, OptionDescription
|
||||
from tiramisu.error import ConfigError
|
||||
|
||||
|
||||
def test_consistency_not_equal():
|
||||
|
@ -22,6 +23,60 @@ def test_consistency_not_equal():
|
|||
c.b = 2
|
||||
|
||||
|
||||
def test_consistency_not_equal_many_opts():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
c = IntOption('c', '')
|
||||
d = IntOption('d', '')
|
||||
e = IntOption('e', '')
|
||||
f = IntOption('f', '')
|
||||
od = OptionDescription('od', '', [a, b, c, d, e, f])
|
||||
a.impl_add_consistency('not_equal', b, c, d, e, f)
|
||||
c = Config(od)
|
||||
assert c.a is None
|
||||
assert c.b is None
|
||||
#
|
||||
c.a = 1
|
||||
del(c.a)
|
||||
#
|
||||
c.a = 1
|
||||
raises(ValueError, "c.b = 1")
|
||||
#
|
||||
c.b = 2
|
||||
raises(ValueError, "c.f = 2")
|
||||
raises(ValueError, "c.f = 1")
|
||||
#
|
||||
c.d = 3
|
||||
raises(ValueError, "c.f = 3")
|
||||
raises(ValueError, "c.a = 3")
|
||||
raises(ValueError, "c.c = 3")
|
||||
raises(ValueError, "c.e = 3")
|
||||
|
||||
|
||||
def test_consistency_not_in_config():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
a.impl_add_consistency('not_equal', b)
|
||||
od1 = OptionDescription('od1', '', [a])
|
||||
od2 = OptionDescription('od2', '', [b])
|
||||
od = OptionDescription('root', '', [od1])
|
||||
raises(ConfigError, "Config(od)")
|
||||
od = OptionDescription('root', '', [od1, od2])
|
||||
Config(od)
|
||||
#with subconfig
|
||||
raises(ConfigError, "Config(od.od1)")
|
||||
|
||||
|
||||
def test_consistency_afer_config():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
od1 = OptionDescription('od1', '', [a])
|
||||
od2 = OptionDescription('od2', '', [b])
|
||||
od = OptionDescription('root', '', [od1, od2])
|
||||
Config(od)
|
||||
raises(AttributeError, "a.impl_add_consistency('not_equal', b)")
|
||||
|
||||
|
||||
def test_consistency_not_equal_symlink():
|
||||
a = IntOption('a', '')
|
||||
b = IntOption('b', '')
|
||||
|
@ -29,7 +84,7 @@ def test_consistency_not_equal_symlink():
|
|||
od = OptionDescription('od', '', [a, b, c])
|
||||
a.impl_add_consistency('not_equal', b)
|
||||
c = Config(od)
|
||||
assert set(od._consistencies.keys()) == set([a, b])
|
||||
assert set(od._cache_consistencies.keys()) == set([a, b])
|
||||
|
||||
|
||||
def test_consistency_not_equal_multi():
|
||||
|
@ -53,6 +108,14 @@ def test_consistency_default():
|
|||
raises(ValueError, "a.impl_add_consistency('not_equal', b)")
|
||||
|
||||
|
||||
def test_consistency_default_multi():
|
||||
a = IntOption('a', '', [2, 1], multi=True)
|
||||
b = IntOption('b', '', [1, 1], multi=True)
|
||||
c = IntOption('c', '', [1, 2], multi=True)
|
||||
raises(ValueError, "a.impl_add_consistency('not_equal', b)")
|
||||
a.impl_add_consistency('not_equal', c)
|
||||
|
||||
|
||||
def test_consistency_default_diff():
|
||||
a = IntOption('a', '', 3)
|
||||
b = IntOption('b', '', 1)
|
||||
|
@ -99,7 +162,7 @@ def test_consistency_ip_netmask_error_multi():
|
|||
a = IPOption('a', '', multi=True)
|
||||
b = NetmaskOption('b', '')
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
raises(ValueError, "b.impl_add_consistency('ip_netmask', a)")
|
||||
raises(ConfigError, "b.impl_add_consistency('ip_netmask', a)")
|
||||
|
||||
|
||||
def test_consistency_ip_netmask_multi():
|
||||
|
@ -159,3 +222,53 @@ def test_consistency_network_netmask_multi_master():
|
|||
c.a = ['192.168.1.0']
|
||||
c.b = ['255.255.255.0']
|
||||
raises(ValueError, "c.a = ['192.168.1.1']")
|
||||
|
||||
|
||||
def test_consistency_broadcast():
|
||||
a = NetworkOption('a', '', multi=True)
|
||||
b = NetmaskOption('b', '', multi=True)
|
||||
c = BroadcastOption('c', '', multi=True)
|
||||
od = OptionDescription('a', '', [a, b, c])
|
||||
od.impl_set_group_type(groups.master)
|
||||
b.impl_add_consistency('network_netmask', a)
|
||||
c.impl_add_consistency('broadcast', a, b)
|
||||
c = Config(od)
|
||||
#first, test network_netmask
|
||||
c.a = ['192.168.1.128']
|
||||
raises(ValueError, "c.b = ['255.255.255.0']")
|
||||
#
|
||||
c.a = ['192.168.1.0']
|
||||
c.b = ['255.255.255.0']
|
||||
c.c = ['192.168.1.255']
|
||||
raises(ValueError, "c.a = ['192.168.1.1']")
|
||||
#
|
||||
c.a = ['192.168.1.0', '192.168.2.128']
|
||||
c.b = ['255.255.255.0', '255.255.255.128']
|
||||
c.c = ['192.168.1.255', '192.168.2.255']
|
||||
raises(ValueError, "c.c[1] = '192.168.2.128'")
|
||||
c.c[1] = '192.168.2.255'
|
||||
|
||||
|
||||
def test_consistency_broadcast_default():
|
||||
a = NetworkOption('a', '', '192.168.1.0')
|
||||
b = NetmaskOption('b', '', '255.255.255.128')
|
||||
c = BroadcastOption('c', '', '192.168.2.127')
|
||||
d = BroadcastOption('d', '', '192.168.1.127')
|
||||
od = OptionDescription('a', '', [a, b, c])
|
||||
raises(ValueError, "c.impl_add_consistency('broadcast', a, b)")
|
||||
od2 = OptionDescription('a', '', [a, b, d])
|
||||
d.impl_add_consistency('broadcast', a, b)
|
||||
|
||||
|
||||
def test_consistency_not_all():
|
||||
#_cache_consistencies is not None by not options has consistencies
|
||||
a = NetworkOption('a', '', multi=True)
|
||||
b = NetmaskOption('b', '', multi=True)
|
||||
c = BroadcastOption('c', '', multi=True)
|
||||
od = OptionDescription('a', '', [a, b, c])
|
||||
od.impl_set_group_type(groups.master)
|
||||
b.impl_add_consistency('network_netmask', a)
|
||||
c = Config(od)
|
||||
c.a = ['192.168.1.0']
|
||||
c.b = ['255.255.255.0']
|
||||
c.c = ['192.168.1.255']
|
||||
|
|
|
@ -327,23 +327,23 @@ def test_reset_properties():
|
|||
cfg = Config(descr)
|
||||
setting = cfg.cfgimpl_get_settings()
|
||||
option = cfg.cfgimpl_get_description().gc.dummy
|
||||
assert setting._p_.get_properties(cfg) == {}
|
||||
assert setting._p_.get_modified_properties() == {}
|
||||
setting.append('frozen')
|
||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'cache', 'validator'))}
|
||||
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'cache', 'validator'))}
|
||||
setting.reset()
|
||||
assert setting._p_.get_properties(cfg) == {}
|
||||
assert setting._p_.get_modified_properties() == {}
|
||||
setting[option].append('test')
|
||||
assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
|
||||
assert setting._p_.get_modified_properties() == {'gc.dummy': set(('test',))}
|
||||
setting.reset()
|
||||
assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
|
||||
assert setting._p_.get_modified_properties() == {'gc.dummy': set(('test',))}
|
||||
setting.append('frozen')
|
||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator', 'cache')), 'gc.dummy': set(('test',))}
|
||||
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'validator', 'cache')), 'gc.dummy': set(('test',))}
|
||||
setting.reset(option)
|
||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator', 'cache'))}
|
||||
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'validator', 'cache'))}
|
||||
setting[option].append('test')
|
||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator', 'cache')), 'gc.dummy': set(('test',))}
|
||||
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'validator', 'cache')), 'gc.dummy': set(('test',))}
|
||||
setting.reset(all_properties=True)
|
||||
assert setting._p_.get_properties(cfg) == {}
|
||||
assert setting._p_.get_modified_properties() == {}
|
||||
raises(ValueError, 'setting.reset(all_properties=True, opt=option)')
|
||||
a = descr.wantref
|
||||
setting[a].append('test')
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
import autopath
|
||||
import warnings
|
||||
from py.test import raises
|
||||
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import StrOption, OptionDescription
|
||||
from tiramisu.setting import groups
|
||||
from tiramisu.error import ValueWarning
|
||||
|
||||
|
||||
def return_true(value, param=None):
|
||||
if value == 'val' and param in [None, 'yes']:
|
||||
return True
|
||||
|
||||
|
||||
def return_false(value, param=None):
|
||||
if value == 'val' and param in [None, 'yes']:
|
||||
raise ValueError('error')
|
||||
|
||||
|
||||
def return_val(value, param=None):
|
||||
return 'val'
|
||||
|
||||
|
||||
def return_if_val(value):
|
||||
if value != 'val':
|
||||
raise ValueError('error')
|
||||
|
||||
|
||||
def test_validator():
|
||||
opt1 = StrOption('opt1', '', validator=return_true, default='val')
|
||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
|
||||
opt2 = StrOption('opt2', '', validator=return_false)
|
||||
root = OptionDescription('root', '', [opt1, opt2])
|
||||
cfg = Config(root)
|
||||
assert cfg.opt1 == 'val'
|
||||
raises(ValueError, "cfg.opt2 = 'val'")
|
||||
|
||||
|
||||
def test_validator_params():
|
||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ('yes',)}, default='val')
|
||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)}, default='val')")
|
||||
opt2 = StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)})
|
||||
root = OptionDescription('root', '', [opt1, opt2])
|
||||
cfg = Config(root)
|
||||
assert cfg.opt1 == 'val'
|
||||
raises(ValueError, "cfg.opt2 = 'val'")
|
||||
|
||||
|
||||
def test_validator_params_key():
|
||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params={'param': ('yes',)}, default='val')
|
||||
raises(TypeError, "StrOption('opt2', '', validator=return_true, validator_params={'param_unknown': ('yes',)}, default='val')")
|
||||
root = OptionDescription('root', '', [opt1])
|
||||
cfg = Config(root)
|
||||
assert cfg.opt1 == 'val'
|
||||
|
||||
|
||||
def test_validator_params_option():
|
||||
opt0 = StrOption('opt0', '', default='val')
|
||||
raises(ValueError, "opt1 = StrOption('opt1', '', validator=return_true, validator_params={'': ((opt0, False),)}, default='val')")
|
||||
|
||||
|
||||
def test_validator_multi():
|
||||
opt1 = StrOption('opt1', '', validator=return_if_val, multi=True)
|
||||
root = OptionDescription('root', '', [opt1])
|
||||
cfg = Config(root)
|
||||
assert cfg.opt1 == []
|
||||
cfg.opt1.append('val')
|
||||
assert cfg.opt1 == ['val']
|
||||
raises(ValueError, "cfg.opt1.append('val1')")
|
||||
raises(ValueError, "cfg.opt1 = ['val', 'val1']")
|
||||
|
||||
|
||||
def test_validator_warning():
|
||||
opt1 = StrOption('opt1', '', validator=return_true, default='val', warnings_only=True)
|
||||
opt2 = StrOption('opt2', '', validator=return_false, warnings_only=True)
|
||||
opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, warnings_only=True)
|
||||
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||
cfg = Config(root)
|
||||
assert cfg.opt1 == 'val'
|
||||
warnings.simplefilter("always", ValueWarning)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.opt1 = 'val'
|
||||
assert w == []
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.opt2 = 'val'
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == opt2
|
||||
assert str(w[0].message) == 'invalid value val for option opt2: error'
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.opt3.append('val')
|
||||
assert w == []
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.opt3.append('val1')
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == opt3
|
||||
assert str(w[0].message) == 'invalid value val1 for option opt3: error'
|
||||
raises(ValueError, "cfg.opt2 = 1")
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.opt2 = 'val'
|
||||
cfg.opt3.append('val')
|
||||
assert len(w) == 2
|
||||
assert w[0].message.opt == opt2
|
||||
assert str(w[0].message) == 'invalid value val for option opt2: error'
|
||||
assert w[1].message.opt == opt3
|
||||
assert str(w[1].message) == 'invalid value val1 for option opt3: error'
|
||||
|
||||
|
||||
def test_validator_warning_master_slave():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=return_false, warnings_only=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=return_if_val, warnings_only=True)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
assert interface1.impl_get_group_type() == groups.master
|
||||
root = OptionDescription('root', '', [interface1])
|
||||
cfg = Config(root)
|
||||
warnings.simplefilter("always", ValueWarning)
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.ip_admin_eth0.append(None)
|
||||
assert w == []
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = ['val1']
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == netmask_admin_eth0
|
||||
assert str(w[0].message) == 'invalid value val1 for option netmask_admin_eth0: error'
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ['val']
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == ip_admin_eth0
|
||||
assert str(w[0].message) == 'invalid value val for option ip_admin_eth0: error'
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ['val', 'val1', 'val1']
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == ip_admin_eth0
|
||||
assert str(w[0].message) == 'invalid value val for option ip_admin_eth0: error'
|
||||
#
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val', 'val1']
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == ip_admin_eth0
|
||||
assert str(w[0].message) == 'invalid value val for option ip_admin_eth0: error'
|
||||
#
|
||||
warnings.resetwarnings()
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val1', 'val']
|
||||
assert len(w) == 1
|
||||
assert w[0].message.opt == ip_admin_eth0
|
||||
assert str(w[0].message) == 'invalid value val for option ip_admin_eth0: error'
|
|
@ -64,9 +64,9 @@ def test_make_dict_filter():
|
|||
config = Config(descr)
|
||||
config.read_write()
|
||||
subresult = {'numero_etab': None, 'nombre_interfaces': 1,
|
||||
'serveur_ntp': [], 'mode_conteneur_actif': False,
|
||||
'time_zone': 'Paris', 'nom_machine': 'eoleng',
|
||||
'activer_proxy_client': False}
|
||||
'serveur_ntp': [], 'mode_conteneur_actif': False,
|
||||
'time_zone': 'Paris', 'nom_machine': 'eoleng',
|
||||
'activer_proxy_client': False}
|
||||
result = {}
|
||||
for key, value in subresult.items():
|
||||
result['general.' + key] = value
|
||||
|
@ -114,7 +114,6 @@ def test_iter_not_group():
|
|||
raises(TypeError, "list(config.iter_groups(group_type='family'))")
|
||||
|
||||
|
||||
|
||||
def test_groups_with_master():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||
|
@ -252,6 +251,22 @@ def test_values_with_master_and_slaves_master():
|
|||
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||
|
||||
|
||||
def test_values_with_master_and_slaves_master_error():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||
interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
interface1.impl_set_group_type(groups.master)
|
||||
maconfig = OptionDescription('toto', '', [interface1])
|
||||
cfg = Config(maconfig)
|
||||
cfg.read_write()
|
||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
|
||||
cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0']")
|
||||
raises(SlaveError, "cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0', '255.255.255.0']")
|
||||
|
||||
|
||||
def test_values_with_master_owner():
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||
|
|
|
@ -1,8 +1,16 @@
|
|||
from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
|
||||
OptionDescription
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.setting import owners
|
||||
from tiramisu.storage import delete_session
|
||||
from tiramisu.error import ConfigError
|
||||
from pickle import dumps, loads
|
||||
|
||||
|
||||
def return_value(value=None):
|
||||
return value
|
||||
|
||||
|
||||
def _get_slots(opt):
|
||||
slots = set()
|
||||
for subclass in opt.__class__.__mro__:
|
||||
|
@ -32,7 +40,7 @@ def _diff_opt(opt1, opt2):
|
|||
if diff2 != set():
|
||||
raise Exception('more attribute in opt2 {0}'.format(list(diff2)))
|
||||
for attr in attr1:
|
||||
if attr in ['_cache_paths']:
|
||||
if attr in ['_cache_paths', '_cache_consistencies']:
|
||||
continue
|
||||
err1 = False
|
||||
err2 = False
|
||||
|
@ -64,7 +72,20 @@ def _diff_opt(opt1, opt2):
|
|||
if isinstance(val1, list):
|
||||
for index, consistency in enumerate(val1):
|
||||
assert consistency[0] == val2[index][0]
|
||||
assert consistency[1]._name == val2[index][1]._name
|
||||
for idx, opt in enumerate(consistency[1]):
|
||||
assert opt._name == val2[index][1][idx]._name
|
||||
elif attr == '_callback':
|
||||
assert val1[0] == val2[0]
|
||||
if val1[1] is not None:
|
||||
for key, values in val1[1].items():
|
||||
for idx, value in enumerate(values):
|
||||
if isinstance(value, tuple):
|
||||
assert val1[1][key][idx][0]._name == val2[1][key][idx][0]._name
|
||||
assert val1[1][key][idx][1] == val2[1][key][idx][1]
|
||||
else:
|
||||
assert val1[1][key][idx] == val2[1][key][idx]
|
||||
else:
|
||||
assert val1[1] == val2[1]
|
||||
else:
|
||||
assert val1 == val2
|
||||
|
||||
|
@ -104,6 +125,23 @@ def test_diff_opt_cache():
|
|||
_diff_opt(o1.o.s, q.o.s)
|
||||
|
||||
|
||||
def test_diff_opt_callback():
|
||||
b = BoolOption('b', '', callback=return_value)
|
||||
b2 = BoolOption('b2', '', callback=return_value, callback_params={'': ('yes',)})
|
||||
b3 = BoolOption('b3', '', callback=return_value, callback_params={'': ('yes', (b, False)), 'value': ('no',)})
|
||||
o = OptionDescription('o', '', [b, b2, b3])
|
||||
o1 = OptionDescription('o1', '', [o])
|
||||
o1.impl_build_cache()
|
||||
|
||||
a = dumps(o1)
|
||||
q = loads(a)
|
||||
_diff_opt(o1, q)
|
||||
_diff_opt(o1.o, q.o)
|
||||
_diff_opt(o1.o.b, q.o.b)
|
||||
_diff_opt(o1.o.b2, q.o.b2)
|
||||
_diff_opt(o1.o.b3, q.o.b3)
|
||||
|
||||
|
||||
def test_no_state_attr():
|
||||
# all _state_xxx attributes should be deleted
|
||||
b = BoolOption('b', '')
|
||||
|
@ -119,3 +157,95 @@ def test_no_state_attr():
|
|||
_no_state(q.o.b)
|
||||
_no_state(q.o.u)
|
||||
_no_state(q.o.s)
|
||||
|
||||
|
||||
def test_state_config():
|
||||
val1 = BoolOption('val1', "")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||
try:
|
||||
cfg = Config(maconfig, persistent=True, session_id='29090931')
|
||||
except ValueError:
|
||||
cfg = Config(maconfig, session_id='29090931')
|
||||
cfg._impl_test = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
try:
|
||||
delete_session('29090931')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
|
||||
def test_state_properties():
|
||||
val1 = BoolOption('val1', "")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||
try:
|
||||
cfg = Config(maconfig, persistent=True, session_id='29090932')
|
||||
except ValueError:
|
||||
cfg = Config(maconfig, session_id='29090932')
|
||||
cfg._impl_test = True
|
||||
cfg.read_write()
|
||||
cfg.cfgimpl_get_settings()[val1].append('test')
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
try:
|
||||
delete_session('29090931')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
|
||||
def test_state_values():
|
||||
val1 = BoolOption('val1', "")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||
try:
|
||||
cfg = Config(maconfig, persistent=True, session_id='29090933')
|
||||
except ValueError:
|
||||
cfg = Config(maconfig, session_id='29090933')
|
||||
cfg._impl_test = True
|
||||
cfg.val1 = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
q.val1 = False
|
||||
#assert cfg.val1 is True
|
||||
assert q.val1 is False
|
||||
try:
|
||||
delete_session('29090931')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
|
||||
def test_state_values_owner():
|
||||
val1 = BoolOption('val1', "")
|
||||
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||
try:
|
||||
cfg = Config(maconfig, persistent=True, session_id='29090934')
|
||||
except ValueError:
|
||||
cfg = Config(maconfig, session_id='29090934')
|
||||
cfg._impl_test = True
|
||||
owners.addowner('newowner')
|
||||
cfg.cfgimpl_get_settings().setowner(owners.newowner)
|
||||
cfg.val1 = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
q.val1 = False
|
||||
nval1 = q.cfgimpl_get_description().val1
|
||||
assert q.getowner(nval1) == owners.newowner
|
||||
try:
|
||||
delete_session('29090931')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
|
|
@ -23,11 +23,9 @@ from tiramisu.error import PropertiesOptionError, ConfigError
|
|||
from tiramisu.i18n import _
|
||||
# ____________________________________________________________
|
||||
|
||||
def carry_out_calculation(name,
|
||||
config,
|
||||
callback,
|
||||
callback_params,
|
||||
index=None):
|
||||
|
||||
def carry_out_calculation(name, config, callback, callback_params,
|
||||
index=None, max_len=None):
|
||||
"""a function that carries out a calculation for an option's value
|
||||
|
||||
:param name: the option name (`opt._name`)
|
||||
|
@ -40,73 +38,161 @@ def carry_out_calculation(name,
|
|||
:type callback_params: dict
|
||||
:param index: if an option is multi, only calculates the nth value
|
||||
:type index: int
|
||||
"""
|
||||
#callback, callback_params = option.getcallback()
|
||||
#if callback_params is None:
|
||||
# callback_params = {}
|
||||
tcparams = {}
|
||||
one_is_multi = False
|
||||
len_multi = 0
|
||||
:param max_len: max length for a multi
|
||||
:type max_len: int
|
||||
|
||||
for key, values in callback_params.items():
|
||||
for value in values:
|
||||
if type(value) == tuple:
|
||||
path, check_disabled = value
|
||||
if config is None:
|
||||
if check_disabled:
|
||||
continue
|
||||
raise ConfigError(_('no config specified but needed'))
|
||||
The callback_params is a dict. Key is used to build args (if key is '')
|
||||
and kwargs (otherwise). Values are tuple of:
|
||||
- values
|
||||
- tuple with option and boolean's force_permissive (True when don't raise
|
||||
if PropertiesOptionError)
|
||||
Values could have multiple values only when key is ''.
|
||||
|
||||
* if no callback_params:
|
||||
=> calculate()
|
||||
|
||||
* if callback_params={'': ('yes',)}
|
||||
=> calculate('yes')
|
||||
|
||||
* if callback_params={'value': ('yes',)}
|
||||
=> calculate(value='yes')
|
||||
|
||||
* if callback_params={'': ('yes', 'no')}
|
||||
=> calculate('yes', 'no')
|
||||
|
||||
* if callback_params={'value': ('yes', 'no')}
|
||||
=> ValueError()
|
||||
|
||||
* if callback_params={'': ((opt1, False),)}
|
||||
|
||||
- a simple option:
|
||||
opt1 == 11
|
||||
=> calculate(11)
|
||||
|
||||
- a multi option:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(1)
|
||||
=> calculate(2)
|
||||
=> calculate(3)
|
||||
|
||||
* if callback_params={'value': ((opt1, False),)}
|
||||
|
||||
- a simple option:
|
||||
opt1 == 11
|
||||
=> calculate(value=11)
|
||||
|
||||
- a multi option:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(value=1)
|
||||
=> calculate(value=2)
|
||||
=> calculate(value=3)
|
||||
|
||||
* if callback_params={'': ((opt1, False), (opt2, False))}
|
||||
|
||||
- a multi option with a simple option
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == 11
|
||||
=> calculate(1, 11)
|
||||
=> calculate(2, 11)
|
||||
=> calculate(3, 11)
|
||||
|
||||
- a multi option with an other multi option but with same length
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == [11, 12, 13]
|
||||
=> calculate(1, 11)
|
||||
=> calculate(2, 12)
|
||||
=> calculate(3, 13)
|
||||
|
||||
- a multi option with an other multi option but with different length
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == [11, 12]
|
||||
=> ConfigError()
|
||||
|
||||
- a multi option without value with a simple option
|
||||
opt1 == []
|
||||
opt2 == 11
|
||||
=> []
|
||||
|
||||
* if callback_params={'value': ((opt1, False), (opt2, False))}
|
||||
=> ConfigError()
|
||||
|
||||
If index is not None, return a value, otherwise return:
|
||||
|
||||
* a list if one parameters have multi option
|
||||
* a value otherwise
|
||||
|
||||
If calculate return list, this list is extend to return value.
|
||||
"""
|
||||
tcparams = {}
|
||||
# if callback_params has a callback, launch several time calculate()
|
||||
one_is_multi = False
|
||||
# multi's option should have same value for all option
|
||||
len_multi = None
|
||||
|
||||
for key, callbacks in callback_params.items():
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
# callbk is something link (opt, True|False)
|
||||
option, force_permissive = callbk
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(
|
||||
option)
|
||||
# get value
|
||||
try:
|
||||
opt_value = config._getattr(path, force_permissive=True)
|
||||
opt = config.unwrap_from_path(path, force_permissive=True)
|
||||
value = config._getattr(path, force_permissive=True)
|
||||
except PropertiesOptionError as err:
|
||||
if check_disabled:
|
||||
if force_permissive:
|
||||
continue
|
||||
raise ConfigError(_('unable to carry out a calculation, '
|
||||
'option {0} has properties: {1} for: '
|
||||
'{2}').format(path, err.proptype,
|
||||
'{2}').format(option._name,
|
||||
err.proptype,
|
||||
name))
|
||||
is_multi = opt.impl_is_multi()
|
||||
is_multi = option.impl_is_multi()
|
||||
if is_multi:
|
||||
if opt_value is not None:
|
||||
len_value = len(opt_value)
|
||||
if len_multi != 0 and len_multi != len_value:
|
||||
raise ConfigError(_('unable to carry out a '
|
||||
'calculation, option value with'
|
||||
' multi types must have same '
|
||||
'length for: {0}').format(name))
|
||||
len_multi = len_value
|
||||
len_value = len(value)
|
||||
if len_multi is not None and len_multi != len_value:
|
||||
raise ConfigError(_('unable to carry out a '
|
||||
'calculation, option value with'
|
||||
' multi types must have same '
|
||||
'length for: {0}').format(name))
|
||||
len_multi = len_value
|
||||
one_is_multi = True
|
||||
tcparams.setdefault(key, []).append((opt_value, is_multi))
|
||||
tcparams.setdefault(key, []).append((value, is_multi))
|
||||
else:
|
||||
tcparams.setdefault(key, []).append((value, False))
|
||||
# callbk is a value and not a multi
|
||||
tcparams.setdefault(key, []).append((callbk, False))
|
||||
|
||||
# if one value is a multi, launch several time calculate
|
||||
# if index is set, return a value
|
||||
# if no index, return a list
|
||||
if one_is_multi:
|
||||
ret = []
|
||||
if index:
|
||||
range_ = [index]
|
||||
if index < len_multi:
|
||||
range_ = [index]
|
||||
else:
|
||||
range_ = []
|
||||
ret = None
|
||||
else:
|
||||
range_ = range(len_multi)
|
||||
if max_len and max_len < len_multi:
|
||||
range_ = range(max_len)
|
||||
else:
|
||||
range_ = range(len_multi)
|
||||
for incr in range_:
|
||||
tcp = {}
|
||||
params = []
|
||||
args = []
|
||||
kwargs = {}
|
||||
for key, couples in tcparams.items():
|
||||
for couple in couples:
|
||||
value, ismulti = couple
|
||||
if ismulti and value is not None:
|
||||
if key == '':
|
||||
params.append(value[incr])
|
||||
else:
|
||||
if len(value) > incr:
|
||||
tcp[key] = value[incr]
|
||||
else:
|
||||
tcp[key] = ''
|
||||
if ismulti:
|
||||
val = value[incr]
|
||||
else:
|
||||
if key == '':
|
||||
params.append(value)
|
||||
else:
|
||||
tcp[key] = value
|
||||
calc = calculate(name, callback, params, tcp)
|
||||
val = value
|
||||
if key == '':
|
||||
args.append(val)
|
||||
else:
|
||||
kwargs[key] = val
|
||||
calc = calculate(callback, args, kwargs)
|
||||
if index:
|
||||
ret = calc
|
||||
else:
|
||||
|
@ -114,28 +200,28 @@ def carry_out_calculation(name,
|
|||
ret.extend(calc)
|
||||
else:
|
||||
ret.append(calc)
|
||||
|
||||
return ret
|
||||
else:
|
||||
tcp = {}
|
||||
params = []
|
||||
# no value is multi
|
||||
# return a single value
|
||||
args = []
|
||||
kwargs = {}
|
||||
for key, couples in tcparams.items():
|
||||
for couple in couples:
|
||||
# couple[1] (ismulti) is always False
|
||||
if key == '':
|
||||
value = couple[0]
|
||||
params.append(value)
|
||||
args.append(couple[0])
|
||||
else:
|
||||
tcp[key] = couple[0]
|
||||
return calculate(name, callback, params, tcp)
|
||||
kwargs[key] = couple[0]
|
||||
return calculate(callback, args, kwargs)
|
||||
|
||||
|
||||
def calculate(name, callback, params, tcparams):
|
||||
# FIXME we don't need the option's name down there.
|
||||
def calculate(callback, args, kwargs):
|
||||
"""wrapper that launches the 'callback'
|
||||
|
||||
:param callback: callback name
|
||||
:param params: in the callback's arity, the unnamed parameters
|
||||
:param tcparams: in the callback's arity, the named parameters
|
||||
:param callback: callback function
|
||||
:param args: in the callback's arity, the unnamed parameters
|
||||
:param kwargs: in the callback's arity, the named parameters
|
||||
|
||||
"""
|
||||
return callback(*params, **tcparams)
|
||||
return callback(*args, **kwargs)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"options handler global entry point"
|
||||
# Copyright (C) 2012-2013 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
@ -20,17 +19,23 @@
|
|||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# the whole pypy projet is under MIT licence
|
||||
# ____________________________________________________________
|
||||
"options handler global entry point"
|
||||
import weakref
|
||||
from tiramisu.error import PropertiesOptionError, ConfigError
|
||||
from tiramisu.option import OptionDescription, Option, SymLinkOption
|
||||
from tiramisu.setting import groups, Settings, default_encoding
|
||||
from tiramisu.storage import get_storages
|
||||
from tiramisu.value import Values
|
||||
from tiramisu.storage import get_storages, get_storage, set_storage, \
|
||||
_impl_getstate_setting
|
||||
from tiramisu.value import Values, Multi
|
||||
from tiramisu.i18n import _
|
||||
|
||||
|
||||
class SubConfig(object):
|
||||
"sub configuration management entry"
|
||||
"""Sub configuration management entry.
|
||||
Tree if OptionDescription's responsability. SubConfig are generated
|
||||
on-demand. A Config is also a SubConfig.
|
||||
Root Config is call context below
|
||||
"""
|
||||
__slots__ = ('_impl_context', '_impl_descr', '_impl_path')
|
||||
|
||||
def __init__(self, descr, context, subpath=None):
|
||||
|
@ -55,6 +60,7 @@ class SubConfig(object):
|
|||
|
||||
def cfgimpl_reset_cache(self, only_expired=False, only=('values',
|
||||
'settings')):
|
||||
"remove cache (in context)"
|
||||
self._cfgimpl_get_context().cfgimpl_reset_cache(only_expired, only)
|
||||
|
||||
def cfgimpl_get_home_by_path(self, path, force_permissive=False,
|
||||
|
@ -179,7 +185,9 @@ class SubConfig(object):
|
|||
homeconfig, name = self.cfgimpl_get_home_by_path(name)
|
||||
return homeconfig.__setattr__(name, value)
|
||||
child = getattr(self.cfgimpl_get_description(), name)
|
||||
if not isinstance(child, SymLinkOption):
|
||||
if isinstance(child, OptionDescription):
|
||||
raise TypeError(_("can't assign to an OptionDescription"))
|
||||
elif not isinstance(child, SymLinkOption):
|
||||
if self._impl_path is None:
|
||||
path = name
|
||||
else:
|
||||
|
@ -293,12 +301,13 @@ class SubConfig(object):
|
|||
return True
|
||||
try:
|
||||
value = getattr(self, path)
|
||||
if value == byvalue:
|
||||
return True
|
||||
if isinstance(value, Multi):
|
||||
return byvalue in value
|
||||
else:
|
||||
return value == byvalue
|
||||
except PropertiesOptionError: # a property is a restriction
|
||||
# upon the access of the value
|
||||
pass
|
||||
return False
|
||||
return False
|
||||
|
||||
def _filter_by_type():
|
||||
if bytype is None:
|
||||
|
@ -323,15 +332,15 @@ class SubConfig(object):
|
|||
continue
|
||||
if not _filter_by_value():
|
||||
continue
|
||||
if not _filter_by_type():
|
||||
continue
|
||||
#remove option with propertyerror, ...
|
||||
if check_properties:
|
||||
if byvalue is None and check_properties:
|
||||
try:
|
||||
value = getattr(self, path)
|
||||
except PropertiesOptionError:
|
||||
# a property restricts the access of the value
|
||||
continue
|
||||
if not _filter_by_type():
|
||||
continue
|
||||
if type_ == 'value':
|
||||
retval = value
|
||||
elif type_ == 'path':
|
||||
|
@ -521,7 +530,7 @@ class CommonConfig(SubConfig):
|
|||
# ____________________________________________________________
|
||||
class Config(CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = ('__weakref__', )
|
||||
__slots__ = ('__weakref__', '_impl_test')
|
||||
|
||||
def __init__(self, descr, session_id=None, persistent=False):
|
||||
""" Configuration option management master class
|
||||
|
@ -542,6 +551,43 @@ class Config(CommonConfig):
|
|||
super(Config, self).__init__(descr, weakref.ref(self))
|
||||
self._impl_build_all_paths()
|
||||
self._impl_meta = None
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
def __getstate__(self):
|
||||
if self._impl_meta is not None:
|
||||
raise ConfigError('cannot serialize Config with meta')
|
||||
slots = set()
|
||||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['_impl_context', '__weakref__'])
|
||||
state = {}
|
||||
for slot in slots:
|
||||
try:
|
||||
state[slot] = getattr(self, slot)
|
||||
except AttributeError:
|
||||
pass
|
||||
storage = self._impl_values._p_._storage
|
||||
if not storage.serializable:
|
||||
raise ConfigError('this storage is not serialisable, could be a '
|
||||
'none persistent storage')
|
||||
state['_storage'] = {'session_id': storage.session_id,
|
||||
'persistent': storage.persistent}
|
||||
state['_impl_setting'] = _impl_getstate_setting()
|
||||
return state
|
||||
|
||||
def __setstate__(self, state):
|
||||
for key, value in state.items():
|
||||
if key not in ['_storage', '_impl_setting']:
|
||||
setattr(self, key, value)
|
||||
set_storage(**state['_impl_setting'])
|
||||
self._impl_context = weakref.ref(self)
|
||||
self._impl_settings.context = weakref.ref(self)
|
||||
self._impl_values.context = weakref.ref(self)
|
||||
storage = get_storage(test=self._impl_test, **state['_storage'])
|
||||
self._impl_values._impl_setstate(storage)
|
||||
self._impl_settings._impl_setstate(storage)
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
|
|
|
@ -61,3 +61,35 @@ class SlaveError(Exception):
|
|||
class ConstError(TypeError):
|
||||
"no uniq value in _NameSpace"
|
||||
pass
|
||||
|
||||
|
||||
#Warning
|
||||
class ValueWarning(UserWarning):
|
||||
"""Option could warn user and not raise ValueError.
|
||||
|
||||
Example:
|
||||
|
||||
>>> import warnings
|
||||
>>> from tiramisu.error import ValueWarning
|
||||
>>> from tiramisu.option import StrOption, OptionDescription
|
||||
>>> from tiramisu.config import Config
|
||||
>>> warnings.simplefilter("always", ValueWarning)
|
||||
>>> def a(val):
|
||||
... raise ValueError('pouet')
|
||||
...
|
||||
>>> s=StrOption('s', '', validator=a, warnings_only=True)
|
||||
>>> o=OptionDescription('o', '', [s])
|
||||
>>> c=Config(o)
|
||||
>>> c.s = 'val'
|
||||
StrOption:0: ValueWarning: invalid value val for option s: pouet
|
||||
>>> with warnings.catch_warnings(record=True) as w:
|
||||
... c.s = 'val'
|
||||
...
|
||||
>>> w[0].message.opt == s
|
||||
True
|
||||
>>> print str(w[0].message)
|
||||
invalid value val for option s: pouet
|
||||
"""
|
||||
def __init__(self, msg, opt):
|
||||
self.opt = opt
|
||||
super(ValueWarning, self).__init__(msg)
|
||||
|
|
|
@ -25,8 +25,9 @@ import sys
|
|||
from copy import copy, deepcopy
|
||||
from types import FunctionType
|
||||
from IPy import IP
|
||||
import warnings
|
||||
|
||||
from tiramisu.error import ConflictError
|
||||
from tiramisu.error import ConfigError, ConflictError, ValueWarning
|
||||
from tiramisu.setting import groups, multitypes
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.autolib import carry_out_calculation
|
||||
|
@ -60,9 +61,8 @@ class BaseOption(object):
|
|||
__setattr__ method
|
||||
"""
|
||||
__slots__ = ('_name', '_requires', '_properties', '_readonly',
|
||||
'_consistencies', '_calc_properties', '_impl_informations',
|
||||
'_state_consistencies', '_state_readonly', '_state_requires',
|
||||
'_stated')
|
||||
'_calc_properties', '_impl_informations',
|
||||
'_state_readonly', '_state_requires', '_stated')
|
||||
|
||||
def __init__(self, name, doc, requires, properties):
|
||||
if not valid_name(name):
|
||||
|
@ -72,7 +72,6 @@ class BaseOption(object):
|
|||
self.impl_set_information('doc', doc)
|
||||
self._calc_properties, self._requires = validate_requires_arg(
|
||||
requires, self._name)
|
||||
self._consistencies = None
|
||||
if properties is None:
|
||||
properties = tuple()
|
||||
if not isinstance(properties, tuple):
|
||||
|
@ -97,8 +96,7 @@ class BaseOption(object):
|
|||
"frozen" (which has noting to do with the high level "freeze"
|
||||
propertie or "read_only" property)
|
||||
"""
|
||||
if not name.startswith('_state') and \
|
||||
name not in ('_cache_paths', '_consistencies'):
|
||||
if not name.startswith('_state') and not name.startswith('_cache'):
|
||||
is_readonly = False
|
||||
# never change _name
|
||||
if name == '_name':
|
||||
|
@ -108,15 +106,12 @@ class BaseOption(object):
|
|||
is_readonly = True
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
if self._readonly is True:
|
||||
if value is True:
|
||||
# already readonly and try to re set readonly
|
||||
# don't raise, just exit
|
||||
return
|
||||
is_readonly = True
|
||||
except AttributeError:
|
||||
pass
|
||||
elif name != '_readonly':
|
||||
try:
|
||||
if self._readonly is True:
|
||||
is_readonly = True
|
||||
except AttributeError:
|
||||
self._readonly = False
|
||||
if is_readonly:
|
||||
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||
" read-only").format(
|
||||
|
@ -148,56 +143,6 @@ class BaseOption(object):
|
|||
raise ValueError(_("information's item not found: {0}").format(
|
||||
key))
|
||||
|
||||
# serialize/unserialize
|
||||
def _impl_convert_consistencies(self, descr, load=False):
|
||||
"""during serialization process, many things have to be done.
|
||||
one of them is the localisation of the options.
|
||||
The paths are set once for all.
|
||||
|
||||
:type descr: :class:`tiramisu.option.OptionDescription`
|
||||
:param load: `True` if we are at the init of the option description
|
||||
:type load: bool
|
||||
"""
|
||||
if not load and self._consistencies is None:
|
||||
self._state_consistencies = None
|
||||
elif load and self._state_consistencies is None:
|
||||
self._consistencies = None
|
||||
del(self._state_consistencies)
|
||||
else:
|
||||
if load:
|
||||
consistencies = self._state_consistencies
|
||||
else:
|
||||
consistencies = self._consistencies
|
||||
if isinstance(consistencies, list):
|
||||
new_value = []
|
||||
for consistency in consistencies:
|
||||
if load:
|
||||
new_value.append((consistency[0],
|
||||
descr.impl_get_opt_by_path(
|
||||
consistency[1])))
|
||||
else:
|
||||
new_value.append((consistency[0],
|
||||
descr.impl_get_path_by_opt(
|
||||
consistency[1])))
|
||||
|
||||
else:
|
||||
new_value = {}
|
||||
for key, _consistencies in consistencies.items():
|
||||
new_value[key] = []
|
||||
for key_cons, _cons in _consistencies:
|
||||
_list_cons = []
|
||||
for _con in _cons:
|
||||
if load:
|
||||
_list_cons.append(descr.impl_get_opt_by_path(_con))
|
||||
else:
|
||||
_list_cons.append(descr.impl_get_path_by_opt(_con))
|
||||
new_value[key].append((key_cons, tuple(_list_cons)))
|
||||
if load:
|
||||
del(self._state_consistencies)
|
||||
self._consistencies = new_value
|
||||
else:
|
||||
self._state_consistencies = new_value
|
||||
|
||||
def _impl_convert_requires(self, descr, load=False):
|
||||
"""export of the requires during the serialization process
|
||||
|
||||
|
@ -240,12 +185,10 @@ class BaseOption(object):
|
|||
:param descr: the parent :class:`tiramisu.option.OptionDescription`
|
||||
"""
|
||||
self._stated = True
|
||||
self._impl_convert_consistencies(descr)
|
||||
self._impl_convert_requires(descr)
|
||||
try:
|
||||
self._state_readonly = self._readonly
|
||||
except AttributeError:
|
||||
pass
|
||||
for func in dir(self):
|
||||
if func.startswith('_impl_convert_'):
|
||||
getattr(self, func)(descr)
|
||||
self._state_readonly = self._readonly
|
||||
|
||||
def __getstate__(self, stated=True):
|
||||
"""special method to enable the serialization with pickle
|
||||
|
@ -265,7 +208,8 @@ class BaseOption(object):
|
|||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['_cache_paths', '__weakref__'])
|
||||
slots -= frozenset(['_cache_paths', '_cache_consistencies',
|
||||
'__weakref__'])
|
||||
states = {}
|
||||
for slot in slots:
|
||||
# remove variable if save variable converted
|
||||
|
@ -292,8 +236,9 @@ class BaseOption(object):
|
|||
|
||||
:type descr: :class:`tiramisu.option.OptionDescription`
|
||||
"""
|
||||
self._impl_convert_consistencies(descr, load=True)
|
||||
self._impl_convert_requires(descr, load=True)
|
||||
for func in dir(self):
|
||||
if func.startswith('_impl_convert_'):
|
||||
getattr(self, func)(descr, load=True)
|
||||
try:
|
||||
self._readonly = self._state_readonly
|
||||
del(self._state_readonly)
|
||||
|
@ -322,13 +267,15 @@ class Option(BaseOption):
|
|||
Reminder: an Option object is **not** a container for the value.
|
||||
"""
|
||||
__slots__ = ('_multi', '_validator', '_default_multi', '_default',
|
||||
'_callback', '_multitype', '_master_slaves', '__weakref__')
|
||||
'_state_callback', '_callback', '_multitype',
|
||||
'_consistencies', '_warnings_only', '_master_slaves',
|
||||
'_state_consistencies', '__weakref__')
|
||||
_empty = ''
|
||||
|
||||
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):
|
||||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, warnings_only=False):
|
||||
"""
|
||||
:param name: the option's name
|
||||
:param doc: the option's description
|
||||
|
@ -344,18 +291,17 @@ class Option(BaseOption):
|
|||
:param callback_params: the callback's parameter
|
||||
:param validator: the name of a function which stands for a custom
|
||||
validation of the value
|
||||
:param validator_args: the validator's parameters
|
||||
:param validator_params: the validator's parameters
|
||||
:param properties: tuple of default properties
|
||||
:param warnings_only: _validator and _consistencies don't raise if True
|
||||
Values()._warning contain message
|
||||
|
||||
"""
|
||||
super(Option, self).__init__(name, doc, requires, properties)
|
||||
self._multi = multi
|
||||
if validator is not None:
|
||||
if type(validator) != FunctionType:
|
||||
raise TypeError(_("validator must be a function"))
|
||||
if validator_args is None:
|
||||
validator_args = {}
|
||||
self._validator = (validator, validator_args)
|
||||
validate_callback(validator, validator_params, 'validator')
|
||||
self._validator = (validator, validator_params)
|
||||
else:
|
||||
self._validator = None
|
||||
if not self._multi and default_multi is not None:
|
||||
|
@ -377,11 +323,7 @@ class Option(BaseOption):
|
|||
"no callback defined"
|
||||
" yet for option {0}").format(name))
|
||||
if callback is not None:
|
||||
if type(callback) != FunctionType:
|
||||
raise ValueError('callback must be a function')
|
||||
if callback_params is not None and \
|
||||
not isinstance(callback_params, dict):
|
||||
raise ValueError('callback_params must be a dict')
|
||||
validate_callback(callback, callback_params, 'callback')
|
||||
self._callback = (callback, callback_params)
|
||||
else:
|
||||
self._callback = None
|
||||
|
@ -390,101 +332,124 @@ class Option(BaseOption):
|
|||
default = []
|
||||
self._multitype = multitypes.default
|
||||
self._default_multi = default_multi
|
||||
self._warnings_only = warnings_only
|
||||
self.impl_validate(default)
|
||||
self._default = default
|
||||
self._consistencies = None
|
||||
|
||||
def _launch_consistency(self, func, opt, vals, context, index, opt_):
|
||||
def _launch_consistency(self, func, option, value, context, index,
|
||||
all_cons_opts):
|
||||
"""Launch consistency now
|
||||
|
||||
:param func: function name, this name should start with _cons_
|
||||
:type func: `str`
|
||||
:param option: option that value is changing
|
||||
:type option: `tiramisu.option.Option`
|
||||
:param value: new value of this option
|
||||
:param context: Config's context, if None, check default value instead
|
||||
:type context: `tiramisu.config.Config`
|
||||
:param index: only for multi option, consistency should be launch for
|
||||
specified index
|
||||
:type index: `int`
|
||||
:param all_cons_opts: all options concerne by this consistency
|
||||
:type all_cons_opts: `list` of `tiramisu.option.Option`
|
||||
"""
|
||||
if context is not None:
|
||||
descr = context.cfgimpl_get_description()
|
||||
if opt is self:
|
||||
#values are for self, search opt_ values
|
||||
values = vals
|
||||
if context is not None:
|
||||
path = descr.impl_get_path_by_opt(opt_)
|
||||
values_ = context._getattr(path, validate=False)
|
||||
else:
|
||||
values_ = opt_.impl_getdefault()
|
||||
if index is not None:
|
||||
#value is not already set, could be higher
|
||||
try:
|
||||
values_ = values_[index]
|
||||
except IndexError:
|
||||
values_ = None
|
||||
else:
|
||||
#values are for opt_, search self values
|
||||
values_ = vals
|
||||
if context is not None:
|
||||
path = descr.impl_get_path_by_opt(self)
|
||||
values = context._getattr(path, validate=False)
|
||||
else:
|
||||
values = self.impl_getdefault()
|
||||
if index is not None:
|
||||
#value is not already set, could be higher
|
||||
try:
|
||||
values = values[index]
|
||||
except IndexError:
|
||||
values = None
|
||||
if index is None and self.impl_is_multi():
|
||||
for index in range(0, len(values)):
|
||||
try:
|
||||
value = values[index]
|
||||
value_ = values_[index]
|
||||
except IndexError:
|
||||
value = None
|
||||
value_ = None
|
||||
if None not in (value, value_):
|
||||
getattr(self, func)(opt_._name, value, value_)
|
||||
else:
|
||||
if None not in (values, values_):
|
||||
getattr(self, func)(opt_._name, values, values_)
|
||||
#option is also in all_cons_opts
|
||||
if option not in all_cons_opts:
|
||||
raise ConfigError(_('option not in all_cons_opts'))
|
||||
|
||||
def impl_validate(self, value, context=None, validate=True):
|
||||
all_cons_vals = []
|
||||
for opt in all_cons_opts:
|
||||
#get value
|
||||
if option == opt:
|
||||
opt_value = value
|
||||
else:
|
||||
#if context, calculate value, otherwise get default value
|
||||
if context is not None:
|
||||
opt_value = context._getattr(
|
||||
descr.impl_get_path_by_opt(opt), validate=False)
|
||||
else:
|
||||
opt_value = opt.impl_getdefault()
|
||||
|
||||
#append value
|
||||
if not self.impl_is_multi() or option == opt:
|
||||
all_cons_vals.append(opt_value)
|
||||
else:
|
||||
#value is not already set, could be higher index
|
||||
try:
|
||||
all_cons_vals.append(opt_value[index])
|
||||
except IndexError:
|
||||
#so return if no value
|
||||
return
|
||||
getattr(self, func)(all_cons_opts, all_cons_vals)
|
||||
|
||||
def impl_validate(self, value, context=None, validate=True,
|
||||
force_index=None):
|
||||
"""
|
||||
:param value: the option's value
|
||||
:param context: Config's context
|
||||
:type context: :class:`tiramisu.config.Config`
|
||||
:param validate: if true enables ``self._validator`` validation
|
||||
:type validate: boolean
|
||||
:param force_no_multi: if multi, value has to be a list
|
||||
not if force_no_multi is True
|
||||
:type force_no_multi: boolean
|
||||
"""
|
||||
if not validate:
|
||||
return
|
||||
|
||||
def val_validator(val):
|
||||
if self._validator is not None:
|
||||
callback_params = deepcopy(self._validator[1])
|
||||
callback_params.setdefault('', []).insert(0, val)
|
||||
return carry_out_calculation(self._name, config=context,
|
||||
callback=self._validator[0],
|
||||
callback_params=callback_params)
|
||||
else:
|
||||
return True
|
||||
if self._validator[1] is not None:
|
||||
validator_params = deepcopy(self._validator[1])
|
||||
if '' in validator_params:
|
||||
lst = list(validator_params[''])
|
||||
lst.insert(0, val)
|
||||
validator_params[''] = tuple(lst)
|
||||
else:
|
||||
validator_params[''] = (val,)
|
||||
else:
|
||||
validator_params = {'': (val,)}
|
||||
# Raise ValueError if not valid
|
||||
carry_out_calculation(self._name, config=context,
|
||||
callback=self._validator[0],
|
||||
callback_params=validator_params)
|
||||
|
||||
def do_validation(_value, _index=None):
|
||||
if _value is None:
|
||||
return True
|
||||
if not val_validator(_value):
|
||||
raise ValueError(_("invalid value {0} "
|
||||
"for option {1} for object {2}"
|
||||
).format(_value,
|
||||
self._name,
|
||||
self.__class__.__name__))
|
||||
return
|
||||
# option validation
|
||||
self._validate(_value)
|
||||
try:
|
||||
self._validate(_value)
|
||||
# valid with self._validator
|
||||
val_validator(_value)
|
||||
# if not context launch consistency validation
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
self._second_level_validation(_value)
|
||||
except ValueError as err:
|
||||
raise ValueError(_("invalid value {0} for option {1}: {2}"
|
||||
"").format(_value, self._name, err))
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
msg = _("invalid value {0} for option {1}: {2}").format(
|
||||
_value, self._name, err)
|
||||
if self._warnings_only:
|
||||
warnings.warn_explicit(ValueWarning(msg, self),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
else:
|
||||
raise ValueError(msg)
|
||||
|
||||
# generic calculation
|
||||
if context is not None:
|
||||
descr = context.cfgimpl_get_description()
|
||||
if not self._multi:
|
||||
do_validation(value)
|
||||
|
||||
if not self._multi or force_index is not None:
|
||||
do_validation(value, force_index)
|
||||
else:
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("invalid value {0} for option {1} "
|
||||
"which must be a list").format(value,
|
||||
raise ValueError(_("which must be a list").format(value,
|
||||
self._name))
|
||||
for index in range(0, len(value)):
|
||||
val = value[index]
|
||||
for index, val in enumerate(value):
|
||||
do_validation(val, index)
|
||||
|
||||
def impl_getdefault(self, default_multi=False):
|
||||
|
@ -529,29 +494,133 @@ class Option(BaseOption):
|
|||
def impl_is_multi(self):
|
||||
return self._multi
|
||||
|
||||
def impl_add_consistency(self, func, opt):
|
||||
def impl_add_consistency(self, func, *other_opts):
|
||||
"""Add consistency means that value will be validate with other_opts
|
||||
option's values.
|
||||
|
||||
:param func: function's name
|
||||
:type func: `str`
|
||||
:param other_opts: options used to validate value
|
||||
:type other_opts: `list` of `tiramisu.option.Option`
|
||||
"""
|
||||
if self._consistencies is None:
|
||||
self._consistencies = []
|
||||
if not isinstance(opt, Option):
|
||||
raise ValueError('consistency must be set with an option')
|
||||
if self is opt:
|
||||
raise ValueError('cannot add consistency with itself')
|
||||
if self.impl_is_multi() != opt.impl_is_multi():
|
||||
raise ValueError('options in consistency'
|
||||
' should be multi in two sides')
|
||||
for opt in other_opts:
|
||||
if not isinstance(opt, Option):
|
||||
raise ConfigError(_('consistency should be set with an option'))
|
||||
if self is opt:
|
||||
raise ConfigError(_('cannot add consistency with itself'))
|
||||
if self.impl_is_multi() != opt.impl_is_multi():
|
||||
raise ConfigError(_('every options in consistency should be '
|
||||
'multi or none'))
|
||||
func = '_cons_{0}'.format(func)
|
||||
self._launch_consistency(func,
|
||||
self,
|
||||
self.impl_getdefault(),
|
||||
None, None, opt)
|
||||
self._consistencies.append((func, opt))
|
||||
all_cons_opts = tuple([self] + list(other_opts))
|
||||
value = self.impl_getdefault()
|
||||
if value is not None:
|
||||
if self.impl_is_multi():
|
||||
for idx, val in enumerate(value):
|
||||
self._launch_consistency(func, self, val, None,
|
||||
idx, all_cons_opts)
|
||||
else:
|
||||
self._launch_consistency(func, self, value, None,
|
||||
None, all_cons_opts)
|
||||
self._consistencies.append((func, all_cons_opts))
|
||||
self.impl_validate(self.impl_getdefault())
|
||||
|
||||
def _cons_not_equal(self, optname, value, value_):
|
||||
if value == value_:
|
||||
raise ValueError(_("invalid value {0} for option {1} "
|
||||
"must be different as {2} option"
|
||||
"").format(value, self._name, optname))
|
||||
def _cons_not_equal(self, opts, vals):
|
||||
for idx_inf, val_inf in enumerate(vals):
|
||||
for idx_sup, val_sup in enumerate(vals[idx_inf + 1:]):
|
||||
if val_inf == val_sup is not None:
|
||||
raise ValueError(_("same value for {0} and {1}").format(
|
||||
opts[idx_inf]._name, opts[idx_inf + idx_sup + 1]._name))
|
||||
|
||||
def _impl_convert_callbacks(self, descr, load=False):
|
||||
if not load and self._callback is None:
|
||||
self._state_callback = None
|
||||
elif load and self._state_callback is None:
|
||||
self._callback = None
|
||||
del(self._state_callback)
|
||||
else:
|
||||
if load:
|
||||
callback, callback_params = self._state_callback
|
||||
else:
|
||||
callback, callback_params = self._callback
|
||||
if callback_params is not None:
|
||||
cllbck_prms = {}
|
||||
for key, values in callback_params.items():
|
||||
vls = []
|
||||
for value in values:
|
||||
if isinstance(value, tuple):
|
||||
if load:
|
||||
value = (descr.impl_get_opt_by_path(value[0]),
|
||||
value[1])
|
||||
else:
|
||||
value = (descr.impl_get_path_by_opt(value[0]),
|
||||
value[1])
|
||||
vls.append(value)
|
||||
cllbck_prms[key] = tuple(vls)
|
||||
else:
|
||||
cllbck_prms = None
|
||||
|
||||
if load:
|
||||
del(self._state_callback)
|
||||
self._callback = (callback, cllbck_prms)
|
||||
else:
|
||||
self._state_callback = (callback, cllbck_prms)
|
||||
|
||||
# serialize/unserialize
|
||||
def _impl_convert_consistencies(self, descr, load=False):
|
||||
"""during serialization process, many things have to be done.
|
||||
one of them is the localisation of the options.
|
||||
The paths are set once for all.
|
||||
|
||||
:type descr: :class:`tiramisu.option.OptionDescription`
|
||||
:param load: `True` if we are at the init of the option description
|
||||
:type load: bool
|
||||
"""
|
||||
if not load and self._consistencies is None:
|
||||
self._state_consistencies = None
|
||||
elif load and self._state_consistencies is None:
|
||||
self._consistencies = None
|
||||
del(self._state_consistencies)
|
||||
else:
|
||||
if load:
|
||||
consistencies = self._state_consistencies
|
||||
else:
|
||||
consistencies = self._consistencies
|
||||
if isinstance(consistencies, list):
|
||||
new_value = []
|
||||
for consistency in consistencies:
|
||||
values = []
|
||||
for obj in consistency[1]:
|
||||
if load:
|
||||
values.append(descr.impl_get_opt_by_path(obj))
|
||||
else:
|
||||
values.append(descr.impl_get_path_by_opt(obj))
|
||||
new_value.append((consistency[0], tuple(values)))
|
||||
|
||||
else:
|
||||
new_value = {}
|
||||
for key, _consistencies in consistencies.items():
|
||||
new_value[key] = []
|
||||
for key_cons, _cons in _consistencies:
|
||||
_list_cons = []
|
||||
for _con in _cons:
|
||||
if load:
|
||||
_list_cons.append(
|
||||
descr.impl_get_opt_by_path(_con))
|
||||
else:
|
||||
_list_cons.append(
|
||||
descr.impl_get_path_by_opt(_con))
|
||||
new_value[key].append((key_cons, tuple(_list_cons)))
|
||||
if load:
|
||||
del(self._state_consistencies)
|
||||
self._consistencies = new_value
|
||||
else:
|
||||
self._state_consistencies = new_value
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
pass
|
||||
|
||||
|
||||
class ChoiceOption(Option):
|
||||
|
@ -566,7 +635,7 @@ class ChoiceOption(Option):
|
|||
def __init__(self, name, doc, values, default=None, default_multi=None,
|
||||
requires=None, multi=False, callback=None,
|
||||
callback_params=None, open_values=False, validator=None,
|
||||
validator_args=None, properties=()):
|
||||
validator_params=None, properties=None, warnings_only=False):
|
||||
"""
|
||||
:param values: is a list of values the option can possibly take
|
||||
"""
|
||||
|
@ -584,8 +653,9 @@ class ChoiceOption(Option):
|
|||
requires=requires,
|
||||
multi=multi,
|
||||
validator=validator,
|
||||
validator_args=validator_args,
|
||||
properties=properties)
|
||||
validator_params=validator_params,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only)
|
||||
|
||||
def impl_get_values(self):
|
||||
return self._values
|
||||
|
@ -662,7 +732,7 @@ class SymLinkOption(BaseOption):
|
|||
__slots__ = ('_name', '_opt', '_state_opt')
|
||||
_opt_type = 'symlink'
|
||||
#not return _opt consistencies
|
||||
_consistencies = {}
|
||||
_consistencies = None
|
||||
|
||||
def __init__(self, name, opt):
|
||||
self._name = name
|
||||
|
@ -688,23 +758,19 @@ class SymLinkOption(BaseOption):
|
|||
del(self._state_opt)
|
||||
super(SymLinkOption, self)._impl_setstate(descr)
|
||||
|
||||
def _impl_convert_consistencies(self, descr, load=False):
|
||||
if load:
|
||||
del(self._state_consistencies)
|
||||
else:
|
||||
self._state_consistencies = None
|
||||
|
||||
|
||||
class IPOption(Option):
|
||||
"represents the choice of an ip"
|
||||
__slots__ = ('_only_private',)
|
||||
__slots__ = ('_private_only', '_allow_reserved')
|
||||
_opt_type = 'ip'
|
||||
|
||||
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, only_private=False):
|
||||
self._only_private = only_private
|
||||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, private_only=False, allow_reserved=False,
|
||||
warnings_only=False):
|
||||
self._private_only = private_only
|
||||
self._allow_reserved = allow_reserved
|
||||
super(IPOption, self).__init__(name, doc, default=default,
|
||||
default_multi=default_multi,
|
||||
callback=callback,
|
||||
|
@ -712,14 +778,21 @@ class IPOption(Option):
|
|||
requires=requires,
|
||||
multi=multi,
|
||||
validator=validator,
|
||||
validator_args=validator_args,
|
||||
properties=properties)
|
||||
validator_params=validator_params,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only)
|
||||
|
||||
def _validate(self, value):
|
||||
try:
|
||||
IP('{0}/32'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid IP {0}').format(self._name))
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
ip = IP('{0}/32'.format(value))
|
||||
if ip.iptype() == 'RESERVED':
|
||||
if not self._allow_reserved and ip.iptype() == 'RESERVED':
|
||||
raise ValueError(_("IP mustn't not be in reserved class"))
|
||||
if self._only_private and not ip.iptype() == 'PRIVATE':
|
||||
if self._private_only and not ip.iptype() == 'PRIVATE':
|
||||
raise ValueError(_("IP must be in private class"))
|
||||
|
||||
|
||||
|
@ -738,10 +811,10 @@ class PortOption(Option):
|
|||
|
||||
def __init__(self, name, doc, default=None, default_multi=None,
|
||||
requires=None, multi=False, callback=None,
|
||||
callback_params=None, validator=None, validator_args=None,
|
||||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, allow_range=False, allow_zero=False,
|
||||
allow_wellknown=True, allow_registred=True,
|
||||
allow_private=False):
|
||||
allow_private=False, warnings_only=False):
|
||||
self._allow_range = allow_range
|
||||
self._min_value = None
|
||||
self._max_value = None
|
||||
|
@ -772,8 +845,9 @@ class PortOption(Option):
|
|||
requires=requires,
|
||||
multi=multi,
|
||||
validator=validator,
|
||||
validator_args=validator_args,
|
||||
properties=properties)
|
||||
validator_params=validator_params,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only)
|
||||
|
||||
def _validate(self, value):
|
||||
if self._allow_range and ":" in str(value):
|
||||
|
@ -798,9 +872,15 @@ class NetworkOption(Option):
|
|||
_opt_type = 'network'
|
||||
|
||||
def _validate(self, value):
|
||||
try:
|
||||
IP(value)
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid network address {0}').format(self._name))
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
ip = IP(value)
|
||||
if ip.iptype() == 'RESERVED':
|
||||
raise ValueError(_("network mustn't not be in reserved class"))
|
||||
raise ValueError(_("network shall not be in reserved class"))
|
||||
|
||||
|
||||
class NetmaskOption(Option):
|
||||
|
@ -809,18 +889,26 @@ class NetmaskOption(Option):
|
|||
_opt_type = 'netmask'
|
||||
|
||||
def _validate(self, value):
|
||||
IP('0.0.0.0/{0}'.format(value))
|
||||
try:
|
||||
IP('0.0.0.0/{0}'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid netmask address {0}').format(self._name))
|
||||
|
||||
def _cons_network_netmask(self, optname, value, value_):
|
||||
def _cons_network_netmask(self, opts, vals):
|
||||
#opts must be (netmask, network) options
|
||||
self.__cons_netmask(optname, value, value_, False)
|
||||
if None in vals:
|
||||
return
|
||||
self.__cons_netmask(opts, vals[0], vals[1], False)
|
||||
|
||||
def _cons_ip_netmask(self, optname, value, value_):
|
||||
def _cons_ip_netmask(self, opts, vals):
|
||||
#opts must be (netmask, ip) options
|
||||
self.__cons_netmask(optname, value, value_, True)
|
||||
if None in vals:
|
||||
return
|
||||
self.__cons_netmask(opts, vals[0], vals[1], True)
|
||||
|
||||
#def __cons_netmask(self, opt, value, context, index, opts, make_net):
|
||||
def __cons_netmask(self, optname, val_netmask, val_ipnetwork, make_net):
|
||||
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net):
|
||||
if len(opts) != 2:
|
||||
raise ConfigError(_('invalid len for opts'))
|
||||
msg = None
|
||||
try:
|
||||
ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
|
||||
|
@ -846,23 +934,48 @@ class NetmaskOption(Option):
|
|||
else:
|
||||
msg = _("invalid network {0} ({1}) with netmask {2} ({3})")
|
||||
if msg is not None:
|
||||
raise ValueError(msg.format(val_ipnetwork, optname,
|
||||
raise ValueError(msg.format(val_ipnetwork, opts[1]._name,
|
||||
val_netmask, self._name))
|
||||
|
||||
|
||||
class BroadcastOption(Option):
|
||||
__slots__ = tuple()
|
||||
_opt_type = 'broadcast'
|
||||
|
||||
def _validate(self, value):
|
||||
try:
|
||||
IP('{0}/32'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid broadcast address {0}').format(self._name))
|
||||
|
||||
def _cons_broadcast(self, opts, vals):
|
||||
if len(vals) != 3:
|
||||
raise ConfigError(_('invalid len for vals'))
|
||||
if None in vals:
|
||||
return
|
||||
broadcast, network, netmask = vals
|
||||
if IP('{0}/{1}'.format(network, netmask)).broadcast() != IP(broadcast):
|
||||
raise ValueError(_('invalid broadcast {0} ({1}) with network {2} '
|
||||
'({3}) and netmask {4} ({5})').format(
|
||||
broadcast, opts[0]._name, network,
|
||||
opts[1]._name, netmask, opts[2]._name))
|
||||
|
||||
|
||||
class DomainnameOption(Option):
|
||||
"represents the choice of a domain name"
|
||||
"""represents the choice of a domain name
|
||||
netbios: for MS domain
|
||||
hostname: to identify the device
|
||||
domainname:
|
||||
fqdn: with tld, not supported yet
|
||||
"""
|
||||
__slots__ = ('_type', '_allow_ip')
|
||||
_opt_type = 'domainname'
|
||||
|
||||
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_ip=False, type_='domainname'):
|
||||
#netbios: for MS domain
|
||||
#hostname: to identify the device
|
||||
#domainname:
|
||||
#fqdn: with tld, not supported yet
|
||||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, allow_ip=False, type_='domainname',
|
||||
warnings_only=False):
|
||||
if type_ not in ['netbios', 'hostname', 'domainname']:
|
||||
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
||||
self._type = type_
|
||||
|
@ -876,8 +989,9 @@ class DomainnameOption(Option):
|
|||
requires=requires,
|
||||
multi=multi,
|
||||
validator=validator,
|
||||
validator_args=validator_args,
|
||||
properties=properties)
|
||||
validator_params=validator_params,
|
||||
properties=properties,
|
||||
warnings_only=warnings_only)
|
||||
|
||||
def _validate(self, value):
|
||||
if self._allow_ip is True:
|
||||
|
@ -915,9 +1029,9 @@ class OptionDescription(BaseOption):
|
|||
"""
|
||||
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
|
||||
'_state_group_type', '_properties', '_children',
|
||||
'_consistencies', '_calc_properties', '__weakref__',
|
||||
'_cache_consistencies', '_calc_properties', '__weakref__',
|
||||
'_readonly', '_impl_informations', '_state_requires',
|
||||
'_state_consistencies', '_stated', '_state_readonly')
|
||||
'_stated', '_state_readonly')
|
||||
_opt_type = 'optiondescription'
|
||||
|
||||
def __init__(self, name, doc, children, requires=None, properties=None):
|
||||
|
@ -938,6 +1052,7 @@ class OptionDescription(BaseOption):
|
|||
old = child
|
||||
self._children = (tuple(child_names), tuple(children))
|
||||
self._cache_paths = None
|
||||
self._cache_consistencies = None
|
||||
# the group_type is useful for filtering OptionDescriptions in a config
|
||||
self._group_type = groups.default
|
||||
|
||||
|
@ -1011,12 +1126,11 @@ class OptionDescription(BaseOption):
|
|||
if not force_no_consistencies and \
|
||||
option._consistencies is not None:
|
||||
for consistency in option._consistencies:
|
||||
func, opt = consistency
|
||||
opts = (option, opt)
|
||||
_consistencies.setdefault(opt,
|
||||
[]).append((func, opts))
|
||||
_consistencies.setdefault(option,
|
||||
[]).append((func, opts))
|
||||
func, all_cons_opts = consistency
|
||||
for opt in all_cons_opts:
|
||||
_consistencies.setdefault(opt,
|
||||
[]).append((func,
|
||||
all_cons_opts))
|
||||
else:
|
||||
_currpath.append(attr)
|
||||
option.impl_build_cache(cache_path,
|
||||
|
@ -1028,7 +1142,12 @@ class OptionDescription(BaseOption):
|
|||
if save:
|
||||
self._cache_paths = (tuple(cache_option), tuple(cache_path))
|
||||
if not force_no_consistencies:
|
||||
self._consistencies = _consistencies
|
||||
if _consistencies != {}:
|
||||
self._cache_consistencies = {}
|
||||
for opt, cons in _consistencies.items():
|
||||
if opt not in cache_option:
|
||||
raise ConfigError(_('consistency with option {0} which is not in Config').format(opt._name))
|
||||
self._cache_consistencies[opt] = tuple(cons)
|
||||
self._readonly = True
|
||||
|
||||
def impl_get_opt_by_path(self, path):
|
||||
|
@ -1099,17 +1218,18 @@ class OptionDescription(BaseOption):
|
|||
def impl_get_group_type(self):
|
||||
return self._group_type
|
||||
|
||||
def _valid_consistency(self, opt, value, context=None, index=None):
|
||||
consistencies = self._consistencies.get(opt)
|
||||
def _valid_consistency(self, option, value, context, index):
|
||||
if self._cache_consistencies is None:
|
||||
return True
|
||||
#consistencies is something like [('_cons_not_equal', (opt1, opt2))]
|
||||
consistencies = self._cache_consistencies.get(option)
|
||||
if consistencies is not None:
|
||||
for consistency in consistencies:
|
||||
opt_ = consistency[1]
|
||||
ret = opt_[0]._launch_consistency(consistency[0],
|
||||
opt,
|
||||
value,
|
||||
context,
|
||||
index,
|
||||
opt_[1])
|
||||
for func, all_cons_opts in consistencies:
|
||||
#all_cons_opts[0] is the option where func is set
|
||||
ret = all_cons_opts[0]._launch_consistency(func, option,
|
||||
value,
|
||||
context, index,
|
||||
all_cons_opts)
|
||||
if ret is False:
|
||||
return False
|
||||
return True
|
||||
|
@ -1149,6 +1269,7 @@ class OptionDescription(BaseOption):
|
|||
"""
|
||||
if descr is None:
|
||||
self._cache_paths = None
|
||||
self._cache_consistencies = None
|
||||
self.impl_build_cache(force_no_consistencies=True)
|
||||
descr = self
|
||||
self._group_type = getattr(groups, self._state_group_type)
|
||||
|
@ -1252,3 +1373,34 @@ def validate_requires_arg(requires, name):
|
|||
require[3], require[4], require[5]))
|
||||
ret.append(tuple(ret_action))
|
||||
return frozenset(config_action.keys()), tuple(ret)
|
||||
|
||||
|
||||
def validate_callback(callback, callback_params, type_):
|
||||
if type(callback) != FunctionType:
|
||||
raise ValueError(_('{0} should be a function').format(type_))
|
||||
if callback_params is not None:
|
||||
if not isinstance(callback_params, dict):
|
||||
raise ValueError(_('{0}_params should be a dict').format(type_))
|
||||
for key, callbacks in callback_params.items():
|
||||
if key != '' and len(callbacks) != 1:
|
||||
raise ValueError(_('{0}_params with key {1} should not have '
|
||||
'length different to 1').format(type_,
|
||||
key))
|
||||
if not isinstance(callbacks, tuple):
|
||||
raise ValueError(_('{0}_params should be tuple for key "{1}"'
|
||||
).format(type_, key))
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
option, force_permissive = callbk
|
||||
if type_ == 'validator' and not force_permissive:
|
||||
raise ValueError(_('validator not support tuple'))
|
||||
if not isinstance(option, Option) and not \
|
||||
isinstance(option, SymLinkOption):
|
||||
raise ValueError(_('{0}_params should have an option '
|
||||
'not a {0} for first argument'
|
||||
).format(type_, type(option)))
|
||||
if force_permissive not in [True, False]:
|
||||
raise ValueError(_('{0}_params should have a boolean'
|
||||
' not a {0} for second argument'
|
||||
).format(type_, type(
|
||||
force_permissive)))
|
||||
|
|
|
@ -105,7 +105,7 @@ rw_remove = set(['permissive', 'everything_frozen', 'mandatory'])
|
|||
|
||||
|
||||
# ____________________________________________________________
|
||||
class _NameSpace:
|
||||
class _NameSpace(object):
|
||||
"""convenient class that emulates a module
|
||||
and builds constants (that is, unique names)
|
||||
when attribute is added, we cannot delete it
|
||||
|
@ -385,13 +385,17 @@ class Settings(object):
|
|||
#____________________________________________________________
|
||||
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
|
||||
value=None, force_permissive=False,
|
||||
force_properties=None):
|
||||
force_properties=None, force_permissives=None):
|
||||
"""
|
||||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param force_properties: set() with properties that is force to add
|
||||
in global properties
|
||||
:param force_permissives: set() with permissives that is force to add
|
||||
in global permissives
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
@ -408,6 +412,8 @@ class Settings(object):
|
|||
self_properties = copy(self._getproperties())
|
||||
if force_permissive is True or 'permissive' in self_properties:
|
||||
properties -= self._p_.getpermissive()
|
||||
if force_permissives is not None:
|
||||
properties -= force_permissives
|
||||
|
||||
# global properties
|
||||
if force_properties is not None:
|
||||
|
@ -585,3 +591,23 @@ class Settings(object):
|
|||
:returns: path
|
||||
"""
|
||||
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
|
||||
def get_modified_properties(self):
|
||||
return self._p_.get_modified_properties()
|
||||
|
||||
def get_modified_permissives(self):
|
||||
return self._p_.get_modified_permissives()
|
||||
|
||||
def __getstate__(self):
|
||||
return {'_p_': self._p_, '_owner': str(self._owner)}
|
||||
|
||||
def _impl_setstate(self, storage):
|
||||
self._p_._storage = storage
|
||||
|
||||
def __setstate__(self, states):
|
||||
self._p_ = states['_p_']
|
||||
try:
|
||||
self._owner = getattr(owners, states['_owner'])
|
||||
except AttributeError:
|
||||
owners.addowner(states['_owner'])
|
||||
self._owner = getattr(owners, states['_owner'])
|
||||
|
|
|
@ -68,7 +68,7 @@ class StorageType(object):
|
|||
storage_type = StorageType()
|
||||
|
||||
|
||||
def set_storage(name, **args):
|
||||
def set_storage(name, **kwargs):
|
||||
"""Change storage's configuration
|
||||
|
||||
:params name: is the storage name. If storage is already set, cannot
|
||||
|
@ -77,16 +77,31 @@ def set_storage(name, **args):
|
|||
Other attributes are differents according to the selected storage's name
|
||||
"""
|
||||
storage_type.set(name)
|
||||
settings = storage_type.get().Setting()
|
||||
for option, value in args.items():
|
||||
setting = storage_type.get().setting
|
||||
for option, value in kwargs.items():
|
||||
try:
|
||||
getattr(settings, option)
|
||||
setattr(settings, option, value)
|
||||
getattr(setting, option)
|
||||
setattr(setting, option, value)
|
||||
except AttributeError:
|
||||
raise ValueError(_('option {0} not already exists in storage {1}'
|
||||
'').format(option, name))
|
||||
|
||||
|
||||
def _impl_getstate_setting():
|
||||
setting = storage_type.get().setting
|
||||
state = {'name': storage_type.storage_type}
|
||||
for var in dir(setting):
|
||||
if not var.startswith('_'):
|
||||
state[var] = getattr(setting, var)
|
||||
return state
|
||||
|
||||
|
||||
def get_storage(session_id, persistent, test):
|
||||
"""all used when __setstate__ a Config
|
||||
"""
|
||||
return storage_type.get().Storage(session_id, persistent, test)
|
||||
|
||||
|
||||
def get_storages(context, session_id, persistent):
|
||||
def gen_id(config):
|
||||
return str(id(config)) + str(time())
|
||||
|
|
|
@ -26,6 +26,6 @@ use it. But if something goes wrong, you will lost your modifications.
|
|||
"""
|
||||
from .value import Values
|
||||
from .setting import Settings
|
||||
from .storage import Setting, Storage, list_sessions, delete_session
|
||||
from .storage import setting, Storage, list_sessions, delete_session
|
||||
|
||||
__all__ = (Setting, Values, Settings, Storage, list_sessions, delete_session)
|
||||
__all__ = (setting, Values, Settings, Storage, list_sessions, delete_session)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# ____________________________________________________________
|
||||
from ..cache import Cache
|
||||
from ..util import Cache
|
||||
|
||||
|
||||
class Settings(Cache):
|
||||
|
@ -50,12 +50,21 @@ class Settings(Cache):
|
|||
except KeyError:
|
||||
pass
|
||||
|
||||
def get_properties(self, context):
|
||||
return self._properties
|
||||
|
||||
# permissive
|
||||
def setpermissive(self, path, permissive):
|
||||
self._permissives[path] = frozenset(permissive)
|
||||
|
||||
def getpermissive(self, path=None):
|
||||
return self._permissives.get(path, frozenset())
|
||||
|
||||
def get_modified_properties(self):
|
||||
"""return all modified settings in a dictionary
|
||||
example: {'path1': set(['prop1', 'prop2'])}
|
||||
"""
|
||||
return self._properties
|
||||
|
||||
def get_modified_permissives(self):
|
||||
"""return all modified permissives in a dictionary
|
||||
example: {'path1': set(['perm1', 'perm2'])}
|
||||
"""
|
||||
return self._permissives
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
# ____________________________________________________________
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.error import ConfigError
|
||||
from ..util import SerializeObject
|
||||
|
||||
|
||||
class Setting(object):
|
||||
class Setting(SerializeObject):
|
||||
"""Dictionary storage has no particular setting.
|
||||
"""
|
||||
pass
|
||||
|
@ -39,15 +40,18 @@ def delete_session(session_id):
|
|||
|
||||
|
||||
class Storage(object):
|
||||
__slots__ = ('session_id', 'values', 'settings')
|
||||
__slots__ = ('session_id', 'persistent')
|
||||
storage = 'dictionary'
|
||||
#if object could be serializable
|
||||
serializable = True
|
||||
|
||||
def __init__(self, session_id, persistent):
|
||||
if session_id in _list_sessions:
|
||||
def __init__(self, session_id, persistent, test=False):
|
||||
if not test and session_id in _list_sessions:
|
||||
raise ValueError(_('session already used'))
|
||||
if persistent:
|
||||
raise ValueError(_('a dictionary cannot be persistent'))
|
||||
self.session_id = session_id
|
||||
self.persistent = persistent
|
||||
_list_sessions.append(self.session_id)
|
||||
|
||||
def __del__(self):
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#
|
||||
# ____________________________________________________________
|
||||
|
||||
from ..cache import Cache
|
||||
from ..util import Cache
|
||||
|
||||
|
||||
class Values(Cache):
|
||||
|
|
|
@ -24,6 +24,6 @@ You should not configure differents Configs with same session_id.
|
|||
"""
|
||||
from .value import Values
|
||||
from .setting import Settings
|
||||
from .storage import Setting, Storage, list_sessions, delete_session
|
||||
from .storage import setting, Storage, list_sessions, delete_session
|
||||
|
||||
__all__ = (Setting, Values, Settings, Storage, list_sessions, delete_session)
|
||||
__all__ = (setting, Values, Settings, Storage, list_sessions, delete_session)
|
||||
|
|
|
@ -30,22 +30,22 @@ class Settings(Sqlite3DB):
|
|||
permissives_table += 'primary key, permissives text)'
|
||||
# should init cache too
|
||||
super(Settings, self).__init__(storage)
|
||||
self.storage.execute(settings_table, commit=False)
|
||||
self.storage.execute(permissives_table)
|
||||
self._storage.execute(settings_table, commit=False)
|
||||
self._storage.execute(permissives_table)
|
||||
|
||||
# propertives
|
||||
def setproperties(self, path, properties):
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("DELETE FROM property WHERE path = ?", (path,),
|
||||
False)
|
||||
self.storage.execute("INSERT INTO property(path, properties) VALUES "
|
||||
"(?, ?)", (path,
|
||||
self._sqlite_encode(properties)))
|
||||
self._storage.execute("DELETE FROM property WHERE path = ?", (path,),
|
||||
False)
|
||||
self._storage.execute("INSERT INTO property(path, properties) VALUES "
|
||||
"(?, ?)", (path,
|
||||
self._sqlite_encode(properties)))
|
||||
|
||||
def getproperties(self, path, default_properties):
|
||||
path = self._sqlite_encode_path(path)
|
||||
value = self.storage.select("SELECT properties FROM property WHERE "
|
||||
"path = ?", (path,))
|
||||
value = self._storage.select("SELECT properties FROM property WHERE "
|
||||
"path = ?", (path,))
|
||||
if value is None:
|
||||
return set(default_properties)
|
||||
else:
|
||||
|
@ -53,42 +53,53 @@ class Settings(Sqlite3DB):
|
|||
|
||||
def hasproperties(self, path):
|
||||
path = self._sqlite_encode_path(path)
|
||||
return self.storage.select("SELECT properties FROM property WHERE "
|
||||
"path = ?", (path,)) is not None
|
||||
return self._storage.select("SELECT properties FROM property WHERE "
|
||||
"path = ?", (path,)) is not None
|
||||
|
||||
def reset_all_propertives(self):
|
||||
self.storage.execute("DELETE FROM property")
|
||||
self._storage.execute("DELETE FROM property")
|
||||
|
||||
def reset_properties(self, path):
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("DELETE FROM property WHERE path = ?", (path,))
|
||||
|
||||
def get_properties(self, context):
|
||||
"""return all properties in a dictionary
|
||||
"""
|
||||
ret = {}
|
||||
for path, properties in self.storage.select("SELECT * FROM property",
|
||||
only_one=False):
|
||||
path = self._sqlite_decode_path(path)
|
||||
properties = self._sqlite_decode(properties)
|
||||
ret[path] = properties
|
||||
return ret
|
||||
self._storage.execute("DELETE FROM property WHERE path = ?", (path,))
|
||||
|
||||
# permissive
|
||||
def setpermissive(self, path, permissive):
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("DELETE FROM permissive WHERE path = ?", (path,),
|
||||
False)
|
||||
self.storage.execute("INSERT INTO permissive(path, permissives) "
|
||||
"VALUES (?, ?)", (path,
|
||||
self._sqlite_encode(permissive)
|
||||
))
|
||||
self._storage.execute("DELETE FROM permissive WHERE path = ?", (path,),
|
||||
False)
|
||||
self._storage.execute("INSERT INTO permissive(path, permissives) "
|
||||
"VALUES (?, ?)", (path,
|
||||
self._sqlite_encode(permissive)
|
||||
))
|
||||
|
||||
def getpermissive(self, path='_none'):
|
||||
permissives = self.storage.select("SELECT permissives FROM "
|
||||
"permissive WHERE path = ?",
|
||||
(path,))
|
||||
permissives = self._storage.select("SELECT permissives FROM "
|
||||
"permissive WHERE path = ?",
|
||||
(path,))
|
||||
if permissives is None:
|
||||
return frozenset()
|
||||
else:
|
||||
return frozenset(self._sqlite_decode(permissives[0]))
|
||||
|
||||
def get_modified_properties(self):
|
||||
"""return all modified settings in a dictionary
|
||||
example: {'path1': set(['prop1', 'prop2'])}
|
||||
"""
|
||||
ret = {}
|
||||
for path, properties in self._storage.select("SELECT * FROM property",
|
||||
only_one=False):
|
||||
path = self._sqlite_decode_path(path)
|
||||
ret[path] = self._sqlite_decode(properties)
|
||||
return ret
|
||||
|
||||
def get_modified_permissives(self):
|
||||
"""return all modified permissives in a dictionary
|
||||
example: {'path1': set(['perm1', 'perm2'])}
|
||||
"""
|
||||
ret = {}
|
||||
for path, permissives in self._storage.select("SELECT * FROM permissive",
|
||||
only_one=False):
|
||||
path = self._sqlite_decode_path(path)
|
||||
ret[path] = self._sqlite_decode(permissives)
|
||||
return ret
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# ____________________________________________________________
|
||||
from cPickle import loads, dumps
|
||||
from ..cache import Cache
|
||||
try:
|
||||
from cPickle import loads, dumps
|
||||
except ImportError:
|
||||
from pickle import loads, dumps
|
||||
from ..util import Cache
|
||||
|
||||
|
||||
class Sqlite3DB(Cache):
|
||||
|
|
|
@ -22,9 +22,10 @@ from os import unlink
|
|||
from os.path import basename, splitext, join
|
||||
import sqlite3
|
||||
from glob import glob
|
||||
from ..util import SerializeObject
|
||||
|
||||
|
||||
class Setting(object):
|
||||
class Setting(SerializeObject):
|
||||
""":param extension: database file extension (by default: db)
|
||||
:param dir_database: root database directory (by default: /tmp)
|
||||
"""
|
||||
|
@ -52,13 +53,17 @@ def delete_session(session_id):
|
|||
|
||||
|
||||
class Storage(object):
|
||||
__slots__ = ('_conn', '_cursor', 'persistent', '_session_id')
|
||||
__slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'serializable')
|
||||
storage = 'sqlite3'
|
||||
|
||||
def __init__(self, session_id, persistent):
|
||||
def __init__(self, session_id, persistent, test=False):
|
||||
self.persistent = persistent
|
||||
self._session_id = session_id
|
||||
self._conn = sqlite3.connect(_gen_filename(self._session_id))
|
||||
if self.persistent:
|
||||
self.serializable = True
|
||||
else:
|
||||
self.serializable = False
|
||||
self.session_id = session_id
|
||||
self._conn = sqlite3.connect(_gen_filename(self.session_id))
|
||||
self._conn.text_factory = str
|
||||
self._cursor = self._conn.cursor()
|
||||
|
||||
|
@ -80,4 +85,4 @@ class Storage(object):
|
|||
self._cursor.close()
|
||||
self._conn.close()
|
||||
if not self.persistent:
|
||||
delete_session(self._session_id)
|
||||
delete_session(self.session_id)
|
||||
|
|
|
@ -32,11 +32,11 @@ class Values(Sqlite3DB):
|
|||
super(Values, self).__init__(storage)
|
||||
values_table = 'CREATE TABLE IF NOT EXISTS value(path text primary '
|
||||
values_table += 'key, value text, owner text)'
|
||||
self.storage.execute(values_table, commit=False)
|
||||
self._storage.execute(values_table, commit=False)
|
||||
informations_table = 'CREATE TABLE IF NOT EXISTS information(key text primary '
|
||||
informations_table += 'key, value text)'
|
||||
self.storage.execute(informations_table)
|
||||
for owner in self.storage.select("SELECT DISTINCT owner FROM value", tuple(), False):
|
||||
self._storage.execute(informations_table)
|
||||
for owner in self._storage.select("SELECT DISTINCT owner FROM value", tuple(), False):
|
||||
try:
|
||||
getattr(owners, owner[0])
|
||||
except AttributeError:
|
||||
|
@ -44,7 +44,7 @@ class Values(Sqlite3DB):
|
|||
|
||||
# sqlite
|
||||
def _sqlite_select(self, path):
|
||||
return self.storage.select("SELECT value FROM value WHERE path = ?",
|
||||
return self._storage.select("SELECT value FROM value WHERE path = ?",
|
||||
(path,))
|
||||
|
||||
# value
|
||||
|
@ -54,7 +54,7 @@ class Values(Sqlite3DB):
|
|||
"""
|
||||
self.resetvalue(path)
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("INSERT INTO value(path, value, owner) VALUES "
|
||||
self._storage.execute("INSERT INTO value(path, value, owner) VALUES "
|
||||
"(?, ?, ?)", (path, self._sqlite_encode(value),
|
||||
str(owner)))
|
||||
|
||||
|
@ -76,14 +76,14 @@ class Values(Sqlite3DB):
|
|||
"""remove value means delete value in storage
|
||||
"""
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("DELETE FROM value WHERE path = ?", (path,))
|
||||
self._storage.execute("DELETE FROM value WHERE path = ?", (path,))
|
||||
|
||||
def get_modified_values(self):
|
||||
"""return all values in a dictionary
|
||||
example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
|
||||
"""
|
||||
ret = {}
|
||||
for path, value, owner in self.storage.select("SELECT * FROM value",
|
||||
for path, value, owner in self._storage.select("SELECT * FROM value",
|
||||
only_one=False):
|
||||
path = self._sqlite_decode_path(path)
|
||||
owner = getattr(owners, owner)
|
||||
|
@ -97,7 +97,7 @@ class Values(Sqlite3DB):
|
|||
"""change owner for an option
|
||||
"""
|
||||
path = self._sqlite_encode_path(path)
|
||||
self.storage.execute("UPDATE value SET owner = ? WHERE path = ?",
|
||||
self._storage.execute("UPDATE value SET owner = ? WHERE path = ?",
|
||||
(str(owner), path))
|
||||
|
||||
def getowner(self, path, default):
|
||||
|
@ -105,7 +105,7 @@ class Values(Sqlite3DB):
|
|||
return: owner object
|
||||
"""
|
||||
path = self._sqlite_encode_path(path)
|
||||
owner = self.storage.select("SELECT owner FROM value WHERE path = ?",
|
||||
owner = self._storage.select("SELECT owner FROM value WHERE path = ?",
|
||||
(path,))
|
||||
if owner is None:
|
||||
return default
|
||||
|
@ -125,9 +125,9 @@ class Values(Sqlite3DB):
|
|||
:param key: information's key (ex: "help", "doc"
|
||||
:param value: information's value (ex: "the help string")
|
||||
"""
|
||||
self.storage.execute("DELETE FROM information WHERE key = ?", (key,),
|
||||
self._storage.execute("DELETE FROM information WHERE key = ?", (key,),
|
||||
False)
|
||||
self.storage.execute("INSERT INTO information(key, value) VALUES "
|
||||
self._storage.execute("INSERT INTO information(key, value) VALUES "
|
||||
"(?, ?)", (key, self._sqlite_encode(value)))
|
||||
|
||||
def get_information(self, key):
|
||||
|
@ -135,7 +135,7 @@ class Values(Sqlite3DB):
|
|||
|
||||
:param key: the item string (ex: "help")
|
||||
"""
|
||||
value = self.storage.select("SELECT value FROM information WHERE key = ?",
|
||||
value = self._storage.select("SELECT value FROM information WHERE key = ?",
|
||||
(key,))
|
||||
if value is None:
|
||||
raise ValueError("not found")
|
||||
|
|
|
@ -17,15 +17,65 @@
|
|||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# ____________________________________________________________
|
||||
from tiramisu.setting import owners
|
||||
|
||||
|
||||
class SerializeObject(object):
|
||||
def __getstate__(self):
|
||||
ret = {}
|
||||
for key in dir(self):
|
||||
if not key.startswith('__'):
|
||||
ret[key] = getattr(self, key)
|
||||
return ret
|
||||
|
||||
|
||||
class Cache(object):
|
||||
__slots__ = ('_cache', 'storage')
|
||||
__slots__ = ('_cache', '_storage')
|
||||
key_is_path = False
|
||||
|
||||
def __init__(self, storage):
|
||||
self._cache = {}
|
||||
self.storage = storage
|
||||
self._storage = storage
|
||||
|
||||
def __getstate__(self):
|
||||
slots = set()
|
||||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['__weakref__', '_storage'])
|
||||
states = {}
|
||||
for slot in slots:
|
||||
try:
|
||||
value = getattr(self, slot)
|
||||
#value has owners object, need 'str()' it
|
||||
if slot == '_values':
|
||||
_value = {}
|
||||
for key, values in value.items():
|
||||
vals = list(values)
|
||||
vals[0] = str(vals[0])
|
||||
_value[key] = tuple(vals)
|
||||
states[slot] = _value
|
||||
else:
|
||||
states[slot] = value
|
||||
except AttributeError:
|
||||
pass
|
||||
return states
|
||||
|
||||
def __setstate__(self, states):
|
||||
for key, value in states.items():
|
||||
#value has owners object, need to reconstruct it
|
||||
if key == '_values':
|
||||
_value = {}
|
||||
for key_, values_ in value.items():
|
||||
vals = list(values_)
|
||||
try:
|
||||
vals[0] = getattr(owners, vals[0])
|
||||
except AttributeError:
|
||||
owners.addowner(vals[0])
|
||||
vals[0] = getattr(owners, vals[0])
|
||||
_value[key_] = tuple(vals)
|
||||
value = _value
|
||||
setattr(self, key, value)
|
||||
|
||||
def setcache(self, path, val, time):
|
||||
self._cache[path] = (val, time)
|
|
@ -106,7 +106,8 @@ class Values(object):
|
|||
path = self._get_opt_path(opt)
|
||||
if self._p_.hasvalue(path):
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
opt.impl_validate(opt.impl_getdefault(), self.context(),
|
||||
opt.impl_validate(opt.impl_getdefault(),
|
||||
self.context(),
|
||||
'validator' in setting)
|
||||
self.context().cfgimpl_reset_cache()
|
||||
if (opt.impl_is_multi() and
|
||||
|
@ -124,7 +125,7 @@ class Values(object):
|
|||
return True
|
||||
return False
|
||||
|
||||
def _getcallback_value(self, opt, index=None):
|
||||
def _getcallback_value(self, opt, index=None, max_len=None):
|
||||
"""
|
||||
retrieves a value for the options that have a callback
|
||||
|
||||
|
@ -139,7 +140,7 @@ class Values(object):
|
|||
return carry_out_calculation(opt._name, config=self.context(),
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
index=index)
|
||||
index=index, max_len=max_len)
|
||||
|
||||
def __getitem__(self, opt):
|
||||
"enables us to use the pythonic dictionary-like access to values"
|
||||
|
@ -177,11 +178,20 @@ class Values(object):
|
|||
# options with callbacks
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
is_frozen = 'frozen' in setting[opt]
|
||||
# For calculating properties, we need value (ie for mandatory value).
|
||||
# If value is calculating with a PropertiesOptionError's option
|
||||
# _getcallback_value raise a ConfigError.
|
||||
# We can not raise ConfigError if this option should raise
|
||||
# PropertiesOptionError too. So we get config_error and raise
|
||||
# ConfigError if properties did not raise.
|
||||
config_error = None
|
||||
force_permissives = None
|
||||
# if value is callback and is not set
|
||||
# or frozen with force_default_on_freeze
|
||||
if opt.impl_has_callback() and (
|
||||
self._is_default_owner(path) or
|
||||
(is_frozen and 'force_default_on_freeze' in setting[opt])):
|
||||
lenmaster = None
|
||||
no_value_slave = False
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.slave):
|
||||
|
@ -193,15 +203,25 @@ class Values(object):
|
|||
no_value_slave = True
|
||||
|
||||
if not no_value_slave:
|
||||
value = self._getcallback_value(opt)
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.slave):
|
||||
if not isinstance(value, list):
|
||||
value = [value for i in range(lenmaster)]
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
# suppress value if already set
|
||||
self.reset(opt, path)
|
||||
try:
|
||||
value = self._getcallback_value(opt, max_len=lenmaster)
|
||||
except ConfigError as err:
|
||||
# cannot assign config_err directly in python 3.3
|
||||
config_error = err
|
||||
value = None
|
||||
# should not raise PropertiesOptionError if option is
|
||||
# mandatory
|
||||
force_permissives = set(['mandatory'])
|
||||
else:
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.slave):
|
||||
if not isinstance(value, list):
|
||||
value = [value for i in range(lenmaster)]
|
||||
if config_error is None:
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
# suppress value if already set
|
||||
self.reset(opt, path)
|
||||
# frozen and force default
|
||||
elif is_frozen and 'force_default_on_freeze' in setting[opt]:
|
||||
value = self._getdefault(opt)
|
||||
|
@ -209,15 +229,18 @@ class Values(object):
|
|||
value = Multi(value, self.context, opt, path, validate)
|
||||
else:
|
||||
value = self._getvalue(opt, path, validate)
|
||||
if validate:
|
||||
if config_error is None and validate:
|
||||
opt.impl_validate(value, self.context(), 'validator' in setting)
|
||||
if self._is_default_owner(path) and \
|
||||
if config_error is None and self._is_default_owner(path) and \
|
||||
'force_store_value' in setting[opt]:
|
||||
self.setitem(opt, value, path, is_write=False)
|
||||
if validate_properties:
|
||||
setting.validate_properties(opt, False, False, value=value, path=path,
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties)
|
||||
force_properties=force_properties,
|
||||
force_permissives=force_permissives)
|
||||
if config_error is not None:
|
||||
raise config_error
|
||||
return value
|
||||
|
||||
def __setitem__(self, opt, value):
|
||||
|
@ -231,7 +254,7 @@ class Values(object):
|
|||
opt.impl_validate(value, self.context(),
|
||||
'validator' in self.context().cfgimpl_get_settings())
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
value = Multi(value, self.context, opt, path)
|
||||
value = Multi(value, self.context, opt, path, setitem=True)
|
||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||
is_write=is_write)
|
||||
|
||||
|
@ -339,6 +362,15 @@ class Values(object):
|
|||
raise ValueError(_("information's item"
|
||||
" not found: {0}").format(key))
|
||||
|
||||
def __getstate__(self):
|
||||
return {'_p_': self._p_}
|
||||
|
||||
def _impl_setstate(self, storage):
|
||||
self._p_._storage = storage
|
||||
|
||||
def __setstate__(self, states):
|
||||
self._p_ = states['_p_']
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
# multi types
|
||||
|
@ -349,11 +381,13 @@ class Multi(list):
|
|||
that support item notation for the values of multi options"""
|
||||
__slots__ = ('opt', 'path', 'context')
|
||||
|
||||
def __init__(self, value, context, opt, path, validate=True):
|
||||
def __init__(self, value, context, opt, path, validate=True,
|
||||
setitem=False):
|
||||
"""
|
||||
:param value: the Multi wraps a list value
|
||||
:param context: the home config that has the values
|
||||
:param opt: the option object that have this Multi value
|
||||
:param setitem: only if set a value
|
||||
"""
|
||||
self.opt = opt
|
||||
self.path = path
|
||||
|
@ -363,27 +397,35 @@ class Multi(list):
|
|||
if not isinstance(value, list):
|
||||
value = [value]
|
||||
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
||||
value = self._valid_slave(value)
|
||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
||||
value = self._valid_slave(value, setitem)
|
||||
elif validate and self.opt.impl_get_multitype() == multitypes.master:
|
||||
self._valid_master(value)
|
||||
super(Multi, self).__init__(value)
|
||||
|
||||
def _valid_slave(self, value):
|
||||
def _valid_slave(self, value, setitem):
|
||||
#if slave, had values until master's one
|
||||
values = self.context().cfgimpl_get_values()
|
||||
masterp = self.context().cfgimpl_get_description().impl_get_path_by_opt(
|
||||
self.opt.impl_get_master_slaves())
|
||||
mastervalue = getattr(self.context(), masterp)
|
||||
masterlen = len(mastervalue)
|
||||
valuelen = len(value)
|
||||
is_default_owner = not values._is_default_owner(self.path) or setitem
|
||||
if valuelen > masterlen or (valuelen < masterlen and
|
||||
not self.context().cfgimpl_get_values(
|
||||
)._is_default_owner(self.path)):
|
||||
is_default_owner):
|
||||
raise SlaveError(_("invalid len for the slave: {0}"
|
||||
" which has {1} as master").format(
|
||||
self.opt._name, masterp))
|
||||
elif valuelen < masterlen:
|
||||
for num in range(0, masterlen - valuelen):
|
||||
value.append(self.opt.impl_getdefault_multi())
|
||||
if self.opt.impl_has_callback():
|
||||
# if callback add a value, but this value will not change
|
||||
# anymore automaticly (because this value has owner)
|
||||
index = value.__len__()
|
||||
value.append(values._getcallback_value(self.opt,
|
||||
index=index))
|
||||
else:
|
||||
value.append(self.opt.impl_getdefault_multi())
|
||||
#else: same len so do nothing
|
||||
return value
|
||||
|
||||
|
@ -401,13 +443,22 @@ class Multi(list):
|
|||
self.opt._name, slave._name))
|
||||
elif len(value_slave) < masterlen:
|
||||
for num in range(0, masterlen - len(value_slave)):
|
||||
value_slave.append(slave.impl_getdefault_multi(),
|
||||
force=True)
|
||||
if slave.impl_has_callback():
|
||||
# if callback add a value, but this value will not
|
||||
# change anymore automaticly (because this value
|
||||
# has owner)
|
||||
index = value_slave.__len__()
|
||||
value_slave.append(
|
||||
values._getcallback_value(slave, index=index),
|
||||
force=True)
|
||||
else:
|
||||
value_slave.append(slave.impl_getdefault_multi(),
|
||||
force=True)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self._validate(value)
|
||||
def __setitem__(self, index, value):
|
||||
self._validate(value, index)
|
||||
#assume not checking mandatory property
|
||||
super(Multi, self).__setitem__(key, value)
|
||||
super(Multi, self).__setitem__(index, value)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def append(self, value, force=False):
|
||||
|
@ -425,15 +476,17 @@ class Multi(list):
|
|||
#Force None il return a list
|
||||
if isinstance(value, list):
|
||||
value = None
|
||||
self._validate(value)
|
||||
index = self.__len__()
|
||||
self._validate(value, index)
|
||||
super(Multi, self).append(value)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self,
|
||||
validate_properties=not force)
|
||||
if not force and self.opt.impl_get_multitype() == multitypes.master:
|
||||
for slave in self.opt.impl_get_master_slaves():
|
||||
path = values._get_opt_path(slave)
|
||||
if not values._is_default_owner(path):
|
||||
if slave.impl_has_callback():
|
||||
index = self.__len__() - 1
|
||||
dvalue = values._getcallback_value(slave, index=index)
|
||||
else:
|
||||
dvalue = slave.impl_getdefault_multi()
|
||||
|
@ -485,22 +538,26 @@ class Multi(list):
|
|||
super(Multi, self).extend(iterable)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def _validate(self, value):
|
||||
def _validate(self, value, force_index):
|
||||
if value is not None:
|
||||
try:
|
||||
self.opt._validate(value)
|
||||
self.opt.impl_validate(value, context=self.context(),
|
||||
force_index=force_index)
|
||||
except ValueError as err:
|
||||
raise ValueError(_("invalid value {0} "
|
||||
"for option {1}: {2}"
|
||||
"").format(str(value),
|
||||
self.opt._name, err))
|
||||
|
||||
def pop(self, key, force=False):
|
||||
def pop(self, index, force=False):
|
||||
"""the list value can be updated (poped)
|
||||
only if the option is a master
|
||||
|
||||
:param key: index of the element to pop
|
||||
:return: the requested element
|
||||
:param index: remove item a index
|
||||
:type index: int
|
||||
:param force: force pop item (withoud check master/slave)
|
||||
:type force: boolean
|
||||
:returns: item at index
|
||||
"""
|
||||
if not force:
|
||||
if self.opt.impl_get_multitype() == multitypes.slave:
|
||||
|
@ -513,8 +570,8 @@ class Multi(list):
|
|||
#get multi without valid properties
|
||||
values.getitem(slave,
|
||||
validate_properties=False
|
||||
).pop(key, force=True)
|
||||
).pop(index, force=True)
|
||||
#set value without valid properties
|
||||
ret = super(Multi, self).pop(key)
|
||||
ret = super(Multi, self).pop(index)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
||||
return ret
|
||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-08-31 09:52+CEST\n"
|
||||
"POT-Creation-Date: 2013-09-28 19:06+CEST\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -11,438 +11,526 @@ msgstr ""
|
|||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
|
||||
#: tiramisu/autolib.py:58
|
||||
msgid "no config specified but needed"
|
||||
msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||
|
||||
#: tiramisu/autolib.py:65
|
||||
#: tiramisu/autolib.py:144
|
||||
msgid ""
|
||||
"unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||
msgstr ""
|
||||
"impossible d'effectuer le calcul, l'option {0} a les propriétés : {1} pour : "
|
||||
"{2}"
|
||||
|
||||
#: tiramisu/autolib.py:74
|
||||
#: tiramisu/autolib.py:153
|
||||
msgid ""
|
||||
"unable to carry out a calculation, option value with multi types must have "
|
||||
"same length for: {0}"
|
||||
msgstr ""
|
||||
"impossible d'effectuer le calcul, valeur d'un option avec le type multi doit "
|
||||
"avoir la même longueur pour : {0}"
|
||||
"impossible d'effectuer le calcul, la valeur d'une option avec le type multi "
|
||||
"doit avoir la même longueur pour : {0}"
|
||||
|
||||
#: tiramisu/config.py:47
|
||||
#: tiramisu/config.py:51
|
||||
msgid "descr must be an optiondescription, not {0}"
|
||||
msgstr "descr doit être une optiondescription pas un {0}"
|
||||
|
||||
#: tiramisu/config.py:121
|
||||
#: tiramisu/config.py:126
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr "group_type inconnu: {0}"
|
||||
|
||||
#: tiramisu/config.py:157
|
||||
#: tiramisu/config.py:162
|
||||
msgid ""
|
||||
"no option description found for this config (may be metaconfig without meta)"
|
||||
msgstr ""
|
||||
"pas d'option description pour cette config (peut être une metaconfig sans "
|
||||
"meta)"
|
||||
"pas d'option description trouvé pour cette config (peut être une metaconfig "
|
||||
"sans meta)"
|
||||
|
||||
#: tiramisu/config.py:311
|
||||
#: tiramisu/config.py:188
|
||||
msgid "can't assign to an OptionDescription"
|
||||
msgstr "ne peut pas attribuer une valeur à une OptionDescription"
|
||||
|
||||
#: tiramisu/config.py:319
|
||||
msgid "unknown type_ type {0}for _find"
|
||||
msgstr "type_ type {0} pour _find inconnu"
|
||||
|
||||
#: tiramisu/config.py:350
|
||||
#: tiramisu/config.py:358
|
||||
msgid "no option found in config with these criteria"
|
||||
msgstr "aucune option trouvée dans la config avec ces critères"
|
||||
|
||||
#: tiramisu/config.py:400
|
||||
#: tiramisu/config.py:408
|
||||
msgid "make_dict can't filtering with value without option"
|
||||
msgstr "make_dict ne peut filtrer sur une valeur mais sans option"
|
||||
|
||||
#: tiramisu/config.py:421
|
||||
#: tiramisu/config.py:429
|
||||
msgid "unexpected path {0}, should start with {1}"
|
||||
msgstr "chemin imprévu {0}, devrait commencer par {1}"
|
||||
|
||||
#: tiramisu/config.py:481
|
||||
#: tiramisu/config.py:489
|
||||
msgid "opt in getowner must be an option not {0}"
|
||||
msgstr "opt dans getowner doit être une option pas {0}"
|
||||
|
||||
#: tiramisu/option.py:71
|
||||
msgid "{0} has no attribute impl_set_information"
|
||||
msgstr "{0} n'a pas d'attribut impl_set_information"
|
||||
|
||||
#: tiramisu/option.py:86
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||
|
||||
#: tiramisu/option.py:89
|
||||
msgid "{0} has no attribute impl_get_information"
|
||||
msgstr "{0} n'a pas d'attribut impl_get_information"
|
||||
|
||||
#: tiramisu/option.py:117
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seul"
|
||||
|
||||
#: tiramisu/option.py:159
|
||||
#: tiramisu/option.py:68
|
||||
msgid "invalid name: {0} for option"
|
||||
msgstr "nom invalide : {0} pour l'option"
|
||||
|
||||
#: tiramisu/option.py:169
|
||||
msgid "validator must be a function"
|
||||
msgstr "validator doit être une fonction"
|
||||
#: tiramisu/option.py:77
|
||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||
msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
|
||||
|
||||
#: tiramisu/option.py:176
|
||||
#: tiramisu/option.py:115
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
|
||||
|
||||
#: tiramisu/option.py:142 tiramisu/value.py:360
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||
|
||||
#: tiramisu/option.py:204
|
||||
msgid "cannot serialize Option, only in OptionDescription"
|
||||
msgstr "ne peut serialiser une Option, seulement via une OptionDescription"
|
||||
|
||||
#: tiramisu/option.py:307
|
||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||
msgstr ""
|
||||
"une default_multi est renseigné alors que multi est False dans l'option : {0}"
|
||||
"une default_multi est renseignée alors que multi est False dans l'option : "
|
||||
"{0}"
|
||||
|
||||
#: tiramisu/option.py:182
|
||||
#: tiramisu/option.py:313
|
||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||
msgstr "la valeur default_multi est invalide {0} pour l'option {1} : {2}"
|
||||
|
||||
#: tiramisu/option.py:187
|
||||
#: tiramisu/option.py:318
|
||||
msgid "default value not allowed if option: {0} is calculated"
|
||||
msgstr "la valeur par défaut n'est pas possible si l'option {0} est calculé"
|
||||
msgstr "la valeur par défaut n'est pas possible si l'option {0} est calculée"
|
||||
|
||||
#: tiramisu/option.py:190
|
||||
#: tiramisu/option.py:321
|
||||
msgid ""
|
||||
"params defined for a callback function but no callback defined yet for "
|
||||
"option {0}"
|
||||
msgstr ""
|
||||
"params définit pour une fonction callback mais par de callback défini encore "
|
||||
"pour l'option {0}"
|
||||
"params définis pour une fonction callback mais par de callback encore "
|
||||
"définis pour l'option {0}"
|
||||
|
||||
#: tiramisu/option.py:212 tiramisu/option.py:753
|
||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||
msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
|
||||
#: tiramisu/option.py:360
|
||||
msgid "option not in all_cons_opts"
|
||||
msgstr "option non présentante dans all_cons_opts"
|
||||
|
||||
#: tiramisu/option.py:285
|
||||
msgid "invalid value {0} for option {1} for object {2}"
|
||||
msgstr "valeur invalide {0} pour l'option {1} pour l'objet {2}"
|
||||
|
||||
#: tiramisu/option.py:293 tiramisu/value.py:468
|
||||
#: tiramisu/option.py:432 tiramisu/value.py:545
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
msgstr "valeur invalide {0} pour l'option {1} : {2}"
|
||||
|
||||
#: tiramisu/option.py:305
|
||||
msgid "invalid value {0} for option {1} which must be a list"
|
||||
msgstr "valeur invalide {0} pour l'option {1} qui doit être une liste"
|
||||
#: tiramisu/option.py:449
|
||||
msgid "which must be a list"
|
||||
msgstr "lequel doit être une liste"
|
||||
|
||||
#: tiramisu/option.py:374
|
||||
msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||
#: tiramisu/option.py:509
|
||||
msgid "consistency should be set with an option"
|
||||
msgstr "consistency doit être configuré avec une option"
|
||||
|
||||
#: tiramisu/option.py:511
|
||||
msgid "cannot add consistency with itself"
|
||||
msgstr "ne peut ajouter une consistency avec lui même"
|
||||
|
||||
#: tiramisu/option.py:513
|
||||
msgid "every options in consistency should be multi or none"
|
||||
msgstr ""
|
||||
"valeur invalide {0} pour l'option {1} doit être différent que l'option {2}"
|
||||
"toutes les options d'une consistency devrait être multi ou ne pas l'être"
|
||||
|
||||
#: tiramisu/option.py:396
|
||||
#: tiramisu/option.py:533
|
||||
msgid "same value for {0} and {1}"
|
||||
msgstr "même valeur pour {0} et {1}"
|
||||
|
||||
#: tiramisu/option.py:642
|
||||
msgid "values must be a tuple for {0}"
|
||||
msgstr "values doit être un tuple pour {0}"
|
||||
|
||||
#: tiramisu/option.py:399
|
||||
#: tiramisu/option.py:645
|
||||
msgid "open_values must be a boolean for {0}"
|
||||
msgstr "open_values doit être un booléen pour {0}"
|
||||
|
||||
#: tiramisu/option.py:420
|
||||
#: tiramisu/option.py:667
|
||||
msgid "value {0} is not permitted, only {1} is allowed"
|
||||
msgstr "valeur {0} n'est pas permit, seules {1} sont autorisées"
|
||||
msgstr "valeur {0} n'est pas permis, seules {1} sont autorisées"
|
||||
|
||||
#: tiramisu/option.py:432
|
||||
#: tiramisu/option.py:679
|
||||
msgid "value must be a boolean"
|
||||
msgstr "valeur doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:442
|
||||
#: tiramisu/option.py:689
|
||||
msgid "value must be an integer"
|
||||
msgstr "valeur doit être un numbre"
|
||||
msgstr "valeur doit être un nombre entier"
|
||||
|
||||
#: tiramisu/option.py:452
|
||||
#: tiramisu/option.py:699
|
||||
msgid "value must be a float"
|
||||
msgstr "valeur doit être un nombre flottant"
|
||||
|
||||
#: tiramisu/option.py:462
|
||||
#: tiramisu/option.py:709
|
||||
msgid "value must be a string, not {0}"
|
||||
msgstr "valeur doit être une chaîne, pas {0}"
|
||||
|
||||
#: tiramisu/option.py:480
|
||||
#: tiramisu/option.py:727
|
||||
msgid "value must be an unicode"
|
||||
msgstr "valeur doit être une valeur unicode"
|
||||
|
||||
#: tiramisu/option.py:490
|
||||
#: tiramisu/option.py:739
|
||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||
msgstr "symlinkoption mal formé doit être une option pour symlink {0}"
|
||||
msgstr "symlinkoption mal formé, doit être une option pour symlink {0}"
|
||||
|
||||
#: tiramisu/option.py:526
|
||||
#: tiramisu/option.py:788
|
||||
msgid "invalid IP {0}"
|
||||
msgstr "adresse IP invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:793
|
||||
msgid "IP mustn't not be in reserved class"
|
||||
msgstr "IP ne doit pas être d'une classe reservée"
|
||||
|
||||
#: tiramisu/option.py:528
|
||||
#: tiramisu/option.py:795
|
||||
msgid "IP must be in private class"
|
||||
msgstr "IP doit être dans la classe privée"
|
||||
|
||||
#: tiramisu/option.py:566
|
||||
#: tiramisu/option.py:833
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr "inconsistence dans la plage autorisée"
|
||||
|
||||
#: tiramisu/option.py:571
|
||||
#: tiramisu/option.py:838
|
||||
msgid "max value is empty"
|
||||
msgstr "valeur maximum est vide"
|
||||
msgstr "la valeur maximum est vide"
|
||||
|
||||
#: tiramisu/option.py:608
|
||||
msgid "network mustn't not be in reserved class"
|
||||
msgstr "réseau ne doit pas être dans la classe reservée"
|
||||
#: tiramisu/option.py:877
|
||||
msgid "invalid network address {0}"
|
||||
msgstr "adresse réseau invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:640
|
||||
#: tiramisu/option.py:882
|
||||
msgid "network shall not be in reserved class"
|
||||
msgstr "le réseau ne doit pas être dans la classe reservée"
|
||||
|
||||
#: tiramisu/option.py:894
|
||||
msgid "invalid netmask address {0}"
|
||||
msgstr "masque de sous-réseau invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:910
|
||||
msgid "invalid len for opts"
|
||||
msgstr "longueur invalide pour opts"
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3}), ce réseau est une IP"
|
||||
|
||||
#: tiramisu/option.py:645
|
||||
#: tiramisu/option.py:927
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||
msgstr "IP invalide {0} ({1}) avec masque {2} ({3}), cette IP est un réseau"
|
||||
|
||||
#: tiramisu/option.py:650
|
||||
#: tiramisu/option.py:932
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr "IP invalide {0} ({1}) avec masque {2} ({3})"
|
||||
|
||||
#: tiramisu/option.py:652
|
||||
#: tiramisu/option.py:934
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3})"
|
||||
|
||||
#: tiramisu/option.py:672
|
||||
#: tiramisu/option.py:948
|
||||
msgid "invalid broadcast address {0}"
|
||||
msgstr "adresse de broadcast invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
msgid "invalid len for vals"
|
||||
msgstr "longueur invalide pour vals"
|
||||
|
||||
#: tiramisu/option.py:957
|
||||
msgid ""
|
||||
"invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
|
||||
msgstr ""
|
||||
"Broadcast invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})"
|
||||
|
||||
#: tiramisu/option.py:979
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr "type_ inconnu {0} pour le nom d'hôte"
|
||||
|
||||
#: tiramisu/option.py:675
|
||||
#: tiramisu/option.py:982
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr "allow_ip doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:704
|
||||
#: tiramisu/option.py:1012
|
||||
msgid "invalid value for {0}, must have dot"
|
||||
msgstr "valeur invalide pour {0}, doit avoir un point"
|
||||
|
||||
#: tiramisu/option.py:707
|
||||
#: tiramisu/option.py:1015
|
||||
msgid "invalid domainname's length for {0} (max {1})"
|
||||
msgstr "longueur du nom de domaine invalide pour {0} (maximum {1})"
|
||||
|
||||
#: tiramisu/option.py:710
|
||||
#: tiramisu/option.py:1018
|
||||
msgid "invalid domainname's length for {0} (min 2)"
|
||||
msgstr "longueur du nom de domaine invalide pour {0} (minimum 2)"
|
||||
|
||||
#: tiramisu/option.py:714
|
||||
#: tiramisu/option.py:1022
|
||||
msgid "invalid domainname"
|
||||
msgstr "nom de domaine invalide"
|
||||
|
||||
#: tiramisu/option.py:731
|
||||
msgid "invalid name: {0} for optiondescription"
|
||||
msgstr "nom invalide : {0} pour l'optiondescription"
|
||||
|
||||
#: tiramisu/option.py:743
|
||||
#: tiramisu/option.py:1049
|
||||
msgid "duplicate option name: {0}"
|
||||
msgstr "nom de l'option dupliqué : {0}"
|
||||
|
||||
#: tiramisu/option.py:769
|
||||
#: tiramisu/option.py:1067
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgstr "Option {} inconnue pour l'OptionDescription{}"
|
||||
msgstr "Option {0} inconnue pour l'OptionDescription {1}"
|
||||
|
||||
#: tiramisu/option.py:820
|
||||
#: tiramisu/option.py:1118
|
||||
msgid "duplicate option: {0}"
|
||||
msgstr "option dupliquée : {0}"
|
||||
|
||||
#: tiramisu/option.py:850
|
||||
#: tiramisu/option.py:1148
|
||||
msgid "consistency with option {0} which is not in Config"
|
||||
msgstr "consistency avec l'option {0} qui n'est pas dans une Config"
|
||||
|
||||
#: tiramisu/option.py:1156
|
||||
msgid "no option for path {0}"
|
||||
msgstr "pas d'option pour le chemin {0}"
|
||||
|
||||
#: tiramisu/option.py:856
|
||||
#: tiramisu/option.py:1162
|
||||
msgid "no option {0} found"
|
||||
msgstr "pas d'option {0} trouvée"
|
||||
|
||||
#: tiramisu/option.py:866
|
||||
#: tiramisu/option.py:1172
|
||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||
msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})"
|
||||
|
||||
#: tiramisu/option.py:879
|
||||
#: tiramisu/option.py:1185
|
||||
msgid "master group {0} shall not have a subgroup"
|
||||
msgstr "groupe maître {0} ne doit pas avoir de sous-groupe"
|
||||
|
||||
#: tiramisu/option.py:882
|
||||
#: tiramisu/option.py:1188
|
||||
msgid "master group {0} shall not have a symlinkoption"
|
||||
msgstr "groupe maître {0} ne doit pas avoir de symlinkoption"
|
||||
|
||||
#: tiramisu/option.py:885
|
||||
#: tiramisu/option.py:1191
|
||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||
msgstr ""
|
||||
"option non autorisée {0} dans le groupe {1} : cette option n'est pas une "
|
||||
"multi"
|
||||
|
||||
#: tiramisu/option.py:896
|
||||
#: tiramisu/option.py:1202
|
||||
msgid "master group with wrong master name for {0}"
|
||||
msgstr "le groupe maître avec un nom de maître éroné pour {0}"
|
||||
msgstr "le groupe maître avec un nom de maître érroné pour {0}"
|
||||
|
||||
#: tiramisu/option.py:905
|
||||
#: tiramisu/option.py:1211
|
||||
msgid "no child has same nom has master group for: {0}"
|
||||
msgstr "pas d'enfant avec le nom du groupe maître pour {0} "
|
||||
|
||||
#: tiramisu/option.py:908
|
||||
#: tiramisu/option.py:1214
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr "group_type : {0} non autorisé"
|
||||
|
||||
#: tiramisu/option.py:946
|
||||
#: tiramisu/option.py:1306
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
|
||||
|
||||
#: tiramisu/option.py:962
|
||||
#: tiramisu/option.py:1323
|
||||
msgid ""
|
||||
"malformed requirements for option: {0} require must have option, expected "
|
||||
"and action keys"
|
||||
msgstr ""
|
||||
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
|
||||
"option, exptected et action"
|
||||
"option, expected et action"
|
||||
|
||||
#: tiramisu/option.py:967
|
||||
#: tiramisu/option.py:1328
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr "requirements malformé pour l'option : {0} inverse doit être un booléen"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} inverse doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:971
|
||||
#: tiramisu/option.py:1332
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr "requirements malformé pour l'option : {0} transitive doit être booléen"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} transitive doit être booléen"
|
||||
|
||||
#: tiramisu/option.py:975
|
||||
#: tiramisu/option.py:1336
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
"requirements malformé pour l'option : {0} same_action doit être un booléen"
|
||||
"requirements mal formés pour l'option : {0} same_action doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:979
|
||||
#: tiramisu/option.py:1340
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
msgstr "requirements malformé doit être une option dans l'option {0}"
|
||||
msgstr "requirements mal formés doit être une option dans l'option {0}"
|
||||
|
||||
#: tiramisu/option.py:982
|
||||
#: tiramisu/option.py:1343
|
||||
msgid "malformed requirements option {0} should not be a multi"
|
||||
msgstr "requirements malformé l'option {0} ne doit pas être une multi"
|
||||
msgstr "requirements mal formés l'option {0} ne doit pas être une multi"
|
||||
|
||||
#: tiramisu/option.py:988
|
||||
#: tiramisu/option.py:1349
|
||||
msgid ""
|
||||
"malformed requirements second argument must be valid for option {0}: {1}"
|
||||
msgstr ""
|
||||
"requirements malformé deuxième argument doit être valide pour l'option {0} : "
|
||||
"{1}"
|
||||
"requirements mal formés deuxième argument doit être valide pour l'option "
|
||||
"{0} : {1}"
|
||||
|
||||
#: tiramisu/option.py:993
|
||||
#: tiramisu/option.py:1354
|
||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||
msgstr "incohérence dans les types action pour l'option : {0} action {1}"
|
||||
|
||||
#: tiramisu/setting.py:47
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
msgstr "storage_type est déjà défini, impossible de le redéfinir"
|
||||
#: tiramisu/option.py:1379
|
||||
msgid "{0} should be a function"
|
||||
msgstr "{0} doit être une fonction"
|
||||
|
||||
#: tiramisu/setting.py:67
|
||||
#: tiramisu/option.py:1382
|
||||
msgid "{0}_params should be a dict"
|
||||
msgstr "{0}_params devrait être un dict"
|
||||
|
||||
#: tiramisu/option.py:1385
|
||||
msgid "{0}_params with key {1} should not have length different to 1"
|
||||
msgstr ""
|
||||
"{0}_params avec la clef {1} devrait ne pas avoir une longueur différent de 1"
|
||||
|
||||
#: tiramisu/option.py:1389
|
||||
msgid "{0}_params should be tuple for key \"{1}\""
|
||||
msgstr "{0}_params devrait être un tuple pour la clef \"{1}\""
|
||||
|
||||
#: tiramisu/option.py:1395
|
||||
msgid "validator not support tuple"
|
||||
msgstr "validator n'accepte pas de tuple"
|
||||
|
||||
#: tiramisu/option.py:1398
|
||||
msgid "{0}_params should have an option not a {0} for first argument"
|
||||
msgstr "{0}_params devrait avoir une option pas un {0} pour premier argument"
|
||||
|
||||
#: tiramisu/option.py:1402
|
||||
msgid "{0}_params should have a boolean not a {0} for second argument"
|
||||
msgstr "{0}_params devrait avoir un boolean pas un {0} pour second argument"
|
||||
|
||||
#: tiramisu/setting.py:111
|
||||
msgid "can't rebind {0}"
|
||||
msgstr "ne peut redéfinir ({0})"
|
||||
|
||||
#: tiramisu/setting.py:72
|
||||
#: tiramisu/setting.py:116
|
||||
msgid "can't unbind {0}"
|
||||
msgstr "ne peut supprimer ({0})"
|
||||
|
||||
#: tiramisu/setting.py:185
|
||||
#: tiramisu/setting.py:254
|
||||
msgid "cannot append {0} property for option {1}: this property is calculated"
|
||||
msgstr ""
|
||||
"ne peut ajouter la propriété {0} dans l'option {1}: cette propriété est "
|
||||
"calculée"
|
||||
|
||||
#: tiramisu/setting.py:215
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr "option {0} n'existe pas dans l'espace de stockage {1}"
|
||||
|
||||
#: tiramisu/setting.py:282
|
||||
#: tiramisu/setting.py:317
|
||||
msgid "opt and all_properties must not be set together in reset"
|
||||
msgstr "opt et all_properties ne doit pas être renseigné ensemble dans reset"
|
||||
|
||||
#: tiramisu/setting.py:297
|
||||
#: tiramisu/setting.py:332
|
||||
msgid "if opt is not None, path should not be None in _getproperties"
|
||||
msgstr ""
|
||||
"si opt n'est pas None, path devrait ne pas être à None dans _getproperties"
|
||||
|
||||
#: tiramisu/setting.py:391
|
||||
#: tiramisu/setting.py:435
|
||||
msgid "cannot change the value for option {0} this option is frozen"
|
||||
msgstr ""
|
||||
"ne peut modifié la valeur de l'option {0} cette option n'est pas modifiable"
|
||||
"ne peut modifier la valeur de l'option {0} cette option n'est pas modifiable"
|
||||
|
||||
#: tiramisu/setting.py:397
|
||||
#: tiramisu/setting.py:441
|
||||
msgid "trying to access to an option named: {0} with properties {1}"
|
||||
msgstr "tentative d'accès à une option nommée : {0} avec les propriétés {1}"
|
||||
|
||||
#: tiramisu/setting.py:415
|
||||
#: tiramisu/setting.py:459
|
||||
msgid "permissive must be a tuple"
|
||||
msgstr "permissive doit être un tuple"
|
||||
|
||||
#: tiramisu/setting.py:422 tiramisu/value.py:277
|
||||
#: tiramisu/setting.py:466 tiramisu/value.py:299
|
||||
msgid "invalid generic owner {0}"
|
||||
msgstr "invalide owner générique {0}"
|
||||
|
||||
#: tiramisu/setting.py:503
|
||||
#: tiramisu/setting.py:553
|
||||
msgid ""
|
||||
"malformed requirements imbrication detected for option: '{0}' with "
|
||||
"requirement on: '{1}'"
|
||||
msgstr ""
|
||||
"imbrication de requirements malformé detectée pour l'option : '{0}' avec "
|
||||
"imbrication de requirements mal formés detectée pour l'option : '{0}' avec "
|
||||
"requirement sur : '{1}'"
|
||||
|
||||
#: tiramisu/setting.py:515
|
||||
#: tiramisu/setting.py:565
|
||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
||||
msgstr "l'option '{0}' a une erreur de propriété pour le requirement : {1} {2}"
|
||||
|
||||
#: tiramisu/storage/__init__.py:47
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
msgstr "storage_type est déjà défini, impossible de le redéfinir"
|
||||
|
||||
#: tiramisu/storage/__init__.py:81
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr "option {0} n'existe pas dans l'espace de stockage {1}"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:37
|
||||
msgid "dictionary storage cannot delete session"
|
||||
msgstr ""
|
||||
"impossible de supprimer une session dans un espace de stockage dictionary"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:46
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
msgid "session already used"
|
||||
msgstr "session déjà utilisée"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
msgid "a dictionary cannot be persistent"
|
||||
msgstr "un espace de stockage dictionary ne peut être persistant"
|
||||
|
||||
#: tiramisu/value.py:284
|
||||
#: tiramisu/value.py:306
|
||||
msgid "no value for {0} cannot change owner to {1}"
|
||||
msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
|
||||
|
||||
#: tiramisu/value.py:356
|
||||
#: tiramisu/value.py:414
|
||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
||||
msgstr "longueur invalide pour une esclave : {0} qui a {1} comme maître"
|
||||
|
||||
#: tiramisu/value.py:373
|
||||
#: tiramisu/value.py:438
|
||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||
msgstr ""
|
||||
"longueur invalide pour un maître : {0} qui a {1} une esclave avec une plus "
|
||||
"grande longueur"
|
||||
|
||||
#: tiramisu/value.py:394
|
||||
#: tiramisu/value.py:468
|
||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
||||
msgstr "ne peut ajouter une valeur sur l'option multi {0} qui est une esclave"
|
||||
|
||||
#: tiramisu/value.py:429
|
||||
#: tiramisu/value.py:505
|
||||
msgid "cannot sort multi option {0} if master or slave"
|
||||
msgstr "ne peut trier une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:433
|
||||
#: tiramisu/value.py:509
|
||||
msgid "cmp is not permitted in python v3 or greater"
|
||||
msgstr "cmp n'est pas permis en python v3 ou supérieure"
|
||||
|
||||
#: tiramisu/value.py:442
|
||||
#: tiramisu/value.py:518
|
||||
msgid "cannot reverse multi option {0} if master or slave"
|
||||
msgstr "ne peut inverser une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:450
|
||||
#: tiramisu/value.py:526
|
||||
msgid "cannot insert multi option {0} if master or slave"
|
||||
msgstr "ne peut insérer une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:458
|
||||
#: tiramisu/value.py:534
|
||||
msgid "cannot extend multi option {0} if master or slave"
|
||||
msgstr "ne peut étendre une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:482
|
||||
#: tiramisu/value.py:562
|
||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
||||
msgstr "ne peut supprimer une valeur dans l'option multi {0} qui est esclave"
|
||||
|
||||
#~ msgid "metaconfig's children must be a list"
|
||||
#~ msgstr "enfants d'une metaconfig doit être une liste"
|
||||
#~ msgid "invalid value {0} for option {1} which must be a list"
|
||||
#~ msgstr "valeur invalide {0} pour l'option {1} qui doit être une liste"
|
||||
|
||||
#~ msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||
#~ msgstr ""
|
||||
#~ "valeur invalide {0} pour l'option {1} doit être différente de l'option {2}"
|
||||
|
||||
#~ msgid "validator should return a boolean, not {0}"
|
||||
#~ msgstr "le validator devrait retourner un boolean, pas un {0}"
|
||||
|
||||
#~ msgid "invalid value {0} for option {1} for object {2}"
|
||||
#~ msgstr "valeur invalide {0} pour l'option {1} pour l'objet {2}"
|
||||
|
||||
#~ msgid "no config specified but needed"
|
||||
#~ msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||
|
||||
#~ msgid "{0} has no attribute impl_set_information"
|
||||
#~ msgstr "{0} n'a pas d'attribut impl_set_information"
|
||||
|
||||
#~ msgid "{0} has no attribute impl_get_information"
|
||||
#~ msgstr "{0} n'a pas d'attribut impl_get_information"
|
||||
|
||||
#~ msgid "invalid name: {0} for optiondescription"
|
||||
#~ msgstr "nom invalide : {0} pour l'optiondescription"
|
||||
|
||||
#~ msgid "metaconfig's children must be config, not {0}"
|
||||
#~ msgstr "enfants d'une metaconfig doit être une config, pas {0}"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2013-09-02 11:30+CEST\n"
|
||||
"POT-Creation-Date: 2013-09-28 19:06+CEST\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -15,395 +15,455 @@ msgstr ""
|
|||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: tiramisu/autolib.py:58
|
||||
msgid "no config specified but needed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/autolib.py:65
|
||||
#: tiramisu/autolib.py:144
|
||||
msgid "unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/autolib.py:74
|
||||
#: tiramisu/autolib.py:153
|
||||
msgid "unable to carry out a calculation, option value with multi types must have same length for: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:47
|
||||
#: tiramisu/config.py:51
|
||||
msgid "descr must be an optiondescription, not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:121
|
||||
#: tiramisu/config.py:126
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:157
|
||||
#: tiramisu/config.py:162
|
||||
msgid "no option description found for this config (may be metaconfig without meta)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:311
|
||||
#: tiramisu/config.py:188
|
||||
msgid "can't assign to an OptionDescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:319
|
||||
msgid "unknown type_ type {0}for _find"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:350
|
||||
#: tiramisu/config.py:358
|
||||
msgid "no option found in config with these criteria"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:400
|
||||
#: tiramisu/config.py:408
|
||||
msgid "make_dict can't filtering with value without option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:421
|
||||
#: tiramisu/config.py:429
|
||||
msgid "unexpected path {0}, should start with {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:481
|
||||
#: tiramisu/config.py:489
|
||||
msgid "opt in getowner must be an option not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:71
|
||||
msgid "{0} has no attribute impl_set_information"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:86
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:89
|
||||
msgid "{0} has no attribute impl_get_information"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:117
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:208
|
||||
#: tiramisu/option.py:68
|
||||
msgid "invalid name: {0} for option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:218
|
||||
msgid "validator must be a function"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:225
|
||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:231
|
||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:236
|
||||
msgid "default value not allowed if option: {0} is calculated"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:239
|
||||
msgid "params defined for a callback function but no callback defined yet for option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:261 tiramisu/option.py:809
|
||||
#: tiramisu/option.py:77
|
||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:334
|
||||
msgid "invalid value {0} for option {1} for object {2}"
|
||||
#: tiramisu/option.py:115
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:342 tiramisu/value.py:468
|
||||
#: tiramisu/option.py:142 tiramisu/value.py:360
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:204
|
||||
msgid "cannot serialize Option, only in OptionDescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:307
|
||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:313
|
||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:318
|
||||
msgid "default value not allowed if option: {0} is calculated"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:321
|
||||
msgid "params defined for a callback function but no callback defined yet for option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:360
|
||||
msgid "option not in all_cons_opts"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:432 tiramisu/value.py:545
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:354
|
||||
msgid "invalid value {0} for option {1} which must be a list"
|
||||
#: tiramisu/option.py:449
|
||||
msgid "which must be a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:423
|
||||
msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:445
|
||||
msgid "values must be a tuple for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:448
|
||||
msgid "open_values must be a boolean for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:469
|
||||
msgid "value {0} is not permitted, only {1} is allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:481
|
||||
msgid "value must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:491
|
||||
msgid "value must be an integer"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:501
|
||||
msgid "value must be a float"
|
||||
#: tiramisu/option.py:509
|
||||
msgid "consistency should be set with an option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:511
|
||||
msgid "cannot add consistency with itself"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:513
|
||||
msgid "every options in consistency should be multi or none"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:533
|
||||
msgid "same value for {0} and {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:642
|
||||
msgid "values must be a tuple for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:645
|
||||
msgid "open_values must be a boolean for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:667
|
||||
msgid "value {0} is not permitted, only {1} is allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:679
|
||||
msgid "value must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:689
|
||||
msgid "value must be an integer"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:699
|
||||
msgid "value must be a float"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:709
|
||||
msgid "value must be a string, not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:529
|
||||
#: tiramisu/option.py:727
|
||||
msgid "value must be an unicode"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:539
|
||||
#: tiramisu/option.py:739
|
||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:581
|
||||
#: tiramisu/option.py:788
|
||||
msgid "invalid IP {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:793
|
||||
msgid "IP mustn't not be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:583
|
||||
#: tiramisu/option.py:795
|
||||
msgid "IP must be in private class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:621
|
||||
#: tiramisu/option.py:833
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:626
|
||||
#: tiramisu/option.py:838
|
||||
msgid "max value is empty"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:663
|
||||
msgid "network mustn't not be in reserved class"
|
||||
#: tiramisu/option.py:877
|
||||
msgid "invalid network address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:695
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||
#: tiramisu/option.py:882
|
||||
msgid "network shall not be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:700
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:705
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:707
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:727
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:730
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:759
|
||||
msgid "invalid value for {0}, must have dot"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:762
|
||||
msgid "invalid domainname's length for {0} (max {1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:765
|
||||
msgid "invalid domainname's length for {0} (min 2)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:769
|
||||
msgid "invalid domainname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:787
|
||||
msgid "invalid name: {0} for optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:799
|
||||
msgid "duplicate option name: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:825
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:874
|
||||
msgid "duplicate option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:904
|
||||
msgid "no option for path {0}"
|
||||
#: tiramisu/option.py:894
|
||||
msgid "invalid netmask address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:910
|
||||
msgid "invalid len for opts"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:927
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:932
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:934
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:948
|
||||
msgid "invalid broadcast address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
msgid "invalid len for vals"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:957
|
||||
msgid "invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:979
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:982
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1012
|
||||
msgid "invalid value for {0}, must have dot"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1015
|
||||
msgid "invalid domainname's length for {0} (max {1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1018
|
||||
msgid "invalid domainname's length for {0} (min 2)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1022
|
||||
msgid "invalid domainname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1049
|
||||
msgid "duplicate option name: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1067
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1118
|
||||
msgid "duplicate option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1148
|
||||
msgid "consistency with option {0} which is not in Config"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1156
|
||||
msgid "no option for path {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1162
|
||||
msgid "no option {0} found"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:920
|
||||
#: tiramisu/option.py:1172
|
||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:933
|
||||
#: tiramisu/option.py:1185
|
||||
msgid "master group {0} shall not have a subgroup"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:936
|
||||
#: tiramisu/option.py:1188
|
||||
msgid "master group {0} shall not have a symlinkoption"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:939
|
||||
#: tiramisu/option.py:1191
|
||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:950
|
||||
#: tiramisu/option.py:1202
|
||||
msgid "master group with wrong master name for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:959
|
||||
#: tiramisu/option.py:1211
|
||||
msgid "no child has same nom has master group for: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:962
|
||||
#: tiramisu/option.py:1214
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1021
|
||||
#: tiramisu/option.py:1306
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1037
|
||||
#: tiramisu/option.py:1323
|
||||
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1042
|
||||
#: tiramisu/option.py:1328
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1046
|
||||
#: tiramisu/option.py:1332
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1050
|
||||
#: tiramisu/option.py:1336
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1054
|
||||
#: tiramisu/option.py:1340
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1057
|
||||
#: tiramisu/option.py:1343
|
||||
msgid "malformed requirements option {0} should not be a multi"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1063
|
||||
#: tiramisu/option.py:1349
|
||||
msgid "malformed requirements second argument must be valid for option {0}: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1068
|
||||
#: tiramisu/option.py:1354
|
||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:47
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
#: tiramisu/option.py:1379
|
||||
msgid "{0} should be a function"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:67
|
||||
#: tiramisu/option.py:1382
|
||||
msgid "{0}_params should be a dict"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1385
|
||||
msgid "{0}_params with key {1} should not have length different to 1"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1389
|
||||
msgid "{0}_params should be tuple for key \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1395
|
||||
msgid "validator not support tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1398
|
||||
msgid "{0}_params should have an option not a {0} for first argument"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1402
|
||||
msgid "{0}_params should have a boolean not a {0} for second argument"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:111
|
||||
msgid "can't rebind {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:72
|
||||
#: tiramisu/setting.py:116
|
||||
msgid "can't unbind {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:185
|
||||
#: tiramisu/setting.py:254
|
||||
msgid "cannot append {0} property for option {1}: this property is calculated"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:215
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:282
|
||||
#: tiramisu/setting.py:317
|
||||
msgid "opt and all_properties must not be set together in reset"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:297
|
||||
#: tiramisu/setting.py:332
|
||||
msgid "if opt is not None, path should not be None in _getproperties"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:391
|
||||
#: tiramisu/setting.py:435
|
||||
msgid "cannot change the value for option {0} this option is frozen"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:397
|
||||
#: tiramisu/setting.py:441
|
||||
msgid "trying to access to an option named: {0} with properties {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:415
|
||||
#: tiramisu/setting.py:459
|
||||
msgid "permissive must be a tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:422 tiramisu/value.py:277
|
||||
#: tiramisu/setting.py:466 tiramisu/value.py:299
|
||||
msgid "invalid generic owner {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:503
|
||||
#: tiramisu/setting.py:553
|
||||
msgid "malformed requirements imbrication detected for option: '{0}' with requirement on: '{1}'"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:515
|
||||
#: tiramisu/setting.py:565
|
||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/__init__.py:47
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/__init__.py:81
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:37
|
||||
msgid "dictionary storage cannot delete session"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:46
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
msgid "session already used"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
msgid "a dictionary cannot be persistent"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:284
|
||||
#: tiramisu/value.py:306
|
||||
msgid "no value for {0} cannot change owner to {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:356
|
||||
#: tiramisu/value.py:414
|
||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:373
|
||||
#: tiramisu/value.py:438
|
||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:394
|
||||
#: tiramisu/value.py:468
|
||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:429
|
||||
#: tiramisu/value.py:505
|
||||
msgid "cannot sort multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:433
|
||||
#: tiramisu/value.py:509
|
||||
msgid "cmp is not permitted in python v3 or greater"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:442
|
||||
#: tiramisu/value.py:518
|
||||
msgid "cannot reverse multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:450
|
||||
#: tiramisu/value.py:526
|
||||
msgid "cannot insert multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:458
|
||||
#: tiramisu/value.py:534
|
||||
msgid "cannot extend multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:482
|
||||
#: tiramisu/value.py:562
|
||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
||||
msgstr ""
|
||||
|
||||
|
|
Loading…
Reference in New Issue