commit
4a44068a23
2
AUTHORS
2
AUTHORS
|
@ -6,3 +6,5 @@ Emmanuel Garette <egarette@cadoles.com> developer
|
||||||
|
|
||||||
Daniel Dehennin <daniel.dehennin@ac-dijon.fr> contributor
|
Daniel Dehennin <daniel.dehennin@ac-dijon.fr> contributor
|
||||||
Philippe Caseiro <pcaseiro@cadoles.com> contributor
|
Philippe Caseiro <pcaseiro@cadoles.com> contributor
|
||||||
|
|
||||||
|
Gerald Schwartzmann <gschartzmann@cadoles.com> tiramisu's logo (made with The Gimp)
|
||||||
|
|
48
Makefile
48
Makefile
|
@ -15,19 +15,28 @@ ifneq ($(DESTDIR),)
|
||||||
PYTHON_OPTS += --root $(DESTDIR)
|
PYTHON_OPTS += --root $(DESTDIR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LAST_TAG := $(shell git describe --tags --abbrev=0)
|
VERSION := `cat VERSION`
|
||||||
VERSION := $(shell echo $(LAST_TAG) | awk -F'/' '{print $$2}' || true)
|
|
||||||
VERSION_FILE := version.in
|
define gettext
|
||||||
|
if command -v pygettext >/dev/null 2>&1 ; then \
|
||||||
|
P="pygettext" ; \
|
||||||
|
else \
|
||||||
|
P="pygettext.py" ; \
|
||||||
|
fi ; \
|
||||||
|
$$P -p translations/ -o $(PACKAGE).pot `find $(PACKAGE)/ -name "*.py"`
|
||||||
|
endef
|
||||||
|
|
||||||
# Build translation files
|
# Build translation files
|
||||||
define build_translation
|
define build_translation
|
||||||
if [ -d ${1} ]; then \
|
if [ -d ${1} ]; then \
|
||||||
for f in `find ${1} -name "*.po"`; do \
|
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; \
|
done; \
|
||||||
fi
|
fi
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Install Traduction
|
# Install Traduction
|
||||||
define install_translation
|
define install_translation
|
||||||
if [ -d ${1} ]; then \
|
if [ -d ${1} ]; then \
|
||||||
|
@ -39,38 +48,33 @@ define install_translation
|
||||||
fi
|
fi
|
||||||
endef
|
endef
|
||||||
|
|
||||||
all:
|
all: build-lang
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(RM) -r build
|
$(RM) -r build
|
||||||
$(RM) -r tiramisu.egg-info/
|
$(RM) -r $(PACKAGE).egg-info/
|
||||||
$(RM) -r $(TRADUC_DIR)/*/*.mo
|
$(RM) -r $(TRADUC_DIR)/*/*.mo
|
||||||
|
|
||||||
#test: clean
|
#test: clean
|
||||||
# py.test
|
# py.test
|
||||||
|
|
||||||
|
# Build or update Portable Object Base Translation for gettext
|
||||||
|
|
||||||
|
build-pot:
|
||||||
|
$(call gettext)
|
||||||
|
|
||||||
build-lang:
|
build-lang:
|
||||||
$(call build_translation, $(TRADUC_DIR))
|
$(call build_translation, $(TRADUC_DIR))
|
||||||
|
|
||||||
install-lang: build-lang
|
install-lang:
|
||||||
$(INSTALL_DIR) $(TRADUC_DEST)
|
$(INSTALL_DIR) $(TRADUC_DEST)
|
||||||
$(call install_translation, $(TRADUC_DIR))
|
$(call install_translation, $(TRADUC_DIR))
|
||||||
|
|
||||||
install: version.in install-lang
|
install: install-lang
|
||||||
python setup.py install --no-compile $(PYTHON_OPTS)
|
python setup.py install --no-compile $(PYTHON_OPTS)
|
||||||
|
|
||||||
|
dist:
|
||||||
|
git archive --format=tar --prefix $(PACKAGE)-$(VERSION)/ HEAD | gzip -9 > $(PACKAGE)-$(VERSION).tar.gz
|
||||||
|
|
||||||
# List in .PHONY to force generation at each call
|
# List in .PHONY to force generation at each call
|
||||||
version.in:
|
.PHONY: all clean build-pot build-lang install-lang install dist
|
||||||
@if test -n $(VERSION) ; then \
|
|
||||||
echo -n $(VERSION) > $(VERSION_FILE) ; \
|
|
||||||
fi
|
|
||||||
@if test ! -s $(VERSION_FILE); then \
|
|
||||||
echo -n '0.0-dev' > $(VERSION_FILE); \
|
|
||||||
fi
|
|
||||||
|
|
||||||
dist: version.in
|
|
||||||
git archive --format=tar --prefix $(PACKAGE)-$(VERSION)/ -o $(PACKAGE)-$(VERSION).tar $(LAST_TAG) \
|
|
||||||
&& tar --xform "s,\(.*\),$(PACKAGE)-$(VERSION)/\1," -f $(PACKAGE)-$(VERSION).tar -r version.in \
|
|
||||||
&& gzip -9 $(PACKAGE)-$(VERSION).tar
|
|
||||||
|
|
||||||
.PHONY: all clean test install version.in dist
|
|
||||||
|
|
|
@ -11,4 +11,5 @@ Auto generated library's API
|
||||||
tiramisu.value
|
tiramisu.value
|
||||||
tiramisu.autolib
|
tiramisu.autolib
|
||||||
tiramisu.error
|
tiramisu.error
|
||||||
|
tiramisu.storage
|
||||||
|
|
||||||
|
|
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 |
113
doc/config.txt
113
doc/config.txt
|
@ -6,15 +6,17 @@ Options handling basics
|
||||||
|
|
||||||
Tiramisu is made of almost three main objects :
|
Tiramisu is made of almost three main objects :
|
||||||
|
|
||||||
- :class:`tiramisu.config.Config` which is the whole configuration entry point
|
|
||||||
- :class:`tiramisu.option.Option` stands for the option types
|
- :class:`tiramisu.option.Option` stands for the option types
|
||||||
- :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
|
- :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
|
||||||
|
- :class:`tiramisu.config.Config` which is the whole configuration entry point
|
||||||
|
|
||||||
|
.. image:: config.png
|
||||||
|
|
||||||
Accessing the `Option`'s
|
Accessing the `Option`'s
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
The :class:`~tiramisu.config.Config` object attribute access notation stands for
|
The :class:`~tiramisu.config.Config` object attribute access notation stands for
|
||||||
the value of the configuration's :class:`~tiramisu.option.Option`. That is, the
|
the value of the configuration's :class:`~tiramisu.option.Option`.
|
||||||
:class:`~tiramisu.config.Config`'s object attribute is the name of the option,
|
:class:`~tiramisu.config.Config`'s object attribute is the name of the option,
|
||||||
and the value is the value accessed by the `__getattr__` attribute access
|
and the value is the value accessed by the `__getattr__` attribute access
|
||||||
mechanism.
|
mechanism.
|
||||||
|
@ -49,7 +51,7 @@ are organized into a tree into nested
|
||||||
as does every option group. The parts of the full name of the option are
|
as does every option group. The parts of the full name of the option are
|
||||||
separated by dots: e.g. ``cfg.optgroup.optname``.
|
separated by dots: e.g. ``cfg.optgroup.optname``.
|
||||||
|
|
||||||
Let's make the protocol of accessing a config's attribute explicit
|
Let's make the protocol of accessing a `Config`'s attribute explicit
|
||||||
(because explicit is better than implicit):
|
(because explicit is better than implicit):
|
||||||
|
|
||||||
1. If the option has not been declared, an `AttributeError` is raised,
|
1. If the option has not been declared, an `AttributeError` is raised,
|
||||||
|
@ -67,22 +69,11 @@ But there are special exceptions. We will see later on that an option can be a
|
||||||
:term:`mandatory option`. A mandatory option is an option that must have a value
|
:term:`mandatory option`. A mandatory option is an option that must have a value
|
||||||
defined.
|
defined.
|
||||||
|
|
||||||
Appart from this case, if no value have been set yet, the value is `None`. When
|
Setting the value of an option
|
||||||
the option is called to retrieve a value, an exception is raised.
|
------------------------------
|
||||||
|
|
||||||
What if a value has been set and `None` is to be returned again ? Don't worry,
|
An important part of the setting's configuration consists of setting the
|
||||||
an option value can be reseted::
|
value's option. There are different ways of setting values,
|
||||||
::
|
|
||||||
|
|
||||||
>>> cfg.cfgimpl_get_values().reset(gcdummy)
|
|
||||||
>>> cfg.dummy
|
|
||||||
False
|
|
||||||
|
|
||||||
Setting the values of the options
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
An important part of the setting of the configuration consists of setting the
|
|
||||||
values of the configuration options. There are different ways of setting values,
|
|
||||||
the first one is of course the `__setattr__` method
|
the first one is of course the `__setattr__` method
|
||||||
|
|
||||||
::
|
::
|
||||||
|
@ -110,14 +101,14 @@ adhere to the option description).
|
||||||
Common manipulations
|
Common manipulations
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
Let's perform some common manipulation on some options:
|
Let's perform some common manipulation on some options
|
||||||
|
|
||||||
>>> from tiramisu.config import Config
|
>>> from tiramisu.config import Config
|
||||||
>>> from tiramisu.option import UnicodeOption, OptionDescription
|
>>> from tiramisu.option import UnicodeOption, OptionDescription
|
||||||
>>>
|
>>> #
|
||||||
>>> var1 = UnicodeOption('var1', 'first variable')
|
>>> var1 = UnicodeOption('var1', 'first variable')
|
||||||
>>> var2 = UnicodeOption('var2', '', u'value')
|
>>> var2 = UnicodeOption('var2', '', u'value')
|
||||||
>>>
|
>>> #
|
||||||
>>> od1 = OptionDescription('od1', 'first OD', [var1, var2])
|
>>> od1 = OptionDescription('od1', 'first OD', [var1, var2])
|
||||||
>>> rootod = OptionDescription('rootod', '', [od1])
|
>>> rootod = OptionDescription('rootod', '', [od1])
|
||||||
|
|
||||||
|
@ -138,11 +129,10 @@ None
|
||||||
>>> print c.od1.var2
|
>>> print c.od1.var2
|
||||||
value
|
value
|
||||||
|
|
||||||
let's modify a value (careful to the value's type...)
|
let's modify a value (be careful to the value's type...)
|
||||||
|
|
||||||
>>> c.od1.var1 = 'value'
|
>>> c.od1.var1 = 'value'
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
ValueError: invalid value value for option var1
|
ValueError: invalid value value for option var1
|
||||||
>>> c.od1.var1 = u'value'
|
>>> c.od1.var1 = u'value'
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
|
@ -158,18 +148,16 @@ let's come back to the default value
|
||||||
value
|
value
|
||||||
|
|
||||||
The value is saved in a :class:`~tiramisu.value.Value` object. It is on this
|
The value is saved in a :class:`~tiramisu.value.Value` object. It is on this
|
||||||
object that we have to trigger the `reset`, wich take the option itself
|
object that we have to trigger the `reset`, which take the option itself
|
||||||
(`var2`) as a parameter.
|
(`var2`) as a parameter.
|
||||||
|
|
||||||
On the other side, in the `read_only` mode, it is not possible to modify the value::
|
On the other side, in the `read_only` mode, it is not possible to modify the value
|
||||||
|
|
||||||
|
>>> c.read_only()
|
||||||
|
>>> c.od1.var2 = u'value2'
|
||||||
|
Traceback (most recent call last):
|
||||||
|
tiramisu.error.PropertiesOptionError: cannot change the value for option var2 this option is frozen
|
||||||
|
|
||||||
>>> c.read_only()
|
|
||||||
>>> c.od1.var2 = u'value2'
|
|
||||||
Traceback (most recent call last):
|
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError:
|
|
||||||
cannot change the value to var2
|
|
||||||
for option ['frozen'] this option is frozen
|
|
||||||
|
|
||||||
let's retrieve the option `var1` description
|
let's retrieve the option `var1` description
|
||||||
|
|
||||||
|
@ -200,7 +188,7 @@ That's why a tree of options can easily be searched. First, let's build such a t
|
||||||
>>> c = Config(rootod)
|
>>> c = Config(rootod)
|
||||||
>>> c.read_write()
|
>>> c.read_write()
|
||||||
|
|
||||||
Second, let's find an option by his name::
|
Second, let's find an option by it's name::
|
||||||
|
|
||||||
>>> print c.find(byname='var1')
|
>>> print c.find(byname='var1')
|
||||||
[<tiramisu.option.UnicodeOption object at 0x7ff1bf7d6ef0>,
|
[<tiramisu.option.UnicodeOption object at 0x7ff1bf7d6ef0>,
|
||||||
|
@ -248,7 +236,7 @@ If the organisation in a tree is not important,
|
||||||
{'var5': None, 'var4': None, 'var6': None, 'var1': u'value', 'var3': None,
|
{'var5': None, 'var4': None, 'var6': None, 'var1': u'value', 'var3': None,
|
||||||
'var2': None}
|
'var2': None}
|
||||||
|
|
||||||
.. note:: carefull with this `flatten` parameter, here we have just lost
|
.. note:: be carefull with this `flatten` parameter, here we have just lost
|
||||||
two options named `var1`
|
two options named `var1`
|
||||||
|
|
||||||
One can export only interesting parts of a tree of options into a dict, for
|
One can export only interesting parts of a tree of options into a dict, for
|
||||||
|
@ -265,7 +253,7 @@ and of course, :meth:`~config.SubConfig.make_dict()` can be called in a subtree:
|
||||||
>>> print c.od1.make_dict(withoption='var1')
|
>>> print c.od1.make_dict(withoption='var1')
|
||||||
{'var1': None, 'var3': None, 'var2': None}
|
{'var1': None, 'var3': None, 'var2': None}
|
||||||
|
|
||||||
the owners
|
The owners
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. glossary::
|
.. glossary::
|
||||||
|
@ -283,24 +271,36 @@ the owners
|
||||||
|
|
||||||
Then let's retrieve the owner associated to an option::
|
Then let's retrieve the owner associated to an option::
|
||||||
|
|
||||||
>>> print c.getowner('var1')
|
>>> print c.getowner(var1)
|
||||||
default
|
default
|
||||||
>>> c.od1.var1 = u'non'
|
>>> c.od1.var1 = u'no'
|
||||||
>>> print c.getowner('var1')
|
>>> print c.getowner(var1)
|
||||||
user
|
user
|
||||||
>>> del(c.var1)
|
>>> del(c.var1)
|
||||||
>>> print c.getowner('var1')
|
>>> print c.getowner(var1)
|
||||||
default
|
default
|
||||||
|
|
||||||
the properties
|
You can create your own owner, for example to distinguish modification made by
|
||||||
~~~~~~~~~~~~~~~~
|
one user to an other one's.
|
||||||
|
|
||||||
|
>>> from tiramisu.setting import owners
|
||||||
|
>>> owners.addowner('toto')
|
||||||
|
>>> c.cfgimpl_get_settings().setowner(owners.toto)
|
||||||
|
>>> print c.getowner(var1)
|
||||||
|
default
|
||||||
|
>>> c.od1.var1 = u'no'
|
||||||
|
>>> print c.getowner(var1)
|
||||||
|
toto
|
||||||
|
|
||||||
|
The properties
|
||||||
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A property is an information on an option's state.
|
A property is an information on an option's state.
|
||||||
Let's create options with properties::
|
Let's create options with properties::
|
||||||
|
|
||||||
>>> var1 = UnicodeOption('var1', '', u'value', properties=('hidden',))
|
>>> var1 = UnicodeOption('var1', '', u'value', properties=('hidden',))
|
||||||
>>> var2 = UnicodeOption('var2', '', properties=('mandatory',))
|
>>> var2 = UnicodeOption('var2', '', properties=('mandatory',))
|
||||||
>>> var3 = UnicodeOption('var3', '', u'value', properties=('frozen', 'inconnu'))
|
>>> var3 = UnicodeOption('var3', '', u'value', properties=('frozen', 'unknown'))
|
||||||
>>> var4 = UnicodeOption('var4', '', u'value')
|
>>> var4 = UnicodeOption('var4', '', u'value')
|
||||||
>>> od1 = OptionDescription('od1', '', [var1, var2, var3])
|
>>> od1 = OptionDescription('od1', '', [var1, var2, var3])
|
||||||
>>> od2 = OptionDescription('od2', '', [var4], properties=('hidden',))
|
>>> od2 = OptionDescription('od2', '', [var4], properties=('hidden',))
|
||||||
|
@ -314,7 +314,6 @@ with a hidden option::
|
||||||
|
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named: var1
|
tiramisu.error.PropertiesOptionError: trying to access to an option named: var1
|
||||||
with properties ['hidden']
|
with properties ['hidden']
|
||||||
>>> c.read_only()
|
>>> c.read_only()
|
||||||
|
@ -331,7 +330,6 @@ mode. But in read only mode, an error is raised if no value has been defined::
|
||||||
>>> c.read_only()
|
>>> c.read_only()
|
||||||
>>> print c.od1.var2
|
>>> print c.od1.var2
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named: var2
|
tiramisu.error.PropertiesOptionError: trying to access to an option named: var2
|
||||||
with properties ['mandatory']
|
with properties ['mandatory']
|
||||||
>>> c.read_write()
|
>>> c.read_write()
|
||||||
|
@ -348,7 +346,6 @@ Let's try to modify a frozen option::
|
||||||
value
|
value
|
||||||
>>> c.od1.var3 = u'value2'
|
>>> c.od1.var3 = u'value2'
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: cannot change the value for option var3 this option is frozen
|
tiramisu.error.PropertiesOptionError: cannot change the value for option var3 this option is frozen
|
||||||
>>> c.read_only()
|
>>> c.read_only()
|
||||||
>>> print c.od1.var3
|
>>> print c.od1.var3
|
||||||
|
@ -357,23 +354,21 @@ Let's try to modify a frozen option::
|
||||||
Tiramisu allows us to use user defined properties. Let's define and use one in
|
Tiramisu allows us to use user defined properties. Let's define and use one in
|
||||||
read/write or read only mode::
|
read/write or read only mode::
|
||||||
|
|
||||||
>>> c.cfgimpl_get_settings().append('inconnu')
|
>>> c.cfgimpl_get_settings().append('unknown')
|
||||||
>>> print c.od1.var3
|
>>> print c.od1.var3
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
||||||
var3 with properties ['inconnu']
|
var3 with properties ['unknown']
|
||||||
>>> c.cfgimpl_get_settings().remove('inconnu')
|
>>> c.cfgimpl_get_settings().remove('unknown')
|
||||||
>>> print c.od1.var3
|
>>> print c.od1.var3
|
||||||
value
|
value
|
||||||
|
|
||||||
Properties can also be defined on an option group, (that is, on an
|
Properties can also be defined on an option group (that is, on an
|
||||||
:term:`option description`), let's hide a group and try to access to it::
|
:term:`option description`) let's hide a group and try to access to it::
|
||||||
|
|
||||||
>>> c.read_write()
|
>>> c.read_write()
|
||||||
>>> print c.od2.var4
|
>>> print c.od2.var4
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named: od2
|
tiramisu.error.PropertiesOptionError: trying to access to an option named: od2
|
||||||
with properties ['hidden']
|
with properties ['hidden']
|
||||||
>>> c.read_only()
|
>>> c.read_only()
|
||||||
|
@ -387,7 +382,6 @@ Furthermore, let's retrieve the properties, delete and add the `hidden` property
|
||||||
['hidden']
|
['hidden']
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
||||||
var1 with properties ['hidden']
|
var1 with properties ['hidden']
|
||||||
>>> c.cfgimpl_get_settings()[rootod.od1.var1].remove('hidden')
|
>>> c.cfgimpl_get_settings()[rootod.od1.var1].remove('hidden')
|
||||||
|
@ -400,7 +394,6 @@ Furthermore, let's retrieve the properties, delete and add the `hidden` property
|
||||||
['hidden']
|
['hidden']
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
||||||
var1 with properties ['hidden']
|
var1 with properties ['hidden']
|
||||||
|
|
||||||
|
@ -438,11 +431,10 @@ A multi-option's value can be manipulated like a list::
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
[u'var1']
|
[u'var1']
|
||||||
|
|
||||||
But it is not possible to set a value to a multi-option wich is not a list::
|
But it is not possible to set a value to a multi-option which is not a list::
|
||||||
|
|
||||||
>>> c.od1.var1 = u'error'
|
>>> c.od1.var1 = u'error'
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
ValueError: invalid value error for option var1 which must be a list
|
ValueError: invalid value error for option var1 which must be a list
|
||||||
|
|
||||||
|
|
||||||
|
@ -514,17 +506,14 @@ But it is forbidden to change the lenght of a slave::
|
||||||
slave2 = [u'default', u'default']
|
slave2 = [u'default', u'default']
|
||||||
>>> c.master.slave1 = [u'new1']
|
>>> c.master.slave1 = [u'new1']
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
|
tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
|
||||||
>>> c.master.slave1 = [u'new1', u'new2', u'new3']
|
>>> c.master.slave1 = [u'new1', u'new2', u'new3']
|
||||||
[...]
|
|
||||||
tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
|
tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
|
||||||
|
|
||||||
you have to call the `pop` function on the master::
|
you have to call the `pop` function on the master::
|
||||||
|
|
||||||
>>> c.master.master = [u'oui']
|
>>> c.master.master = [u'oui']
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.SlaveError: invalid len for the master: master which has slave1 as slave with greater len
|
tiramisu.error.SlaveError: invalid len for the master: master which has slave1 as slave with greater len
|
||||||
>>> c.master.master.pop(0)
|
>>> c.master.master.pop(0)
|
||||||
u'oui'
|
u'oui'
|
||||||
|
@ -570,6 +559,6 @@ Here are the (useful) methods on ``Config`` (or `SubConfig`).
|
||||||
A :class:`~config.CommonConfig` is a abstract base class. A
|
A :class:`~config.CommonConfig` is a abstract base class. A
|
||||||
:class:`~config.SubConfig` is an just in time created objects that wraps an
|
:class:`~config.SubConfig` is an just in time created objects that wraps an
|
||||||
::class:`~option.OptionDescription`. A SubConfig differs from a Config in the
|
::class:`~option.OptionDescription`. A SubConfig differs from a Config in the
|
||||||
::fact that a config is a root object and has an environnement, a context wich
|
fact that a config is a root object and has an environnement, a context which
|
||||||
::defines the different properties, access rules, vs... There is generally only
|
defines the different properties, access rules, vs... There is generally only
|
||||||
::one Config, and many SubConfigs.
|
one Config, and many SubConfigs.
|
||||||
|
|
|
@ -57,7 +57,7 @@ A requirement is a list of dictionaries that have fairly this form::
|
||||||
'transitive':True, 'same_action': True}]
|
'transitive':True, 'same_action': True}]
|
||||||
|
|
||||||
Actually a transformation is made to this dictionary during the validation of
|
Actually a transformation is made to this dictionary during the validation of
|
||||||
this requires at the :class:`~option.Option()`'s init. The dictionairy becomes
|
this requires at the :class:`~option.Option()`'s init. The dictionary becomes
|
||||||
a tuple, wich is passed to the :meth:`~setting.Settings.apply_requires()`
|
a tuple, wich is passed to the :meth:`~setting.Settings.apply_requires()`
|
||||||
method. Take a look at the code to fully understand the exact meaning of the
|
method. Take a look at the code to fully understand the exact meaning of the
|
||||||
requirements:
|
requirements:
|
||||||
|
@ -103,7 +103,6 @@ hidden any more::
|
||||||
['hidden']
|
['hidden']
|
||||||
>>> print c.od1.var1
|
>>> print c.od1.var1
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
tiramisu.error.PropertiesOptionError: trying to access to an option named:
|
||||||
var1 with properties ['hidden']
|
var1 with properties ['hidden']
|
||||||
>>> c.od1.var2 = u'oui'
|
>>> c.od1.var2 = u'oui'
|
||||||
|
@ -123,7 +122,6 @@ document.)::
|
||||||
>>> c.od1.var2 = u'non'
|
>>> c.od1.var2 = u'non'
|
||||||
>>> print c.od2.var4
|
>>> print c.od2.var4
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
tiramisu.error.PropertiesOptionError: trying to access to an option named: od2 with properties ['hidden']
|
tiramisu.error.PropertiesOptionError: trying to access to an option named: od2 with properties ['hidden']
|
||||||
>>> c.od1.var2 = u'oui'
|
>>> c.od1.var2 = u'oui'
|
||||||
>>> print c.od2.var4
|
>>> print c.od2.var4
|
||||||
|
@ -144,21 +142,20 @@ Requirements can be accumulated for different or identical properties (inverted
|
||||||
or not)::
|
or not)::
|
||||||
|
|
||||||
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
||||||
'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'expected':'oui',
|
... 'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'expected':'oui',
|
||||||
'action':'hidden'}])
|
... 'action':'hidden'}])
|
||||||
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
||||||
'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'excepted':'oui',
|
... 'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'excepted':'oui',
|
||||||
'action':'disabled', 'inverse':True}])
|
... 'action':'disabled', 'inverse':True}])
|
||||||
|
|
||||||
But it is not possible to have inverted requirements on the same property.
|
But it is not possible to have inverted requirements on the same property.
|
||||||
Here is an impossible situation::
|
Here is an impossible situation::
|
||||||
|
|
||||||
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
>>> a = UnicodeOption('var3', '', u'value', requires=[{'option':od1.var2,
|
||||||
'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'expected':'oui',
|
... 'expected':'non', 'action':'hidden'}, {'option':od1.var1, 'expected':'oui',
|
||||||
'hidden', True}])
|
... 'hidden', True}])
|
||||||
|
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
ValueError: inconsistency in action types for option: var3 action: hidden
|
ValueError: inconsistency in action types for option: var3 action: hidden
|
||||||
|
|
||||||
Validation upon a whole configuration object
|
Validation upon a whole configuration object
|
||||||
|
@ -184,11 +181,8 @@ Let's define validator (wich is a normal python function)::
|
||||||
Here is an option wich uses this validator::
|
Here is an option wich uses this validator::
|
||||||
|
|
||||||
>>> var1 = UnicodeOption('var1', '', u'oui', validator=valid_a, validator_args={'letter': 'o'})
|
>>> var1 = UnicodeOption('var1', '', u'oui', validator=valid_a, validator_args={'letter': 'o'})
|
||||||
>>>
|
|
||||||
>>> od1 = OptionDescription('od1', '', [var1])
|
>>> od1 = OptionDescription('od1', '', [var1])
|
||||||
>>>
|
|
||||||
>>> rootod = OptionDescription('rootod', '', [od1])
|
>>> rootod = OptionDescription('rootod', '', [od1])
|
||||||
>>>
|
|
||||||
>>> c = Config(rootod)
|
>>> c = Config(rootod)
|
||||||
>>> c.read_write()
|
>>> c.read_write()
|
||||||
|
|
||||||
|
@ -196,11 +190,10 @@ The validation is applied at the modification time::
|
||||||
|
|
||||||
>>> c.od1.var1 = u'non'
|
>>> c.od1.var1 = u'non'
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
[...]
|
|
||||||
ValueError: invalid value non for option var1
|
ValueError: invalid value non for option var1
|
||||||
>>> c.od1.var1 = u'oh non'
|
>>> c.od1.var1 = u'oh non'
|
||||||
|
|
||||||
Il est possible de désactiver la validation :
|
You can disabled this validation::
|
||||||
|
|
||||||
>>> c.cfgimpl_get_settings().remove('validator')
|
>>> c.cfgimpl_get_settings().remove('validator')
|
||||||
>>> c.od1.var1 = u'non'
|
>>> c.od1.var1 = u'non'
|
||||||
|
|
|
@ -23,9 +23,6 @@ option APIs
|
||||||
others
|
others
|
||||||
----------
|
----------
|
||||||
|
|
||||||
.. automodule:: test.test_config_api
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. automodule:: test.test_mandatory
|
.. automodule:: test.test_mandatory
|
||||||
:members:
|
:members:
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ introduced...
|
||||||
What is Tiramisu ?
|
What is Tiramisu ?
|
||||||
===================
|
===================
|
||||||
|
|
||||||
Tiramisu is an options handler and an options controller, wich aims at
|
Tiramisu is an options handler and an options controller, which aims at
|
||||||
producing flexible and fast options access. The main advantages are its access
|
producing flexible and fast options access. The main advantages are its access
|
||||||
rules and the fact that the whole consistency is preserved at any time, see
|
rules and the fact that the whole consistency is preserved at any time, see
|
||||||
:doc:`consistency`. There is of course type and structure validations, but also
|
:doc:`consistency`. There is of course type and structure validations, but also
|
||||||
|
@ -65,7 +65,7 @@ So by now, we have:
|
||||||
|
|
||||||
- a namespace (which is `c` here)
|
- a namespace (which is `c` here)
|
||||||
- the access of an option's value by the
|
- the access of an option's value by the
|
||||||
attribute access way (here `bool`, wich is a boolean option
|
attribute access way (here `bool`, which is a boolean option
|
||||||
:class:`~tiramisu.option.BoolOption()`.
|
:class:`~tiramisu.option.BoolOption()`.
|
||||||
|
|
||||||
So, option objects are produced at the entry point `c` and then handed down to
|
So, option objects are produced at the entry point `c` and then handed down to
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
The tasting of `Tiramisu`
|
The tasting of `Tiramisu`
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
.. image:: tiramisu.jpeg
|
.. image:: logo.png
|
||||||
:height: 150px
|
:height: 150px
|
||||||
|
|
||||||
`Tiramisu`
|
`Tiramisu`
|
||||||
|
@ -34,6 +34,7 @@ controlling options explanations
|
||||||
getting-started
|
getting-started
|
||||||
config
|
config
|
||||||
option
|
option
|
||||||
|
storage
|
||||||
status
|
status
|
||||||
consistency
|
consistency
|
||||||
error
|
error
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
|
@ -9,7 +9,7 @@ Description of Options
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
All the constructors take a ``name`` and a ``doc`` argument as first
|
All the constructors take a ``name`` and a ``doc`` argument as first
|
||||||
arguments to give the option or option group a name and to document it.
|
arguments to give to the option or option description a name and a description document.
|
||||||
Most constructors take a ``default`` argument that specifies the default
|
Most constructors take a ``default`` argument that specifies the default
|
||||||
value of the option. If this argument is not supplied the default value
|
value of the option. If this argument is not supplied the default value
|
||||||
is assumed to be ``None``.
|
is assumed to be ``None``.
|
||||||
|
@ -17,7 +17,7 @@ is assumed to be ``None``.
|
||||||
The `Option` base class
|
The `Option` base class
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
It's the abstract base class for almost all options (except the symblink).
|
It's the abstract base class for almost all options (except the symlink).
|
||||||
|
|
||||||
.. _optioninit:
|
.. _optioninit:
|
||||||
|
|
||||||
|
@ -28,22 +28,41 @@ It's the abstract base class for almost all options (except the symblink).
|
||||||
All option types
|
All option types
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
BoolOption
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: BoolOption
|
.. autoclass:: BoolOption
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
IntOption
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: IntOption
|
.. autoclass:: IntOption
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
FloatOption
|
||||||
|
~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: FloatOption
|
.. autoclass:: FloatOption
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
StrOption
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: StrOption
|
.. autoclass:: StrOption
|
||||||
:private-members:
|
:private-members:
|
||||||
|
|
||||||
|
UnicodeOption
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: UnicodeOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
SymLinkOption
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: SymLinkOption
|
.. autoclass:: SymLinkOption
|
||||||
|
:private-members:
|
||||||
.. automethod:: __init__
|
|
||||||
|
|
||||||
|
|
||||||
``SymLinkOption`` redirects to another configuration option in the
|
``SymLinkOption`` redirects to another configuration option in the
|
||||||
|
@ -52,19 +71,41 @@ configuration, that is :
|
||||||
- retrieves the value of the target,
|
- retrieves the value of the target,
|
||||||
- can set the value of the target too
|
- can set the value of the target too
|
||||||
|
|
||||||
|
IPOption
|
||||||
|
~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: IPOption
|
.. autoclass:: IPOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
PortOption
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. autoclass:: PortOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
NetmaskOption
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: NetmaskOption
|
.. autoclass:: NetmaskOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
NetworkOption
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: NetworkOption
|
.. autoclass:: NetworkOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
DomainnameOption
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: DomainnameOption
|
.. autoclass:: DomainnameOption
|
||||||
|
:private-members:
|
||||||
|
|
||||||
|
ChoiceOption
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
.. autoclass:: ChoiceOption
|
.. autoclass:: ChoiceOption
|
||||||
|
:private-members:
|
||||||
.. automethod:: __init__
|
|
||||||
|
|
||||||
|
|
||||||
.. _optdescr:
|
.. _optdescr:
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,265 @@
|
||||||
|
<?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="106.95445"
|
||||||
|
inkscape:cy="208.15932"
|
||||||
|
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)">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 235.5,78.588237 306,109"
|
||||||
|
id="path4403"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:connection-start="#g4211"
|
||||||
|
inkscape:connection-start-point="d4"
|
||||||
|
transform="translate(0,852.36218)" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 235.5,131.08416 305,107"
|
||||||
|
id="path4405"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
inkscape:connection-start="#g4216"
|
||||||
|
inkscape:connection-start-point="d4"
|
||||||
|
transform="translate(0,852.36218)" />
|
||||||
|
<g
|
||||||
|
id="g4206"
|
||||||
|
transform="translate(-17,590)">
|
||||||
|
<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(-17,590)">
|
||||||
|
<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="686.00001%"
|
||||||
|
id="text3777"
|
||||||
|
y="330.36218"
|
||||||
|
x="206"
|
||||||
|
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="330.36218"
|
||||||
|
x="206"
|
||||||
|
id="tspan3779"
|
||||||
|
sodipodi:role="line">Values</tspan></text>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4216"
|
||||||
|
transform="translate(-17,590)">
|
||||||
|
<rect
|
||||||
|
y="389.36218"
|
||||||
|
x="189.5"
|
||||||
|
height="30"
|
||||||
|
width="63"
|
||||||
|
id="rect3757-4"
|
||||||
|
style="fill:none;stroke:#000000;stroke-linejoin:round;stroke-opacity:1" />
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="686.00001%"
|
||||||
|
id="text3799"
|
||||||
|
y="407.36218"
|
||||||
|
x="200"
|
||||||
|
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="407.36218"
|
||||||
|
x="200"
|
||||||
|
id="tspan3801"
|
||||||
|
sodipodi:role="line">Settings</tspan></text>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 127,967.39444 45.5,15.93548"
|
||||||
|
id="path4028"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 127,945.0396 45.5,-16.35484"
|
||||||
|
id="path4030"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
id="rect4161"
|
||||||
|
width="55.5"
|
||||||
|
height="26"
|
||||||
|
x="277.5"
|
||||||
|
y="946.36218" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.96347165;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3843"
|
||||||
|
sodipodi:cx="401"
|
||||||
|
sodipodi:cy="334.86218"
|
||||||
|
sodipodi:rx="38"
|
||||||
|
sodipodi:ry="10.5"
|
||||||
|
d="m 439,334.86218 a 38,10.5 0 1 1 -76,0 38,10.5 0 1 1 76,0 z"
|
||||||
|
transform="matrix(0.71325325,0,0,0.57998971,18.66254,749.17042)" />
|
||||||
|
<path
|
||||||
|
transform="matrix(0.71325325,0,0,0.57998971,18.57337,775.05247)"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.96347165;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3843-3"
|
||||||
|
sodipodi:cx="401"
|
||||||
|
sodipodi:cy="334.86218"
|
||||||
|
sodipodi:rx="38"
|
||||||
|
sodipodi:ry="10.5"
|
||||||
|
d="m 439,334.86218 a 38,10.5 0 1 1 -76,0 38,10.5 0 1 1 76,0 z" />
|
||||||
|
<path
|
||||||
|
transform="matrix(0.71325325,0,0,0.57998971,18.52879,762.07519)"
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.96347165;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3843-3-0"
|
||||||
|
sodipodi:cx="401"
|
||||||
|
sodipodi:cy="334.86218"
|
||||||
|
sodipodi:rx="38"
|
||||||
|
sodipodi:ry="10.5"
|
||||||
|
d="m 439,334.86218 a 38,10.5 0 1 1 -76,0 38,10.5 0 1 1 76,0 z" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
id="rect3883"
|
||||||
|
width="62.989182"
|
||||||
|
height="6.7061315"
|
||||||
|
x="274.72043"
|
||||||
|
y="949.91193" />
|
||||||
|
<rect
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||||
|
id="rect3883-3"
|
||||||
|
width="58.087975"
|
||||||
|
height="6.4161367"
|
||||||
|
x="277.34818"
|
||||||
|
y="962.78046" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.26286423;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||||
|
d="m 277.52869,943.35095 -0.0442,26.02673"
|
||||||
|
id="path3917"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.26286423;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
|
||||||
|
d="m 331.64698,969.26909 0.13377,-26.17203"
|
||||||
|
id="path3921"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
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"
|
||||||
|
x="286.33643"
|
||||||
|
y="958.32324"
|
||||||
|
id="text3821"
|
||||||
|
sodipodi:linespacing="686.00001%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan3823"
|
||||||
|
x="286.33643"
|
||||||
|
y="958.32324">Storage</tspan></text>
|
||||||
|
<g
|
||||||
|
id="g4201"
|
||||||
|
transform="translate(-17,590)">
|
||||||
|
<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>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 95.5,913.42468 0,27.9375"
|
||||||
|
id="path4199"
|
||||||
|
inkscape:connector-type="polyline"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.4 KiB |
|
@ -0,0 +1,52 @@
|
||||||
|
Storage
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. automodule:: tiramisu.storage
|
||||||
|
|
||||||
|
.. automethod:: tiramisu.storage.set_storage
|
||||||
|
|
||||||
|
.. image:: storage.png
|
||||||
|
|
||||||
|
Dictionary
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
.. automodule:: tiramisu.storage.dictionary
|
||||||
|
|
||||||
|
Dictionary settings:
|
||||||
|
|
||||||
|
.. automethod:: tiramisu.storage.dictionary.storage.Setting
|
||||||
|
|
||||||
|
Sqlite3
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
.. automodule:: tiramisu.storage.sqlite3
|
||||||
|
|
||||||
|
Sqlite3 settings:
|
||||||
|
|
||||||
|
.. automethod:: tiramisu.storage.sqlite3.storage.Setting
|
||||||
|
|
||||||
|
Example
|
||||||
|
~~~~~~~
|
||||||
|
|
||||||
|
>>> from tiramisu.option import StrOption, OptionDescription
|
||||||
|
>>> from tiramisu.config import Config
|
||||||
|
>>> from tiramisu.storage import set_storage
|
||||||
|
>>> set_storage('sqlite3', dir_database='/tmp/tiramisu')
|
||||||
|
>>> s = StrOption('str', '')
|
||||||
|
>>> o = OptionDescription('od', '', [s])
|
||||||
|
>>> c1 = Config(o, persistent=True, session_id='xxxx')
|
||||||
|
>>> c1.str
|
||||||
|
>>> c1.str = 'yes'
|
||||||
|
>>> c1.str
|
||||||
|
'yes'
|
||||||
|
>>> del(c1)
|
||||||
|
>>> c2 = Config(o, persistent=True, session_id='xxxx')
|
||||||
|
>>> c2.str
|
||||||
|
'yes'
|
||||||
|
>>> del(c2)
|
||||||
|
>>> list_sessions()
|
||||||
|
['xxxx']
|
||||||
|
>>> delete_session('xxxx')
|
||||||
|
>>> c3 = Config(o, persistent=True, session_id='xxxx')
|
||||||
|
>>> c3.str
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
68
setup.py
68
setup.py
|
@ -1,53 +1,63 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from distutils.core import setup
|
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
|
from os import listdir
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
def fetch_version():
|
def fetch_version():
|
||||||
"""Get version from version.in or latest git tag"""
|
"""Get version from version.in"""
|
||||||
version_file='version.in'
|
return file('VERSION', 'r').readline().strip()
|
||||||
version = "1.0"
|
|
||||||
git_last_tag_cmd = ['git', 'describe', '--tags', '--abbrev=0']
|
|
||||||
|
|
||||||
try:
|
|
||||||
if os.path.isfile(version_file):
|
|
||||||
version=file(version_file).readline().strip()
|
|
||||||
elif os.path.isdir('.git'):
|
|
||||||
popen = subprocess.Popen(git_last_tag_cmd, stdout=subprocess.PIPE)
|
|
||||||
out, ret = popen.communicate()
|
|
||||||
for line in out.split('\n'):
|
|
||||||
if line:
|
|
||||||
version = line.lstrip('release/')
|
|
||||||
break
|
|
||||||
except OSError:
|
|
||||||
pass # Failing is fine, we just can't print the version then
|
|
||||||
|
|
||||||
return version
|
|
||||||
|
|
||||||
def return_storages():
|
def return_storages():
|
||||||
"returns all the storage plugins that are living in tiramisu/storage"
|
"returns all the storage plugins that are living in tiramisu/storage"
|
||||||
here = dirname(abspath(__file__))
|
here = dirname(abspath(__file__))
|
||||||
storages_path = normpath(join(here, 'tiramisu', 'storage'))
|
storages_path = normpath(join(here, 'tiramisu', 'storage'))
|
||||||
dir_content = [ content for content in listdir(storages_path) \
|
dir_content = [content for content in listdir(storages_path)
|
||||||
if not content =='__pycache__']
|
if not content == '__pycache__']
|
||||||
storages = filter(isdir, [join(storages_path, content) \
|
storages = filter(isdir, [join(storages_path, content)
|
||||||
for content in dir_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
|
return storage_list
|
||||||
|
|
||||||
|
|
||||||
packages = ['tiramisu', 'tiramisu.storage']
|
packages = ['tiramisu', 'tiramisu.storage']
|
||||||
packages.extend(return_storages())
|
packages.extend(return_storages())
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
author='cadoles team',
|
author="Tiramisu's team",
|
||||||
author_email='contact@cadoles.com',
|
author_email='contact@cadoles.com',
|
||||||
name='tiramisu',
|
name='tiramisu',
|
||||||
version=fetch_version(),
|
version=fetch_version(),
|
||||||
description='configuration management tool',
|
description='an options controller tool',
|
||||||
url='http://labs.libre-entreprise.org/projects/tiramisu',
|
url='http://tiramisu.labs.libre-entreprise.org/',
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 2",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Development Status :: 4 - Beta",
|
||||||
|
"Environment :: Other Environment",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Text Processing :: Linguistic"
|
||||||
|
],
|
||||||
|
long_description="""\
|
||||||
|
An options controller tool
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
Due to more and more available options required to set up an operating system,
|
||||||
|
compiler options or whatever, it became quite annoying to hand the necessary
|
||||||
|
options to where they are actually used and even more annoying to add new
|
||||||
|
options. To circumvent these problems the configuration control was
|
||||||
|
introduced...
|
||||||
|
|
||||||
|
Tiramisu is an options handler and an options controller, wich aims at
|
||||||
|
producing flexible and fast options access.
|
||||||
|
|
||||||
|
|
||||||
|
This version requires Python 2.6 or later.
|
||||||
|
""",
|
||||||
packages=packages
|
packages=packages
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,7 +4,7 @@ from tiramisu import setting
|
||||||
setting.expires_time = 1
|
setting.expires_time = 1
|
||||||
from tiramisu.option import IntOption, OptionDescription
|
from tiramisu.option import IntOption, OptionDescription
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from time import sleep
|
from time import sleep, time
|
||||||
|
|
||||||
|
|
||||||
def make_description():
|
def make_description():
|
||||||
|
@ -20,13 +20,38 @@ def test_cache():
|
||||||
values = c.cfgimpl_get_values()
|
values = c.cfgimpl_get_values()
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u2
|
c.u2
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
assert 'u2' in values._p_.get_cached('value', c)
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
assert 'u2' in settings._p_.get_cached('property', c)
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_cache():
|
||||||
|
# force a value in cache, try if reget corrupted value
|
||||||
|
od1 = make_description()
|
||||||
|
c = Config(od1)
|
||||||
|
values = c.cfgimpl_get_values()
|
||||||
|
settings = c.cfgimpl_get_settings()
|
||||||
|
ntime = time() + 1
|
||||||
|
settings._p_.setcache('u1', set(['inject']), ntime)
|
||||||
|
assert 'inject' in settings[od1.u1]
|
||||||
|
values._p_.setcache('u1', 100, ntime)
|
||||||
|
assert c.u1 == [100]
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_cache_no_expire():
|
||||||
|
# force a value in cache, try if reget corrupted value
|
||||||
|
od1 = make_description()
|
||||||
|
c = Config(od1)
|
||||||
|
values = c.cfgimpl_get_values()
|
||||||
|
settings = c.cfgimpl_get_settings()
|
||||||
|
settings._p_.setcache('u1', set(['inject2']), None)
|
||||||
|
assert 'inject2' in settings[od1.u1]
|
||||||
|
values._p_.setcache('u1', 200, None)
|
||||||
|
assert c.u1 == [200]
|
||||||
|
|
||||||
|
|
||||||
def test_cache_reset():
|
def test_cache_reset():
|
||||||
|
@ -36,44 +61,44 @@ def test_cache_reset():
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
#when change a value
|
#when change a value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u2 = 1
|
c.u2 = 1
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when remove a value
|
#when remove a value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
del(c.u2)
|
del(c.u2)
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when add/del property
|
#when add/del property
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_get_settings()[od1.u2].append('test')
|
c.cfgimpl_get_settings()[od1.u2].append('test')
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_get_settings()[od1.u2].remove('test')
|
c.cfgimpl_get_settings()[od1.u2].remove('test')
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when enable/disabled property
|
#when enable/disabled property
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_get_settings().append('test')
|
c.cfgimpl_get_settings().append('test')
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_get_settings().remove('test')
|
c.cfgimpl_get_settings().remove('test')
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
def test_cache_reset_multi():
|
def test_cache_reset_multi():
|
||||||
|
@ -83,32 +108,32 @@ def test_cache_reset_multi():
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
#when change a value
|
#when change a value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u3 = [1]
|
c.u3 = [1]
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when append value
|
#when append value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u3.append(1)
|
c.u3.append(1)
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when pop value
|
#when pop value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u3.pop(1)
|
c.u3.pop(1)
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
#when remove a value
|
#when remove a value
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
del(c.u3)
|
del(c.u3)
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
def test_reset_cache():
|
def test_reset_cache():
|
||||||
|
@ -117,23 +142,25 @@ def test_reset_cache():
|
||||||
values = c.cfgimpl_get_values()
|
values = c.cfgimpl_get_values()
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache()
|
c.cfgimpl_reset_cache()
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
|
c.u1
|
||||||
|
sleep(1)
|
||||||
c.u1
|
c.u1
|
||||||
sleep(1)
|
sleep(1)
|
||||||
c.u2
|
c.u2
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
assert 'u2' in values._p_.get_cached('value', c)
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
assert 'u2' in settings._p_.get_cached('property', c)
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache()
|
c.cfgimpl_reset_cache()
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
assert 'u2' not in values._p_.get_cached('value', c)
|
assert 'u2' not in values._p_.get_cached(c)
|
||||||
assert 'u2' not in settings._p_.get_cached('property', c)
|
assert 'u2' not in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
def test_reset_cache_subconfig():
|
def test_reset_cache_subconfig():
|
||||||
|
@ -142,9 +169,9 @@ def test_reset_cache_subconfig():
|
||||||
c = Config(od2)
|
c = Config(od2)
|
||||||
values = c.cfgimpl_get_values()
|
values = c.cfgimpl_get_values()
|
||||||
c.od1.u1
|
c.od1.u1
|
||||||
assert 'od1.u1' in values._p_.get_cached('value', c)
|
assert 'od1.u1' in values._p_.get_cached(c)
|
||||||
c.od1.cfgimpl_reset_cache()
|
c.od1.cfgimpl_reset_cache()
|
||||||
assert 'od1.u1' not in values._p_.get_cached('value', c)
|
assert 'od1.u1' not in values._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
def test_reset_cache_only_expired():
|
def test_reset_cache_only_expired():
|
||||||
|
@ -153,22 +180,60 @@ def test_reset_cache_only_expired():
|
||||||
values = c.cfgimpl_get_values()
|
values = c.cfgimpl_get_values()
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache(True)
|
c.cfgimpl_reset_cache(True)
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
|
sleep(1)
|
||||||
|
c.u1
|
||||||
sleep(1)
|
sleep(1)
|
||||||
c.u2
|
c.u2
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
assert 'u2' in values._p_.get_cached('value', c)
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
assert 'u2' in settings._p_.get_cached('property', c)
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache(True)
|
c.cfgimpl_reset_cache(True)
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
assert 'u2' in values._p_.get_cached('value', c)
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
assert 'u2' in settings._p_.get_cached('property', c)
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_not_expire():
|
||||||
|
od1 = make_description()
|
||||||
|
c = Config(od1)
|
||||||
|
values = c.cfgimpl_get_values()
|
||||||
|
settings = c.cfgimpl_get_settings()
|
||||||
|
settings.remove('expire')
|
||||||
|
c.u1
|
||||||
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
|
c.cfgimpl_reset_cache(True)
|
||||||
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
|
sleep(1)
|
||||||
|
c.u2
|
||||||
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
|
c.cfgimpl_reset_cache(True)
|
||||||
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
|
assert 'u2' in values._p_.get_cached(c)
|
||||||
|
assert 'u2' in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
|
def test_cache_not_cache():
|
||||||
|
od1 = make_description()
|
||||||
|
c = Config(od1)
|
||||||
|
values = c.cfgimpl_get_values()
|
||||||
|
settings = c.cfgimpl_get_settings()
|
||||||
|
settings.remove('cache')
|
||||||
|
c.u1
|
||||||
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
|
|
||||||
|
|
||||||
def test_reset_cache_only():
|
def test_reset_cache_only():
|
||||||
|
@ -177,14 +242,14 @@ def test_reset_cache_only():
|
||||||
values = c.cfgimpl_get_values()
|
values = c.cfgimpl_get_values()
|
||||||
settings = c.cfgimpl_get_settings()
|
settings = c.cfgimpl_get_settings()
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache(only=('values',))
|
c.cfgimpl_reset_cache(only=('values',))
|
||||||
assert 'u1' not in values._p_.get_cached('value', c)
|
assert 'u1' not in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.u1
|
c.u1
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' in settings._p_.get_cached('property', c)
|
assert 'u1' in settings._p_.get_cached(c)
|
||||||
c.cfgimpl_reset_cache(only=('settings',))
|
c.cfgimpl_reset_cache(only=('settings',))
|
||||||
assert 'u1' in values._p_.get_cached('value', c)
|
assert 'u1' in values._p_.get_cached(c)
|
||||||
assert 'u1' not in settings._p_.get_cached('property', c)
|
assert 'u1' not in settings._p_.get_cached(c)
|
||||||
|
|
|
@ -141,6 +141,7 @@ def test_information_config():
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
config.impl_set_information('info', string)
|
config.impl_set_information('info', string)
|
||||||
assert config.impl_get_information('info') == string
|
assert config.impl_get_information('info') == string
|
||||||
|
raises(ValueError, "config.impl_get_information('noinfo')")
|
||||||
|
|
||||||
|
|
||||||
def test_config_impl_get_path_by_opt():
|
def test_config_impl_get_path_by_opt():
|
||||||
|
|
|
@ -19,7 +19,6 @@ def make_description():
|
||||||
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
|
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
|
||||||
wantref_option = BoolOption('wantref', 'Tests', default=False)
|
wantref_option = BoolOption('wantref', 'Tests', default=False)
|
||||||
wantframework_option = BoolOption('wantframework', 'Test', default=False)
|
wantframework_option = BoolOption('wantframework', 'Test', default=False)
|
||||||
|
|
||||||
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
|
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
|
||||||
descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption,
|
descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption,
|
||||||
wantref_option, stroption,
|
wantref_option, stroption,
|
||||||
|
@ -117,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')
|
#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():
|
def test_does_not_find_in_config():
|
||||||
descr = make_description()
|
descr = make_description()
|
||||||
conf = Config(descr)
|
conf = Config(descr)
|
||||||
|
|
|
@ -29,6 +29,15 @@ def test_ip_default():
|
||||||
c.a == '88.88.88.88'
|
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():
|
def test_network():
|
||||||
a = NetworkOption('a', '')
|
a = NetworkOption('a', '')
|
||||||
od = OptionDescription('od', '', [a])
|
od = OptionDescription('od', '', [a])
|
||||||
|
|
|
@ -4,19 +4,27 @@ from py.test import raises
|
||||||
from tiramisu.setting import groups
|
from tiramisu.setting import groups
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
StrOption, OptionDescription
|
StrOption, OptionDescription, SymLinkOption
|
||||||
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError
|
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
|
||||||
|
|
||||||
|
|
||||||
def return_val():
|
def return_val():
|
||||||
return 'val'
|
return 'val'
|
||||||
|
|
||||||
|
|
||||||
def return_list():
|
def return_concat(*args):
|
||||||
|
return '.'.join(list(args))
|
||||||
|
|
||||||
|
|
||||||
|
def return_list(value=None):
|
||||||
return ['val', 'val']
|
return ['val', 'val']
|
||||||
|
|
||||||
|
|
||||||
def return_value(value):
|
def return_list2(*args):
|
||||||
|
return list(args)
|
||||||
|
|
||||||
|
|
||||||
|
def return_value(value=None):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@ -298,18 +306,73 @@ def test_callback():
|
||||||
|
|
||||||
def test_callback_value():
|
def test_callback_value():
|
||||||
val1 = StrOption('val1', "", 'val')
|
val1 = StrOption('val1', "", 'val')
|
||||||
val2 = StrOption('val2', "", callback=return_value, callback_params={'': (('val1', False),)})
|
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
|
||||||
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
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 = Config(maconfig)
|
||||||
cfg.read_write()
|
cfg.read_write()
|
||||||
assert cfg.val1 == 'val'
|
assert cfg.val1 == 'val'
|
||||||
assert cfg.val2 == 'val'
|
assert cfg.val2 == 'val'
|
||||||
|
assert cfg.val4 == 'val'
|
||||||
cfg.val1 = 'new-val'
|
cfg.val1 = 'new-val'
|
||||||
assert cfg.val1 == 'new-val'
|
assert cfg.val1 == 'new-val'
|
||||||
assert cfg.val2 == 'new-val'
|
assert cfg.val2 == 'new-val'
|
||||||
|
assert cfg.val4 == 'new-val'
|
||||||
del(cfg.val1)
|
del(cfg.val1)
|
||||||
assert cfg.val1 == 'val'
|
assert cfg.val1 == 'val'
|
||||||
assert cfg.val2 == '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():
|
def test_callback_list():
|
||||||
|
@ -336,21 +399,28 @@ def test_callback_multi():
|
||||||
|
|
||||||
def test_callback_multi_value():
|
def test_callback_multi_value():
|
||||||
val1 = StrOption('val1', "", ['val'], multi=True)
|
val1 = StrOption('val1', "", ['val'], multi=True)
|
||||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1', False),)})
|
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
|
||||||
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
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 = Config(maconfig)
|
||||||
cfg.read_write()
|
cfg.read_write()
|
||||||
assert cfg.val1 == ['val']
|
assert cfg.val1 == ['val']
|
||||||
assert cfg.val2 == ['val']
|
assert cfg.val2 == ['val']
|
||||||
|
assert cfg.val4 == ['val', 'yes']
|
||||||
cfg.val1 = ['new-val']
|
cfg.val1 = ['new-val']
|
||||||
assert cfg.val1 == ['new-val']
|
assert cfg.val1 == ['new-val']
|
||||||
assert cfg.val2 == ['new-val']
|
assert cfg.val2 == ['new-val']
|
||||||
|
assert cfg.val4 == ['new-val', 'yes']
|
||||||
cfg.val1.append('new-val2')
|
cfg.val1.append('new-val2')
|
||||||
assert cfg.val1 == ['new-val', 'new-val2']
|
assert cfg.val1 == ['new-val', 'new-val2']
|
||||||
assert cfg.val2 == ['new-val', 'new-val2']
|
assert cfg.val2 == ['new-val', 'new-val2']
|
||||||
|
assert cfg.val4 == ['new-val', 'yes', 'new-val2', 'yes']
|
||||||
del(cfg.val1)
|
del(cfg.val1)
|
||||||
assert cfg.val1 == ['val']
|
assert cfg.val1 == ['val']
|
||||||
assert cfg.val2 == ['val']
|
assert cfg.val2 == ['val']
|
||||||
|
assert cfg.val3 == ['yes']
|
||||||
|
assert cfg.val4 == ['val', 'yes']
|
||||||
|
|
||||||
|
|
||||||
def test_callback_multi_list():
|
def test_callback_multi_list():
|
||||||
|
@ -455,41 +525,67 @@ def test_callback_master_and_slaves_slave_list():
|
||||||
|
|
||||||
def test_callback_master_and_slaves_value():
|
def test_callback_master_and_slaves_value():
|
||||||
val1 = StrOption('val1', "", multi=True)
|
val1 = StrOption('val1', "", multi=True)
|
||||||
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1.val1', False),)})
|
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
|
||||||
interface1 = OptionDescription('val1', '', [val1, val2])
|
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)
|
interface1.impl_set_group_type(groups.master)
|
||||||
maconfig = OptionDescription('rootconfig', '', [interface1])
|
maconfig = OptionDescription('rootconfig', '', [interface1, val4])
|
||||||
cfg = Config(maconfig)
|
cfg = Config(maconfig)
|
||||||
cfg.read_write()
|
cfg.read_write()
|
||||||
assert cfg.val1.val1 == []
|
assert cfg.val1.val1 == []
|
||||||
assert cfg.val1.val2 == []
|
assert cfg.val1.val2 == []
|
||||||
|
assert cfg.val1.val3 == []
|
||||||
|
assert cfg.val1.val5 == []
|
||||||
#
|
#
|
||||||
cfg.val1.val1 = ['val1']
|
cfg.val1.val1 = ['val1']
|
||||||
assert cfg.val1.val1 == ['val1']
|
assert cfg.val1.val1 == ['val1']
|
||||||
assert cfg.val1.val2 == ['val1']
|
assert cfg.val1.val2 == ['val1']
|
||||||
|
assert cfg.val1.val3 == ['yes']
|
||||||
|
assert cfg.val1.val5 == ['val10']
|
||||||
#
|
#
|
||||||
cfg.val1.val1.append('val2')
|
cfg.val1.val1.append('val2')
|
||||||
assert cfg.val1.val1 == ['val1', 'val2']
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
assert cfg.val1.val2 == ['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']
|
cfg.val1.val1 = ['val1', 'val2', 'val3']
|
||||||
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
|
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
|
||||||
assert cfg.val1.val2 == ['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)
|
cfg.val1.val1.pop(2)
|
||||||
assert cfg.val1.val1 == ['val1', 'val2']
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
assert cfg.val1.val2 == ['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.val2 = ['val2', 'val2']
|
||||||
|
cfg.val1.val3 = ['val2', 'val2']
|
||||||
|
cfg.val1.val5 = ['val2', 'val2']
|
||||||
assert cfg.val1.val2 == ['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')
|
cfg.val1.val1.append('val3')
|
||||||
assert cfg.val1.val2 == ['val2', 'val2', '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():
|
def test_callback_hidden():
|
||||||
opt1 = BoolOption('opt1', '')
|
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',))
|
od1 = OptionDescription('od1', '', [opt1], properties=('hidden',))
|
||||||
od2 = OptionDescription('od2', '', [opt2])
|
od2 = OptionDescription('od2', '', [opt2])
|
||||||
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
maconfig = OptionDescription('rootconfig', '', [od1, od2])
|
||||||
|
@ -498,3 +594,84 @@ def test_callback_hidden():
|
||||||
cfg.read_write()
|
cfg.read_write()
|
||||||
raises(PropertiesOptionError, 'cfg.od1.opt1')
|
raises(PropertiesOptionError, 'cfg.od1.opt1')
|
||||||
cfg.od2.opt2
|
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']
|
||||||
|
|
|
@ -4,7 +4,7 @@ from py.test import raises
|
||||||
from tiramisu.setting import owners, groups
|
from tiramisu.setting import owners, groups
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
|
||||||
OptionDescription
|
SymLinkOption, OptionDescription
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_not_equal():
|
def test_consistency_not_equal():
|
||||||
|
@ -22,6 +22,16 @@ def test_consistency_not_equal():
|
||||||
c.b = 2
|
c.b = 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_not_equal_symlink():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '')
|
||||||
|
c = SymLinkOption('c', a)
|
||||||
|
od = OptionDescription('od', '', [a, b, c])
|
||||||
|
a.impl_add_consistency('not_equal', b)
|
||||||
|
c = Config(od)
|
||||||
|
assert set(od._consistencies.keys()) == set([a, b])
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_not_equal_multi():
|
def test_consistency_not_equal_multi():
|
||||||
a = IntOption('a', '', multi=True)
|
a = IntOption('a', '', multi=True)
|
||||||
b = IntOption('b', '', multi=True)
|
b = IntOption('b', '', multi=True)
|
||||||
|
|
|
@ -327,30 +327,29 @@ def test_reset_properties():
|
||||||
cfg = Config(descr)
|
cfg = Config(descr)
|
||||||
setting = cfg.cfgimpl_get_settings()
|
setting = cfg.cfgimpl_get_settings()
|
||||||
option = cfg.cfgimpl_get_description().gc.dummy
|
option = cfg.cfgimpl_get_description().gc.dummy
|
||||||
assert setting._p_.get_properties(cfg) == {}
|
assert setting._p_.get_modified_properties() == {}
|
||||||
setting.append('frozen')
|
setting.append('frozen')
|
||||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
|
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'cache', 'validator'))}
|
||||||
setting.reset()
|
setting.reset()
|
||||||
assert setting._p_.get_properties(cfg) == {}
|
assert setting._p_.get_modified_properties() == {}
|
||||||
setting[option].append('test')
|
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()
|
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')
|
setting.append('frozen')
|
||||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), 'gc.dummy': set(('test',))}
|
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'validator', 'cache')), 'gc.dummy': set(('test',))}
|
||||||
setting.reset(option)
|
setting.reset(option)
|
||||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
|
assert setting._p_.get_modified_properties() == {None: set(('frozen', 'expire', 'validator', 'cache'))}
|
||||||
setting[option].append('test')
|
setting[option].append('test')
|
||||||
assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), '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)
|
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)')
|
raises(ValueError, 'setting.reset(all_properties=True, opt=option)')
|
||||||
a = descr.wantref
|
a = descr.wantref
|
||||||
setting[a].append('test')
|
setting[a].append('test')
|
||||||
setting[a].reset()
|
setting[a].reset()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_reset_multiple():
|
def test_reset_multiple():
|
||||||
descr = make_description()
|
descr = make_description()
|
||||||
cfg = Config(descr)
|
cfg = Config(descr)
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
import autopath
|
||||||
|
from py.test import raises
|
||||||
|
|
||||||
|
from tiramisu.config import Config
|
||||||
|
from tiramisu.option import StrOption, OptionDescription
|
||||||
|
from tiramisu.error import ConfigError
|
||||||
|
|
||||||
|
|
||||||
|
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']:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def return_val(value, param=None):
|
||||||
|
return 'val'
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator():
|
||||||
|
opt1 = StrOption('opt1', '', validator=return_true, default='val')
|
||||||
|
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
|
||||||
|
raises(ConfigError, "StrOption('opt3', '', validator=return_val, default='val')")
|
||||||
|
opt2 = StrOption('opt2', '', validator=return_false)
|
||||||
|
opt3 = StrOption('opt3', '', validator=return_val)
|
||||||
|
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||||
|
cfg = Config(root)
|
||||||
|
assert cfg.opt1 == 'val'
|
||||||
|
raises(ValueError, "cfg.opt2 = 'val'")
|
||||||
|
raises(ConfigError, "cfg.opt3 = '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')")
|
||||||
|
raises(ConfigError, "StrOption('opt3', '', validator=return_val, validator_params={'': ('yes',)}, default='val')")
|
||||||
|
opt2 = StrOption('opt2', '', validator=return_false, validator_params={'': ('yes',)})
|
||||||
|
opt3 = StrOption('opt3', '', validator=return_val, validator_params={'': ('yes',)})
|
||||||
|
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||||
|
cfg = Config(root)
|
||||||
|
assert cfg.opt1 == 'val'
|
||||||
|
raises(ValueError, "cfg.opt2 = 'val'")
|
||||||
|
raises(ConfigError, "cfg.opt3 = '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')")
|
|
@ -114,7 +114,6 @@ def test_iter_not_group():
|
||||||
raises(TypeError, "list(config.iter_groups(group_type='family'))")
|
raises(TypeError, "list(config.iter_groups(group_type='family'))")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_groups_with_master():
|
def test_groups_with_master():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
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)
|
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 == []
|
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():
|
def test_values_with_master_owner():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
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)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||||
|
|
|
@ -88,6 +88,64 @@ def test_multiple_requires():
|
||||||
c.ip_address_service
|
c.ip_address_service
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_requires_cumulative():
|
||||||
|
a = StrOption('activate_service', '')
|
||||||
|
b = IPOption('ip_address_service', '',
|
||||||
|
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
|
||||||
|
{'option': a, 'expected': 'yes', 'action': 'hidden'}])
|
||||||
|
od = OptionDescription('service', '', [a, b])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.ip_address_service
|
||||||
|
c.activate_service = 'yes'
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
props = err.proptype
|
||||||
|
assert set(props) == set(['hidden', 'disabled'])
|
||||||
|
|
||||||
|
c.activate_service = 'ok'
|
||||||
|
c.ip_address_service
|
||||||
|
|
||||||
|
c.activate_service = 'no'
|
||||||
|
c.ip_address_service
|
||||||
|
|
||||||
|
|
||||||
|
def test_multiple_requires_cumulative_inverse():
|
||||||
|
a = StrOption('activate_service', '')
|
||||||
|
b = IPOption('ip_address_service', '',
|
||||||
|
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
|
||||||
|
{'option': a, 'expected': 'yes', 'action': 'hidden', 'inverse': True}])
|
||||||
|
od = OptionDescription('service', '', [a, b])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
props = err.proptype
|
||||||
|
assert set(props) == set(['hidden', 'disabled'])
|
||||||
|
c.activate_service = 'yes'
|
||||||
|
c.ip_address_service
|
||||||
|
|
||||||
|
c.activate_service = 'ok'
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
props = err.proptype
|
||||||
|
assert set(props) == set(['hidden', 'disabled'])
|
||||||
|
|
||||||
|
c.activate_service = 'no'
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
props = err.proptype
|
||||||
|
assert set(props) == set(['hidden', 'disabled'])
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_requires_inverse():
|
def test_multiple_requires_inverse():
|
||||||
a = StrOption('activate_service', '')
|
a = StrOption('activate_service', '')
|
||||||
b = IPOption('ip_address_service', '',
|
b = IPOption('ip_address_service', '',
|
||||||
|
@ -476,3 +534,9 @@ def test_set_item():
|
||||||
c = Config(od)
|
c = Config(od)
|
||||||
c.read_write()
|
c.read_write()
|
||||||
raises(ValueError, 'c.cfgimpl_get_settings()[a] = ("test",)')
|
raises(ValueError, 'c.cfgimpl_get_settings()[a] = ("test",)')
|
||||||
|
|
||||||
|
|
||||||
|
def test_properties_conflict():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
|
||||||
|
raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
|
||||||
|
|
|
@ -4,10 +4,13 @@ from py.test import raises
|
||||||
|
|
||||||
from tiramisu.config import Config, SubConfig
|
from tiramisu.config import Config, SubConfig
|
||||||
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
StrOption, OptionDescription, SymLinkOption, UnicodeOption
|
StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \
|
||||||
|
PortOption, NetworkOption, NetmaskOption, DomainnameOption
|
||||||
|
|
||||||
|
|
||||||
def test_slots_option():
|
def test_slots_option():
|
||||||
|
c = ChoiceOption('a', '', ('a',))
|
||||||
|
raises(AttributeError, "c.x = 1")
|
||||||
c = BoolOption('a', '')
|
c = BoolOption('a', '')
|
||||||
raises(AttributeError, "c.x = 1")
|
raises(AttributeError, "c.x = 1")
|
||||||
c = IntOption('a', '')
|
c = IntOption('a', '')
|
||||||
|
@ -20,10 +23,96 @@ def test_slots_option():
|
||||||
raises(AttributeError, "c.x = 1")
|
raises(AttributeError, "c.x = 1")
|
||||||
c = UnicodeOption('a', '')
|
c = UnicodeOption('a', '')
|
||||||
raises(AttributeError, "c.x = 1")
|
raises(AttributeError, "c.x = 1")
|
||||||
c = ChoiceOption('a', '', ('a',))
|
c = IPOption('a', '')
|
||||||
raises(AttributeError, "c.x = 1")
|
raises(AttributeError, "c.x = 1")
|
||||||
c = OptionDescription('a', '', [])
|
c = OptionDescription('a', '', [])
|
||||||
raises(AttributeError, "c.x = 1")
|
raises(AttributeError, "c.x = 1")
|
||||||
|
c = PortOption('a', '')
|
||||||
|
raises(AttributeError, "c.x = 1")
|
||||||
|
c = NetworkOption('a', '')
|
||||||
|
raises(AttributeError, "c.x = 1")
|
||||||
|
c = NetmaskOption('a', '')
|
||||||
|
raises(AttributeError, "c.x = 1")
|
||||||
|
c = DomainnameOption('a', '')
|
||||||
|
raises(AttributeError, "c.x = 1")
|
||||||
|
|
||||||
|
|
||||||
|
def test_slots_option_readonly():
|
||||||
|
a = ChoiceOption('a', '', ('a',))
|
||||||
|
b = BoolOption('b', '')
|
||||||
|
c = IntOption('c', '')
|
||||||
|
d = FloatOption('d', '')
|
||||||
|
e = StrOption('e', '')
|
||||||
|
g = UnicodeOption('g', '')
|
||||||
|
h = IPOption('h', '')
|
||||||
|
i = PortOption('i', '')
|
||||||
|
j = NetworkOption('j', '')
|
||||||
|
k = NetmaskOption('k', '')
|
||||||
|
l = DomainnameOption('l', '')
|
||||||
|
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l])
|
||||||
|
a._requires = 'a'
|
||||||
|
b._requires = 'b'
|
||||||
|
c._requires = 'c'
|
||||||
|
d._requires = 'd'
|
||||||
|
e._requires = 'e'
|
||||||
|
g._requires = 'g'
|
||||||
|
h._requires = 'h'
|
||||||
|
i._requires = 'i'
|
||||||
|
j._requires = 'j'
|
||||||
|
k._requires = 'k'
|
||||||
|
l._requires = 'l'
|
||||||
|
m._requires = 'm'
|
||||||
|
Config(m)
|
||||||
|
raises(AttributeError, "a._requires = 'a'")
|
||||||
|
raises(AttributeError, "b._requires = 'b'")
|
||||||
|
raises(AttributeError, "c._requires = 'c'")
|
||||||
|
raises(AttributeError, "d._requires = 'd'")
|
||||||
|
raises(AttributeError, "e._requires = 'e'")
|
||||||
|
raises(AttributeError, "g._requires = 'g'")
|
||||||
|
raises(AttributeError, "h._requires = 'h'")
|
||||||
|
raises(AttributeError, "i._requires = 'i'")
|
||||||
|
raises(AttributeError, "j._requires = 'j'")
|
||||||
|
raises(AttributeError, "k._requires = 'k'")
|
||||||
|
raises(AttributeError, "l._requires = 'l'")
|
||||||
|
raises(AttributeError, "m._requires = 'm'")
|
||||||
|
|
||||||
|
|
||||||
|
def test_slots_option_readonly_name():
|
||||||
|
a = ChoiceOption('a', '', ('a',))
|
||||||
|
b = BoolOption('b', '')
|
||||||
|
c = IntOption('c', '')
|
||||||
|
d = FloatOption('d', '')
|
||||||
|
e = StrOption('e', '')
|
||||||
|
f = SymLinkOption('f', c)
|
||||||
|
g = UnicodeOption('g', '')
|
||||||
|
h = IPOption('h', '')
|
||||||
|
i = PortOption('i', '')
|
||||||
|
j = NetworkOption('j', '')
|
||||||
|
k = NetmaskOption('k', '')
|
||||||
|
l = DomainnameOption('l', '')
|
||||||
|
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l])
|
||||||
|
raises(AttributeError, "a._name = 'a'")
|
||||||
|
raises(AttributeError, "b._name = 'b'")
|
||||||
|
raises(AttributeError, "c._name = 'c'")
|
||||||
|
raises(AttributeError, "d._name = 'd'")
|
||||||
|
raises(AttributeError, "e._name = 'e'")
|
||||||
|
raises(AttributeError, "f._name = 'f'")
|
||||||
|
raises(AttributeError, "g._name = 'g'")
|
||||||
|
raises(AttributeError, "h._name = 'h'")
|
||||||
|
raises(AttributeError, "i._name = 'i'")
|
||||||
|
raises(AttributeError, "j._name = 'j'")
|
||||||
|
raises(AttributeError, "k._name = 'k'")
|
||||||
|
raises(AttributeError, "l._name = 'l'")
|
||||||
|
raises(AttributeError, "m._name = 'm'")
|
||||||
|
|
||||||
|
|
||||||
|
def test_slots_description():
|
||||||
|
# __slots__ for OptionDescription should be complete for __getattr__
|
||||||
|
slots = set()
|
||||||
|
for subclass in OptionDescription.__mro__:
|
||||||
|
if subclass is not object:
|
||||||
|
slots.update(subclass.__slots__)
|
||||||
|
assert slots == set(OptionDescription.__slots__)
|
||||||
|
|
||||||
|
|
||||||
def test_slots_config():
|
def test_slots_config():
|
||||||
|
|
|
@ -0,0 +1,250 @@
|
||||||
|
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__:
|
||||||
|
if subclass is not object:
|
||||||
|
slots.update(subclass.__slots__)
|
||||||
|
return slots
|
||||||
|
|
||||||
|
|
||||||
|
def _no_state(opt):
|
||||||
|
for attr in _get_slots(opt):
|
||||||
|
if 'state' in attr:
|
||||||
|
try:
|
||||||
|
getattr(opt, attr)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise Exception('opt should have already attribute {0}'.format(attr))
|
||||||
|
|
||||||
|
|
||||||
|
def _diff_opt(opt1, opt2):
|
||||||
|
attr1 = set(_get_slots(opt1))
|
||||||
|
attr2 = set(_get_slots(opt2))
|
||||||
|
diff1 = attr1 - attr2
|
||||||
|
diff2 = attr2 - attr1
|
||||||
|
if diff1 != set():
|
||||||
|
raise Exception('more attribute in opt1 {0}'.format(list(diff1)))
|
||||||
|
if diff2 != set():
|
||||||
|
raise Exception('more attribute in opt2 {0}'.format(list(diff2)))
|
||||||
|
for attr in attr1:
|
||||||
|
if attr in ['_cache_paths']:
|
||||||
|
continue
|
||||||
|
err1 = False
|
||||||
|
err2 = False
|
||||||
|
val1 = None
|
||||||
|
val2 = None
|
||||||
|
try:
|
||||||
|
val1 = getattr(opt1, attr)
|
||||||
|
except:
|
||||||
|
err1 = True
|
||||||
|
|
||||||
|
try:
|
||||||
|
val2 = getattr(opt2, attr)
|
||||||
|
except:
|
||||||
|
err2 = True
|
||||||
|
assert err1 == err2
|
||||||
|
if val1 is None:
|
||||||
|
assert val1 == val2
|
||||||
|
elif attr == '_children':
|
||||||
|
assert val1[0] == val2[0]
|
||||||
|
for index, _opt in enumerate(val1[1]):
|
||||||
|
assert _opt._name == val2[1][index]._name
|
||||||
|
elif attr == '_requires':
|
||||||
|
assert val1[0][0][0]._name == val2[0][0][0]._name
|
||||||
|
assert val1[0][0][1:] == val2[0][0][1:]
|
||||||
|
elif attr == '_opt':
|
||||||
|
assert val1._name == val2._name
|
||||||
|
elif attr == '_consistencies':
|
||||||
|
# dict is only a cache
|
||||||
|
if isinstance(val1, list):
|
||||||
|
for index, consistency in enumerate(val1):
|
||||||
|
assert consistency[0] == val2[index][0]
|
||||||
|
assert consistency[1]._name == val2[index][1]._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
|
||||||
|
|
||||||
|
|
||||||
|
def test_diff_opt():
|
||||||
|
b = BoolOption('b', '')
|
||||||
|
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
|
||||||
|
#u.impl_add_consistency('not_equal', b)
|
||||||
|
s = SymLinkOption('s', u)
|
||||||
|
o = OptionDescription('o', '', [b, u, s])
|
||||||
|
o1 = OptionDescription('o1', '', [o])
|
||||||
|
|
||||||
|
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.u, q.o.u)
|
||||||
|
_diff_opt(o1.o.s, q.o.s)
|
||||||
|
|
||||||
|
|
||||||
|
def test_diff_opt_cache():
|
||||||
|
b = BoolOption('b', '')
|
||||||
|
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
|
||||||
|
u.impl_add_consistency('not_equal', b)
|
||||||
|
s = SymLinkOption('s', u)
|
||||||
|
o = OptionDescription('o', '', [b, u, s])
|
||||||
|
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.u, q.o.u)
|
||||||
|
_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', '')
|
||||||
|
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
|
||||||
|
s = SymLinkOption('s', u)
|
||||||
|
o = OptionDescription('o', '', [b, u, s])
|
||||||
|
o1 = OptionDescription('o1', '', [o])
|
||||||
|
|
||||||
|
a = dumps(o1)
|
||||||
|
q = loads(a)
|
||||||
|
_no_state(q)
|
||||||
|
_no_state(q.o)
|
||||||
|
_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
|
|
@ -5,7 +5,7 @@ import autopath
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import BoolOption, OptionDescription
|
from tiramisu.option import BoolOption, OptionDescription
|
||||||
from tiramisu.setting import owners
|
from tiramisu.setting import owners
|
||||||
from tiramisu.setting import list_sessions, delete_session
|
from tiramisu.storage import list_sessions, delete_session
|
||||||
|
|
||||||
|
|
||||||
def test_non_persistent():
|
def test_non_persistent():
|
||||||
|
@ -18,7 +18,7 @@ def test_list():
|
||||||
b = BoolOption('b', '')
|
b = BoolOption('b', '')
|
||||||
o = OptionDescription('od', '', [b])
|
o = OptionDescription('od', '', [b])
|
||||||
c = Config(o, session_id='test_non_persistent')
|
c = Config(o, session_id='test_non_persistent')
|
||||||
from tiramisu.setting import list_sessions
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
assert 'test_non_persistent' in list_sessions()
|
assert 'test_non_persistent' in list_sessions()
|
||||||
del(c)
|
del(c)
|
||||||
assert 'test_non_persistent' not in list_sessions()
|
assert 'test_non_persistent' not in list_sessions()
|
||||||
|
@ -43,7 +43,6 @@ def test_list_sessions_persistent():
|
||||||
# storage is not persistent
|
# storage is not persistent
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
from tiramisu.setting import list_sessions
|
|
||||||
assert 'test_persistent' in list_sessions()
|
assert 'test_persistent' in list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,6 +65,7 @@ def test_create_persistent_retrieve():
|
||||||
o = OptionDescription('od', '', [b])
|
o = OptionDescription('od', '', [b])
|
||||||
try:
|
try:
|
||||||
c = Config(o, session_id='test_persistent', persistent=True)
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# storage is not persistent
|
# storage is not persistent
|
||||||
pass
|
pass
|
||||||
|
@ -75,10 +75,12 @@ def test_create_persistent_retrieve():
|
||||||
assert c.b is True
|
assert c.b is True
|
||||||
del(c)
|
del(c)
|
||||||
c = Config(o, session_id='test_persistent', persistent=True)
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
assert c.b is True
|
assert c.b is True
|
||||||
assert 'test_persistent' in list_sessions()
|
assert 'test_persistent' in list_sessions()
|
||||||
delete_session('test_persistent')
|
delete_session('test_persistent')
|
||||||
c = Config(o, session_id='test_persistent', persistent=True)
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
assert c.b is None
|
assert c.b is None
|
||||||
delete_session('test_persistent')
|
delete_session('test_persistent')
|
||||||
|
|
||||||
|
@ -88,11 +90,13 @@ def test_two_persistent():
|
||||||
o = OptionDescription('od', '', [b])
|
o = OptionDescription('od', '', [b])
|
||||||
try:
|
try:
|
||||||
c = Config(o, session_id='test_persistent', persistent=True)
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# storage is not persistent
|
# storage is not persistent
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
c2 = Config(o, session_id='test_persistent', persistent=True)
|
c2 = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c2.cfgimpl_get_settings().remove('cache')
|
||||||
assert c.b is None
|
assert c.b is None
|
||||||
assert c2.b is None
|
assert c2.b is None
|
||||||
c.b = False
|
c.b = False
|
||||||
|
@ -109,11 +113,13 @@ def test_two_persistent_owner():
|
||||||
o = OptionDescription('od', '', [b])
|
o = OptionDescription('od', '', [b])
|
||||||
try:
|
try:
|
||||||
c = Config(o, session_id='test_persistent', persistent=True)
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# storage is not persistent
|
# storage is not persistent
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
c2 = Config(o, session_id='test_persistent', persistent=True)
|
c2 = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c2.cfgimpl_get_settings().remove('cache')
|
||||||
owners.addowner('persistent')
|
owners.addowner('persistent')
|
||||||
assert c.getowner(b) == owners.default
|
assert c.getowner(b) == owners.default
|
||||||
assert c2.getowner(b) == owners.default
|
assert c2.getowner(b) == owners.default
|
||||||
|
@ -124,3 +130,22 @@ def test_two_persistent_owner():
|
||||||
assert c.getowner(b) == owners.persistent
|
assert c.getowner(b) == owners.persistent
|
||||||
assert c2.getowner(b) == owners.persistent
|
assert c2.getowner(b) == owners.persistent
|
||||||
delete_session('test_persistent')
|
delete_session('test_persistent')
|
||||||
|
|
||||||
|
|
||||||
|
def test_two_persistent_information():
|
||||||
|
b = BoolOption('b', '')
|
||||||
|
o = OptionDescription('od', '', [b])
|
||||||
|
try:
|
||||||
|
c = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c.cfgimpl_get_settings().remove('cache')
|
||||||
|
except ValueError:
|
||||||
|
# storage is not persistent
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
c.impl_set_information('info', 'string')
|
||||||
|
assert c.impl_get_information('info') == 'string'
|
||||||
|
c2 = Config(o, session_id='test_persistent', persistent=True)
|
||||||
|
c2.cfgimpl_get_settings().remove('cache')
|
||||||
|
c2.cfgimpl_get_settings().remove('cache')
|
||||||
|
assert c2.impl_get_information('info') == 'string'
|
||||||
|
delete_session('test_persistent')
|
||||||
|
|
|
@ -23,11 +23,9 @@ from tiramisu.error import PropertiesOptionError, ConfigError
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
|
||||||
def carry_out_calculation(name,
|
|
||||||
config,
|
def carry_out_calculation(name, config, callback, callback_params,
|
||||||
callback,
|
index=None, max_len=None):
|
||||||
callback_params,
|
|
||||||
index=None):
|
|
||||||
"""a function that carries out a calculation for an option's value
|
"""a function that carries out a calculation for an option's value
|
||||||
|
|
||||||
:param name: the option name (`opt._name`)
|
:param name: the option name (`opt._name`)
|
||||||
|
@ -40,36 +38,104 @@ def carry_out_calculation(name,
|
||||||
:type callback_params: dict
|
:type callback_params: dict
|
||||||
:param index: if an option is multi, only calculates the nth value
|
:param index: if an option is multi, only calculates the nth value
|
||||||
:type index: int
|
:type index: int
|
||||||
|
:param max_len: max length for a multi
|
||||||
|
:type max_len: int
|
||||||
|
|
||||||
|
* 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]
|
||||||
|
callback_params={'': ((opt1, False), (opt2, False))}
|
||||||
|
=> 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]
|
||||||
|
callback_params={'': ((opt1, False), (opt2, False))}
|
||||||
|
=> ConfigError()
|
||||||
|
|
||||||
|
* 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.
|
||||||
"""
|
"""
|
||||||
#callback, callback_params = option.getcallback()
|
|
||||||
#if callback_params is None:
|
|
||||||
# callback_params = {}
|
|
||||||
tcparams = {}
|
tcparams = {}
|
||||||
one_is_multi = False
|
one_is_multi = False
|
||||||
len_multi = 0
|
len_multi = 0
|
||||||
|
|
||||||
for key, values in callback_params.items():
|
for key, callbacks in callback_params.items():
|
||||||
for value in values:
|
for callbk in callbacks:
|
||||||
if type(value) == tuple:
|
if isinstance(callbk, tuple):
|
||||||
path, check_disabled = value
|
option, force_permissive = callbk
|
||||||
if config is None:
|
# get value
|
||||||
if check_disabled:
|
|
||||||
continue
|
|
||||||
raise ConfigError(_('no config specified but needed'))
|
|
||||||
try:
|
try:
|
||||||
opt_value = config._getattr(path, force_permissive=True)
|
path = config.cfgimpl_get_description().impl_get_path_by_opt(option)
|
||||||
opt = config.unwrap_from_path(path, force_permissive=True)
|
value = config._getattr(path, force_permissive=True)
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
if check_disabled:
|
if force_permissive:
|
||||||
continue
|
continue
|
||||||
raise ConfigError(_('unable to carry out a calculation, '
|
raise ConfigError(_('unable to carry out a calculation, '
|
||||||
'option {0} has properties: {1} for: '
|
'option {0} has properties: {1} for: '
|
||||||
'{2}').format(path, err.proptype,
|
'{2}').format(option._name, err.proptype,
|
||||||
name))
|
name))
|
||||||
is_multi = opt.impl_is_multi()
|
is_multi = option.impl_is_multi()
|
||||||
if is_multi:
|
if is_multi:
|
||||||
if opt_value is not None:
|
if value is not None:
|
||||||
len_value = len(opt_value)
|
len_value = len(value)
|
||||||
if len_multi != 0 and len_multi != len_value:
|
if len_multi != 0 and len_multi != len_value:
|
||||||
raise ConfigError(_('unable to carry out a '
|
raise ConfigError(_('unable to carry out a '
|
||||||
'calculation, option value with'
|
'calculation, option value with'
|
||||||
|
@ -77,14 +143,21 @@ def carry_out_calculation(name,
|
||||||
'length for: {0}').format(name))
|
'length for: {0}').format(name))
|
||||||
len_multi = len_value
|
len_multi = len_value
|
||||||
one_is_multi = True
|
one_is_multi = True
|
||||||
tcparams.setdefault(key, []).append((opt_value, is_multi))
|
tcparams.setdefault(key, []).append((value, is_multi))
|
||||||
else:
|
else:
|
||||||
tcparams.setdefault(key, []).append((value, False))
|
tcparams.setdefault(key, []).append((callbk, False))
|
||||||
|
|
||||||
if one_is_multi:
|
if one_is_multi:
|
||||||
ret = []
|
ret = []
|
||||||
if index:
|
if index:
|
||||||
|
if index < len_multi:
|
||||||
range_ = [index]
|
range_ = [index]
|
||||||
|
else:
|
||||||
|
range_ = []
|
||||||
|
ret = None
|
||||||
|
else:
|
||||||
|
if max_len and max_len < len_multi:
|
||||||
|
range_ = range(max_len)
|
||||||
else:
|
else:
|
||||||
range_ = range(len_multi)
|
range_ = range(len_multi)
|
||||||
for incr in range_:
|
for incr in range_:
|
||||||
|
@ -97,15 +170,9 @@ def carry_out_calculation(name,
|
||||||
if key == '':
|
if key == '':
|
||||||
params.append(value[incr])
|
params.append(value[incr])
|
||||||
else:
|
else:
|
||||||
if len(value) > incr:
|
|
||||||
tcp[key] = value[incr]
|
tcp[key] = value[incr]
|
||||||
else:
|
else:
|
||||||
tcp[key] = ''
|
|
||||||
else:
|
|
||||||
if key == '':
|
|
||||||
params.append(value)
|
params.append(value)
|
||||||
else:
|
|
||||||
tcp[key] = value
|
|
||||||
calc = calculate(name, callback, params, tcp)
|
calc = calculate(name, callback, params, tcp)
|
||||||
if index:
|
if index:
|
||||||
ret = calc
|
ret = calc
|
||||||
|
@ -114,7 +181,6 @@ def carry_out_calculation(name,
|
||||||
ret.extend(calc)
|
ret.extend(calc)
|
||||||
else:
|
else:
|
||||||
ret.append(calc)
|
ret.append(calc)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
tcp = {}
|
tcp = {}
|
||||||
|
@ -130,7 +196,6 @@ def carry_out_calculation(name,
|
||||||
|
|
||||||
|
|
||||||
def calculate(name, callback, params, tcparams):
|
def calculate(name, callback, params, tcparams):
|
||||||
# FIXME we don't need the option's name down there.
|
|
||||||
"""wrapper that launches the 'callback'
|
"""wrapper that launches the 'callback'
|
||||||
|
|
||||||
:param callback: callback name
|
:param callback: callback name
|
||||||
|
|
|
@ -22,14 +22,15 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import weakref
|
import weakref
|
||||||
from tiramisu.error import PropertiesOptionError, ConfigError
|
from tiramisu.error import PropertiesOptionError, ConfigError
|
||||||
from tiramisu.option import OptionDescription, Option, SymLinkOption, \
|
from tiramisu.option import OptionDescription, Option, SymLinkOption
|
||||||
BaseInformation
|
from tiramisu.setting import groups, Settings, default_encoding
|
||||||
from tiramisu.setting import groups, Settings, default_encoding, get_storage
|
from tiramisu.storage import get_storages, get_storage, set_storage, \
|
||||||
from tiramisu.value import Values
|
_impl_getstate_setting
|
||||||
|
from tiramisu.value import Values, Multi
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
|
|
||||||
|
|
||||||
class SubConfig(BaseInformation):
|
class SubConfig(object):
|
||||||
"sub configuration management entry"
|
"sub configuration management entry"
|
||||||
__slots__ = ('_impl_context', '_impl_descr', '_impl_path')
|
__slots__ = ('_impl_context', '_impl_descr', '_impl_path')
|
||||||
|
|
||||||
|
@ -293,11 +294,12 @@ class SubConfig(BaseInformation):
|
||||||
return True
|
return True
|
||||||
try:
|
try:
|
||||||
value = getattr(self, path)
|
value = getattr(self, path)
|
||||||
if value == byvalue:
|
if isinstance(value, Multi):
|
||||||
return True
|
return byvalue in value
|
||||||
|
else:
|
||||||
|
return value == byvalue
|
||||||
except PropertiesOptionError: # a property is a restriction
|
except PropertiesOptionError: # a property is a restriction
|
||||||
# upon the access of the value
|
# upon the access of the value
|
||||||
pass
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _filter_by_type():
|
def _filter_by_type():
|
||||||
|
@ -323,15 +325,15 @@ class SubConfig(BaseInformation):
|
||||||
continue
|
continue
|
||||||
if not _filter_by_value():
|
if not _filter_by_value():
|
||||||
continue
|
continue
|
||||||
|
if not _filter_by_type():
|
||||||
|
continue
|
||||||
#remove option with propertyerror, ...
|
#remove option with propertyerror, ...
|
||||||
if check_properties:
|
if byvalue is None and check_properties:
|
||||||
try:
|
try:
|
||||||
value = getattr(self, path)
|
value = getattr(self, path)
|
||||||
except PropertiesOptionError:
|
except PropertiesOptionError:
|
||||||
# a property restricts the access of the value
|
# a property restricts the access of the value
|
||||||
continue
|
continue
|
||||||
if not _filter_by_type():
|
|
||||||
continue
|
|
||||||
if type_ == 'value':
|
if type_ == 'value':
|
||||||
retval = value
|
retval = value
|
||||||
elif type_ == 'path':
|
elif type_ == 'path':
|
||||||
|
@ -501,11 +503,27 @@ class CommonConfig(SubConfig):
|
||||||
def cfgimpl_get_meta(self):
|
def cfgimpl_get_meta(self):
|
||||||
return self._impl_meta
|
return self._impl_meta
|
||||||
|
|
||||||
|
# information
|
||||||
|
def impl_set_information(self, key, value):
|
||||||
|
"""updates the information's attribute
|
||||||
|
|
||||||
|
:param key: information's key (ex: "help", "doc"
|
||||||
|
:param value: information's value (ex: "the help string")
|
||||||
|
"""
|
||||||
|
self._impl_values.set_information(key, value)
|
||||||
|
|
||||||
|
def impl_get_information(self, key, default=None):
|
||||||
|
"""retrieves one information's item
|
||||||
|
|
||||||
|
:param key: the item string (ex: "help")
|
||||||
|
"""
|
||||||
|
return self._impl_values.get_information(key, default)
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
class Config(CommonConfig):
|
class Config(CommonConfig):
|
||||||
"main configuration management entry"
|
"main configuration management entry"
|
||||||
__slots__ = ('__weakref__', )
|
__slots__ = ('__weakref__', '_impl_test')
|
||||||
|
|
||||||
def __init__(self, descr, session_id=None, persistent=False):
|
def __init__(self, descr, session_id=None, persistent=False):
|
||||||
""" Configuration option management master class
|
""" Configuration option management master class
|
||||||
|
@ -520,13 +538,49 @@ class Config(CommonConfig):
|
||||||
:param persistent: if persistent, don't delete storage when leaving
|
:param persistent: if persistent, don't delete storage when leaving
|
||||||
:type persistent: `boolean`
|
:type persistent: `boolean`
|
||||||
"""
|
"""
|
||||||
storage = get_storage(self, session_id, persistent)
|
settings, values = get_storages(self, session_id, persistent)
|
||||||
self._impl_settings = Settings(self, storage)
|
self._impl_settings = Settings(self, settings)
|
||||||
self._impl_values = Values(self, storage)
|
self._impl_values = Values(self, values)
|
||||||
super(Config, self).__init__(descr, weakref.ref(self))
|
super(Config, self).__init__(descr, weakref.ref(self))
|
||||||
self._impl_build_all_paths()
|
self._impl_build_all_paths()
|
||||||
self._impl_meta = None
|
self._impl_meta = None
|
||||||
self._impl_informations = {}
|
#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,
|
def cfgimpl_reset_cache(self,
|
||||||
only_expired=False,
|
only_expired=False,
|
||||||
|
@ -561,11 +615,10 @@ class Config(CommonConfig):
|
||||||
# child._impl_meta = self
|
# child._impl_meta = self
|
||||||
|
|
||||||
# self._impl_children = children
|
# self._impl_children = children
|
||||||
# storage = get_storage(self, session_id, persistent)
|
# settings, values = get_storages(self, session_id, persistent)
|
||||||
# self._impl_settings = Settings(self, storage)
|
# self._impl_settings = Settings(self, settings)
|
||||||
# self._impl_values = Values(self, storage)
|
# self._impl_values = Values(self, values)
|
||||||
# self._impl_meta = None
|
# self._impl_meta = None
|
||||||
# self._impl_informations = {}
|
|
||||||
|
|
||||||
# def cfgimpl_get_children(self):
|
# def cfgimpl_get_children(self):
|
||||||
# return self._impl_children
|
# return self._impl_children
|
||||||
|
|
|
@ -26,7 +26,7 @@ from copy import copy, deepcopy
|
||||||
from types import FunctionType
|
from types import FunctionType
|
||||||
from IPy import IP
|
from IPy import IP
|
||||||
|
|
||||||
from tiramisu.error import ConflictError
|
from tiramisu.error import ConflictError, ConfigError
|
||||||
from tiramisu.setting import groups, multitypes
|
from tiramisu.setting import groups, multitypes
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu.autolib import carry_out_calculation
|
from tiramisu.autolib import carry_out_calculation
|
||||||
|
@ -54,10 +54,78 @@ def valid_name(name):
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class BaseInformation(object):
|
class BaseOption(object):
|
||||||
"interface for an option's information attribute"
|
"""This abstract base class stands for attribute access
|
||||||
__slots__ = ('_impl_informations',)
|
in options that have to be set only once, it is of course done in the
|
||||||
|
__setattr__ method
|
||||||
|
"""
|
||||||
|
__slots__ = ('_name', '_requires', '_properties', '_readonly',
|
||||||
|
'_consistencies', '_calc_properties', '_impl_informations',
|
||||||
|
'_state_consistencies', '_state_readonly', '_state_requires',
|
||||||
|
'_stated')
|
||||||
|
|
||||||
|
def __init__(self, name, doc, requires, properties):
|
||||||
|
if not valid_name(name):
|
||||||
|
raise ValueError(_("invalid name: {0} for option").format(name))
|
||||||
|
self._name = name
|
||||||
|
self._impl_informations = {}
|
||||||
|
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):
|
||||||
|
raise TypeError(_('invalid properties type {0} for {1},'
|
||||||
|
' must be a tuple').format(
|
||||||
|
type(properties),
|
||||||
|
self._name))
|
||||||
|
if self._calc_properties is not None and properties is not tuple():
|
||||||
|
set_forbidden_properties = set(properties) & self._calc_properties
|
||||||
|
if set_forbidden_properties != frozenset():
|
||||||
|
raise ValueError('conflict: properties already set in '
|
||||||
|
'requirement {0}'.format(
|
||||||
|
list(set_forbidden_properties)))
|
||||||
|
self._properties = properties # 'hidden', 'disabled'...
|
||||||
|
|
||||||
|
def __setattr__(self, name, value):
|
||||||
|
"""set once and only once some attributes in the option,
|
||||||
|
like `_name`. `_name` cannot be changed one the option and
|
||||||
|
pushed in the :class:`tiramisu.option.OptionDescription`.
|
||||||
|
|
||||||
|
if the attribute `_readonly` is set to `True`, the option is
|
||||||
|
"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'):
|
||||||
|
is_readonly = False
|
||||||
|
# never change _name
|
||||||
|
if name == '_name':
|
||||||
|
try:
|
||||||
|
self._name
|
||||||
|
#so _name is already set
|
||||||
|
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
|
||||||
|
if is_readonly:
|
||||||
|
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||||
|
" read-only").format(
|
||||||
|
self.__class__.__name__,
|
||||||
|
self._name,
|
||||||
|
name))
|
||||||
|
object.__setattr__(self, name, value)
|
||||||
|
|
||||||
|
# information
|
||||||
def impl_set_information(self, key, value):
|
def impl_set_information(self, key, value):
|
||||||
"""updates the information's attribute
|
"""updates the information's attribute
|
||||||
(which is a dictionary)
|
(which is a dictionary)
|
||||||
|
@ -65,47 +133,206 @@ class BaseInformation(object):
|
||||||
:param key: information's key (ex: "help", "doc"
|
:param key: information's key (ex: "help", "doc"
|
||||||
:param value: information's value (ex: "the help string")
|
:param value: information's value (ex: "the help string")
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
self._impl_informations[key] = value
|
self._impl_informations[key] = value
|
||||||
except AttributeError:
|
|
||||||
raise AttributeError(_('{0} has no attribute '
|
|
||||||
'impl_set_information').format(
|
|
||||||
self.__class__.__name__))
|
|
||||||
|
|
||||||
def impl_get_information(self, key, default=None):
|
def impl_get_information(self, key, default=None):
|
||||||
"""retrieves one information's item
|
"""retrieves one information's item
|
||||||
|
|
||||||
:param key: the item string (ex: "help")
|
:param key: the item string (ex: "help")
|
||||||
"""
|
"""
|
||||||
try:
|
|
||||||
if key in self._impl_informations:
|
if key in self._impl_informations:
|
||||||
return self._impl_informations[key]
|
return self._impl_informations[key]
|
||||||
elif default is not None:
|
elif default is not None:
|
||||||
return default
|
return default
|
||||||
else:
|
else:
|
||||||
raise ValueError(_("Information's item"
|
raise ValueError(_("information's item not found: {0}").format(
|
||||||
"not found: {0}").format(key))
|
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
|
||||||
|
|
||||||
|
: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._requires is None:
|
||||||
|
self._state_requires = None
|
||||||
|
elif load and self._state_requires is None:
|
||||||
|
self._requires = None
|
||||||
|
del(self._state_requires)
|
||||||
|
else:
|
||||||
|
if load:
|
||||||
|
_requires = self._state_requires
|
||||||
|
else:
|
||||||
|
_requires = self._requires
|
||||||
|
new_value = []
|
||||||
|
for requires in _requires:
|
||||||
|
new_requires = []
|
||||||
|
for require in requires:
|
||||||
|
if load:
|
||||||
|
new_require = [descr.impl_get_opt_by_path(require[0])]
|
||||||
|
else:
|
||||||
|
new_require = [descr.impl_get_path_by_opt(require[0])]
|
||||||
|
new_require.extend(require[1:])
|
||||||
|
new_requires.append(tuple(new_require))
|
||||||
|
new_value.append(tuple(new_requires))
|
||||||
|
if load:
|
||||||
|
del(self._state_requires)
|
||||||
|
self._requires = new_value
|
||||||
|
else:
|
||||||
|
self._state_requires = new_value
|
||||||
|
|
||||||
|
# serialize
|
||||||
|
def _impl_getstate(self, descr):
|
||||||
|
"""the under the hood stuff that need to be done
|
||||||
|
before the serialization.
|
||||||
|
|
||||||
|
:param descr: the parent :class:`tiramisu.option.OptionDescription`
|
||||||
|
"""
|
||||||
|
self._stated = True
|
||||||
|
for func in dir(self):
|
||||||
|
if func.startswith('_impl_convert_'):
|
||||||
|
getattr(self, func)(descr)
|
||||||
|
try:
|
||||||
|
self._state_readonly = self._readonly
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AttributeError(_('{0} has no attribute '
|
pass
|
||||||
'impl_get_information').format(
|
|
||||||
self.__class__.__name__))
|
def __getstate__(self, stated=True):
|
||||||
|
"""special method to enable the serialization with pickle
|
||||||
|
Usualy, a `__getstate__` method does'nt need any parameter,
|
||||||
|
but somme under the hood stuff need to be done before this action
|
||||||
|
|
||||||
|
:parameter stated: if stated is `True`, the serialization protocol
|
||||||
|
can be performed, not ready yet otherwise
|
||||||
|
:parameter type: bool
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self._stated
|
||||||
|
except AttributeError:
|
||||||
|
raise SystemError(_('cannot serialize Option, '
|
||||||
|
'only in OptionDescription'))
|
||||||
|
slots = set()
|
||||||
|
for subclass in self.__class__.__mro__:
|
||||||
|
if subclass is not object:
|
||||||
|
slots.update(subclass.__slots__)
|
||||||
|
slots -= frozenset(['_cache_paths', '__weakref__'])
|
||||||
|
states = {}
|
||||||
|
for slot in slots:
|
||||||
|
# remove variable if save variable converted
|
||||||
|
# in _state_xxxx variable
|
||||||
|
if '_state' + slot not in slots:
|
||||||
|
if slot.startswith('_state'):
|
||||||
|
# should exists
|
||||||
|
states[slot] = getattr(self, slot)
|
||||||
|
# remove _state_xxx variable
|
||||||
|
self.__delattr__(slot)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
states[slot] = getattr(self, slot)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if not stated:
|
||||||
|
del(states['_stated'])
|
||||||
|
return states
|
||||||
|
|
||||||
|
# unserialize
|
||||||
|
def _impl_setstate(self, descr):
|
||||||
|
"""the under the hood stuff that need to be done
|
||||||
|
before the serialization.
|
||||||
|
|
||||||
|
:type descr: :class:`tiramisu.option.OptionDescription`
|
||||||
|
"""
|
||||||
|
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)
|
||||||
|
del(self._stated)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __setstate__(self, state):
|
||||||
|
"""special method that enables us to serialize (pickle)
|
||||||
|
|
||||||
|
Usualy, a `__setstate__` method does'nt need any parameter,
|
||||||
|
but somme under the hood stuff need to be done before this action
|
||||||
|
|
||||||
|
:parameter state: a dict is passed to the loads, it is the attributes
|
||||||
|
of the options object
|
||||||
|
:type state: dict
|
||||||
|
"""
|
||||||
|
for key, value in state.items():
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
|
||||||
class Option(BaseInformation):
|
class Option(BaseOption):
|
||||||
"""
|
"""
|
||||||
Abstract base class for configuration option's.
|
Abstract base class for configuration option's.
|
||||||
|
|
||||||
Reminder: an Option object is **not** a container for the value
|
Reminder: an Option object is **not** a container for the value.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name', '_requires', '_multi', '_validator',
|
__slots__ = ('_multi', '_validator', '_default_multi', '_default',
|
||||||
'_default_multi', '_default', '_properties', '_callback',
|
'_state_callback', '_callback', '_multitype',
|
||||||
'_multitype', '_master_slaves', '_consistencies',
|
'_master_slaves', '__weakref__')
|
||||||
'_calc_properties', '__weakref__')
|
|
||||||
_empty = ''
|
_empty = ''
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=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):
|
properties=None):
|
||||||
"""
|
"""
|
||||||
:param name: the option's name
|
:param name: the option's name
|
||||||
|
@ -120,26 +347,17 @@ class Option(BaseInformation):
|
||||||
:param callback: the name of a function. If set, the function's output
|
:param callback: the name of a function. If set, the function's output
|
||||||
is responsible of the option's value
|
is responsible of the option's value
|
||||||
:param callback_params: the callback's parameter
|
:param callback_params: the callback's parameter
|
||||||
:param validator: the name of a function wich stands for a custom
|
:param validator: the name of a function which stands for a custom
|
||||||
validation of the value
|
validation of the value
|
||||||
:param validator_args: the validator's parameters
|
:param validator_params: the validator's parameters
|
||||||
|
:param properties: tuple of default properties
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not valid_name(name):
|
super(Option, self).__init__(name, doc, requires, properties)
|
||||||
raise ValueError(_("invalid name: {0} for option").format(name))
|
|
||||||
self._name = name
|
|
||||||
self._impl_informations = {}
|
|
||||||
self.impl_set_information('doc', doc)
|
|
||||||
self._calc_properties, self._requires = validate_requires_arg(
|
|
||||||
requires, self._name)
|
|
||||||
self._multi = multi
|
self._multi = multi
|
||||||
self._consistencies = None
|
|
||||||
if validator is not None:
|
if validator is not None:
|
||||||
if type(validator) != FunctionType:
|
validate_callback(validator, validator_params, 'validator')
|
||||||
raise TypeError(_("validator must be a function"))
|
self._validator = (validator, validator_params)
|
||||||
if validator_args is None:
|
|
||||||
validator_args = {}
|
|
||||||
self._validator = (validator, validator_args)
|
|
||||||
else:
|
else:
|
||||||
self._validator = None
|
self._validator = None
|
||||||
if not self._multi and default_multi is not None:
|
if not self._multi and default_multi is not None:
|
||||||
|
@ -161,11 +379,7 @@ class Option(BaseInformation):
|
||||||
"no callback defined"
|
"no callback defined"
|
||||||
" yet for option {0}").format(name))
|
" yet for option {0}").format(name))
|
||||||
if callback is not None:
|
if callback is not None:
|
||||||
if type(callback) != FunctionType:
|
validate_callback(callback, callback_params, 'callback')
|
||||||
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')
|
|
||||||
self._callback = (callback, callback_params)
|
self._callback = (callback, callback_params)
|
||||||
else:
|
else:
|
||||||
self._callback = None
|
self._callback = None
|
||||||
|
@ -176,14 +390,6 @@ class Option(BaseInformation):
|
||||||
self._default_multi = default_multi
|
self._default_multi = default_multi
|
||||||
self.impl_validate(default)
|
self.impl_validate(default)
|
||||||
self._default = default
|
self._default = default
|
||||||
if properties is None:
|
|
||||||
properties = tuple()
|
|
||||||
if not isinstance(properties, tuple):
|
|
||||||
raise TypeError(_('invalid properties type {0} for {1},'
|
|
||||||
' must be a tuple').format(
|
|
||||||
type(properties),
|
|
||||||
self._name))
|
|
||||||
self._properties = properties # 'hidden', 'disabled'...
|
|
||||||
|
|
||||||
def _launch_consistency(self, func, opt, vals, context, index, opt_):
|
def _launch_consistency(self, func, opt, vals, context, index, opt_):
|
||||||
if context is not None:
|
if context is not None:
|
||||||
|
@ -240,11 +446,23 @@ class Option(BaseInformation):
|
||||||
|
|
||||||
def val_validator(val):
|
def val_validator(val):
|
||||||
if self._validator is not None:
|
if self._validator is not None:
|
||||||
callback_params = deepcopy(self._validator[1])
|
if self._validator[1] is not None:
|
||||||
callback_params.setdefault('', []).insert(0, val)
|
validator_params = deepcopy(self._validator[1])
|
||||||
return carry_out_calculation(self._name, config=context,
|
if '' in validator_params:
|
||||||
|
lst = list(validator_params[''])
|
||||||
|
lst.insert(0, val)
|
||||||
|
validator_params[''] = tuple(lst)
|
||||||
|
else:
|
||||||
|
validator_params[''] = (val,)
|
||||||
|
else:
|
||||||
|
validator_params = {'': (val,)}
|
||||||
|
ret = carry_out_calculation(self._name, config=context,
|
||||||
callback=self._validator[0],
|
callback=self._validator[0],
|
||||||
callback_params=callback_params)
|
callback_params=validator_params)
|
||||||
|
if ret not in [False, True]:
|
||||||
|
raise ConfigError(_('validator should return a boolean, '
|
||||||
|
'not {0}').format(ret))
|
||||||
|
return ret
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -345,6 +563,40 @@ class Option(BaseInformation):
|
||||||
"must be different as {2} option"
|
"must be different as {2} option"
|
||||||
"").format(value, self._name, optname))
|
"").format(value, self._name, optname))
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class ChoiceOption(Option):
|
class ChoiceOption(Option):
|
||||||
"""represents a choice out of several objects.
|
"""represents a choice out of several objects.
|
||||||
|
@ -358,7 +610,7 @@ class ChoiceOption(Option):
|
||||||
def __init__(self, name, doc, values, default=None, default_multi=None,
|
def __init__(self, name, doc, values, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=None,
|
requires=None, multi=False, callback=None,
|
||||||
callback_params=None, open_values=False, validator=None,
|
callback_params=None, open_values=False, validator=None,
|
||||||
validator_args=None, properties=()):
|
validator_params=None, properties=()):
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
"""
|
"""
|
||||||
|
@ -376,7 +628,7 @@ class ChoiceOption(Option):
|
||||||
requires=requires,
|
requires=requires,
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_args=validator_args,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties)
|
||||||
|
|
||||||
def impl_get_values(self):
|
def impl_get_values(self):
|
||||||
|
@ -450,10 +702,11 @@ else:
|
||||||
raise ValueError(_('value must be an unicode'))
|
raise ValueError(_('value must be an unicode'))
|
||||||
|
|
||||||
|
|
||||||
class SymLinkOption(object):
|
class SymLinkOption(BaseOption):
|
||||||
__slots__ = ('_name', '_opt')
|
__slots__ = ('_name', '_opt', '_state_opt')
|
||||||
_opt_type = 'symlink'
|
_opt_type = 'symlink'
|
||||||
_consistencies = None
|
#not return _opt consistencies
|
||||||
|
_consistencies = {}
|
||||||
|
|
||||||
def __init__(self, name, opt):
|
def __init__(self, name, opt):
|
||||||
self._name = name
|
self._name = name
|
||||||
|
@ -462,24 +715,41 @@ class SymLinkOption(object):
|
||||||
'must be an option '
|
'must be an option '
|
||||||
'for symlink {0}').format(name))
|
'for symlink {0}').format(name))
|
||||||
self._opt = opt
|
self._opt = opt
|
||||||
|
self._readonly = True
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in ('_name', '_opt', '_consistencies'):
|
if name in ('_name', '_opt', '_opt_type', '_readonly'):
|
||||||
return object.__getattr__(self, name)
|
return object.__getattr__(self, name)
|
||||||
else:
|
else:
|
||||||
return getattr(self._opt, name)
|
return getattr(self._opt, name)
|
||||||
|
|
||||||
|
def _impl_getstate(self, descr):
|
||||||
|
super(SymLinkOption, self)._impl_getstate(descr)
|
||||||
|
self._state_opt = descr.impl_get_path_by_opt(self._opt)
|
||||||
|
|
||||||
|
def _impl_setstate(self, descr):
|
||||||
|
self._opt = descr.impl_get_opt_by_path(self._state_opt)
|
||||||
|
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):
|
class IPOption(Option):
|
||||||
"represents the choice of an ip"
|
"represents the choice of an ip"
|
||||||
__slots__ = ('_only_private',)
|
__slots__ = ('_only_private', '_allow_reserved')
|
||||||
_opt_type = 'ip'
|
_opt_type = 'ip'
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=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, only_private=False):
|
properties=None, only_private=False, allow_reserved=False):
|
||||||
self._only_private = only_private
|
self._only_private = only_private
|
||||||
|
self._allow_reserved = allow_reserved
|
||||||
super(IPOption, self).__init__(name, doc, default=default,
|
super(IPOption, self).__init__(name, doc, default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
callback=callback,
|
||||||
|
@ -487,12 +757,12 @@ class IPOption(Option):
|
||||||
requires=requires,
|
requires=requires,
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_args=validator_args,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
ip = IP('{0}/32'.format(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"))
|
raise ValueError(_("IP mustn't not be in reserved class"))
|
||||||
if self._only_private and not ip.iptype() == 'PRIVATE':
|
if self._only_private and not ip.iptype() == 'PRIVATE':
|
||||||
raise ValueError(_("IP must be in private class"))
|
raise ValueError(_("IP must be in private class"))
|
||||||
|
@ -513,7 +783,7 @@ class PortOption(Option):
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=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,
|
properties=None, allow_range=False, allow_zero=False,
|
||||||
allow_wellknown=True, allow_registred=True,
|
allow_wellknown=True, allow_registred=True,
|
||||||
allow_private=False):
|
allow_private=False):
|
||||||
|
@ -547,7 +817,7 @@ class PortOption(Option):
|
||||||
requires=requires,
|
requires=requires,
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_args=validator_args,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
|
@ -575,7 +845,7 @@ class NetworkOption(Option):
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
ip = IP(value)
|
ip = IP(value)
|
||||||
if ip.iptype() == 'RESERVED':
|
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):
|
class NetmaskOption(Option):
|
||||||
|
@ -632,7 +902,7 @@ class DomainnameOption(Option):
|
||||||
|
|
||||||
def __init__(self, name, doc, default=None, default_multi=None,
|
def __init__(self, name, doc, default=None, default_multi=None,
|
||||||
requires=None, multi=False, callback=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_ip=False, type_='domainname'):
|
properties=None, allow_ip=False, type_='domainname'):
|
||||||
#netbios: for MS domain
|
#netbios: for MS domain
|
||||||
#hostname: to identify the device
|
#hostname: to identify the device
|
||||||
|
@ -651,7 +921,7 @@ class DomainnameOption(Option):
|
||||||
requires=requires,
|
requires=requires,
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validator=validator,
|
||||||
validator_args=validator_args,
|
validator_params=validator_params,
|
||||||
properties=properties)
|
properties=properties)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
|
@ -674,7 +944,7 @@ class DomainnameOption(Option):
|
||||||
raise ValueError(_("invalid value for {0}, must have dot"
|
raise ValueError(_("invalid value for {0}, must have dot"
|
||||||
"").format(self._name))
|
"").format(self._name))
|
||||||
if len(value) > length:
|
if len(value) > length:
|
||||||
raise ValueError(_("invalid domainname's length for "
|
raise ValueError(_("invalid domainname's length for"
|
||||||
" {0} (max {1})").format(self._name, length))
|
" {0} (max {1})").format(self._name, length))
|
||||||
if len(value) == 1:
|
if len(value) == 1:
|
||||||
raise ValueError(_("invalid domainname's length for {0} (min 2)"
|
raise ValueError(_("invalid domainname's length for {0} (min 2)"
|
||||||
|
@ -684,25 +954,23 @@ class DomainnameOption(Option):
|
||||||
raise ValueError(_('invalid domainname'))
|
raise ValueError(_('invalid domainname'))
|
||||||
|
|
||||||
|
|
||||||
class OptionDescription(BaseInformation):
|
class OptionDescription(BaseOption):
|
||||||
"""Config's schema (organisation, group) and container of Options
|
"""Config's schema (organisation, group) and container of Options
|
||||||
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
|
__slots__ = ('_name', '_requires', '_cache_paths', '_group_type',
|
||||||
'_properties', '_children', '_consistencies',
|
'_state_group_type', '_properties', '_children',
|
||||||
'_calc_properties', '__weakref__')
|
'_consistencies', '_calc_properties', '__weakref__',
|
||||||
|
'_readonly', '_impl_informations', '_state_requires',
|
||||||
|
'_state_consistencies', '_stated', '_state_readonly')
|
||||||
|
_opt_type = 'optiondescription'
|
||||||
|
|
||||||
def __init__(self, name, doc, children, requires=None, properties=None):
|
def __init__(self, name, doc, children, requires=None, properties=None):
|
||||||
"""
|
"""
|
||||||
:param children: a list of options (including optiondescriptions)
|
:param children: a list of options (including optiondescriptions)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not valid_name(name):
|
super(OptionDescription, self).__init__(name, doc, requires, properties)
|
||||||
raise ValueError(_("invalid name: "
|
|
||||||
" {0} for optiondescription").format(name))
|
|
||||||
self._name = name
|
|
||||||
self._impl_informations = {}
|
|
||||||
self.impl_set_information('doc', doc)
|
|
||||||
child_names = [child._name for child in children]
|
child_names = [child._name for child in children]
|
||||||
#better performance like this
|
#better performance like this
|
||||||
valid_child = copy(child_names)
|
valid_child = copy(child_names)
|
||||||
|
@ -714,16 +982,7 @@ class OptionDescription(BaseInformation):
|
||||||
'{0}').format(child))
|
'{0}').format(child))
|
||||||
old = child
|
old = child
|
||||||
self._children = (tuple(child_names), tuple(children))
|
self._children = (tuple(child_names), tuple(children))
|
||||||
self._calc_properties, self._requires = validate_requires_arg(requires, self._name)
|
|
||||||
self._cache_paths = None
|
self._cache_paths = None
|
||||||
self._consistencies = None
|
|
||||||
if properties is None:
|
|
||||||
properties = tuple()
|
|
||||||
if not isinstance(properties, tuple):
|
|
||||||
raise TypeError(_('invalid properties type {0} for {1},'
|
|
||||||
' must be a tuple').format(type(properties),
|
|
||||||
self._name))
|
|
||||||
self._properties = properties # 'hidden', 'disabled'...
|
|
||||||
# the group_type is useful for filtering OptionDescriptions in a config
|
# the group_type is useful for filtering OptionDescriptions in a config
|
||||||
self._group_type = groups.default
|
self._group_type = groups.default
|
||||||
|
|
||||||
|
@ -731,6 +990,8 @@ class OptionDescription(BaseInformation):
|
||||||
return self.impl_get_information('doc')
|
return self.impl_get_information('doc')
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
|
if name in self.__slots__:
|
||||||
|
return object.__getattribute__(self, name)
|
||||||
try:
|
try:
|
||||||
return self._children[1][self._children[0].index(name)]
|
return self._children[1][self._children[0].index(name)]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
@ -767,12 +1028,15 @@ class OptionDescription(BaseInformation):
|
||||||
cache_path=None,
|
cache_path=None,
|
||||||
cache_option=None,
|
cache_option=None,
|
||||||
_currpath=None,
|
_currpath=None,
|
||||||
_consistencies=None):
|
_consistencies=None,
|
||||||
|
force_no_consistencies=False):
|
||||||
if _currpath is None and self._cache_paths is not None:
|
if _currpath is None and self._cache_paths is not None:
|
||||||
|
# cache already set
|
||||||
return
|
return
|
||||||
if _currpath is None:
|
if _currpath is None:
|
||||||
save = True
|
save = True
|
||||||
_currpath = []
|
_currpath = []
|
||||||
|
if not force_no_consistencies:
|
||||||
_consistencies = {}
|
_consistencies = {}
|
||||||
else:
|
else:
|
||||||
save = False
|
save = False
|
||||||
|
@ -781,15 +1045,16 @@ class OptionDescription(BaseInformation):
|
||||||
cache_option = []
|
cache_option = []
|
||||||
for option in self.impl_getchildren():
|
for option in self.impl_getchildren():
|
||||||
attr = option._name
|
attr = option._name
|
||||||
if attr.startswith('_cfgimpl'):
|
|
||||||
continue
|
|
||||||
if option in cache_option:
|
if option in cache_option:
|
||||||
raise ConflictError(_('duplicate option: {0}').format(option))
|
raise ConflictError(_('duplicate option: {0}').format(option))
|
||||||
|
|
||||||
cache_option.append(option)
|
cache_option.append(option)
|
||||||
|
if not force_no_consistencies:
|
||||||
|
option._readonly = True
|
||||||
cache_path.append(str('.'.join(_currpath + [attr])))
|
cache_path.append(str('.'.join(_currpath + [attr])))
|
||||||
if not isinstance(option, OptionDescription):
|
if not isinstance(option, OptionDescription):
|
||||||
if option._consistencies is not None:
|
if not force_no_consistencies and \
|
||||||
|
option._consistencies is not None:
|
||||||
for consistency in option._consistencies:
|
for consistency in option._consistencies:
|
||||||
func, opt = consistency
|
func, opt = consistency
|
||||||
opts = (option, opt)
|
opts = (option, opt)
|
||||||
|
@ -802,11 +1067,14 @@ class OptionDescription(BaseInformation):
|
||||||
option.impl_build_cache(cache_path,
|
option.impl_build_cache(cache_path,
|
||||||
cache_option,
|
cache_option,
|
||||||
_currpath,
|
_currpath,
|
||||||
_consistencies)
|
_consistencies,
|
||||||
|
force_no_consistencies)
|
||||||
_currpath.pop()
|
_currpath.pop()
|
||||||
if save:
|
if save:
|
||||||
self._cache_paths = (tuple(cache_option), tuple(cache_path))
|
self._cache_paths = (tuple(cache_option), tuple(cache_path))
|
||||||
|
if not force_no_consistencies:
|
||||||
self._consistencies = _consistencies
|
self._consistencies = _consistencies
|
||||||
|
self._readonly = True
|
||||||
|
|
||||||
def impl_get_opt_by_path(self, path):
|
def impl_get_opt_by_path(self, path):
|
||||||
try:
|
try:
|
||||||
|
@ -870,7 +1138,7 @@ class OptionDescription(BaseInformation):
|
||||||
raise ValueError(_("no child has same nom has master group"
|
raise ValueError(_("no child has same nom has master group"
|
||||||
" for: {0}").format(self._name))
|
" for: {0}").format(self._name))
|
||||||
else:
|
else:
|
||||||
raise ValueError(_('group_type : {0}'
|
raise ValueError(_('group_type: {0}'
|
||||||
' not allowed').format(group_type))
|
' not allowed').format(group_type))
|
||||||
|
|
||||||
def impl_get_group_type(self):
|
def impl_get_group_type(self):
|
||||||
|
@ -891,6 +1159,56 @@ class OptionDescription(BaseInformation):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _impl_getstate(self, descr=None):
|
||||||
|
"""enables us to export into a dict
|
||||||
|
:param descr: parent :class:`tiramisu.option.OptionDescription`
|
||||||
|
"""
|
||||||
|
if descr is None:
|
||||||
|
self.impl_build_cache()
|
||||||
|
descr = self
|
||||||
|
super(OptionDescription, self)._impl_getstate(descr)
|
||||||
|
self._state_group_type = str(self._group_type)
|
||||||
|
for option in self.impl_getchildren():
|
||||||
|
option._impl_getstate(descr)
|
||||||
|
|
||||||
|
def __getstate__(self):
|
||||||
|
"""special method to enable the serialization with pickle
|
||||||
|
"""
|
||||||
|
stated = True
|
||||||
|
try:
|
||||||
|
# the `_state` attribute is a flag that which tells us if
|
||||||
|
# the serialization can be performed
|
||||||
|
self._stated
|
||||||
|
except AttributeError:
|
||||||
|
# if cannot delete, _impl_getstate never launch
|
||||||
|
# launch it recursivement
|
||||||
|
# _stated prevent __getstate__ launch more than one time
|
||||||
|
# _stated is delete, if re-serialize, re-lauch _impl_getstate
|
||||||
|
self._impl_getstate()
|
||||||
|
stated = False
|
||||||
|
return super(OptionDescription, self).__getstate__(stated)
|
||||||
|
|
||||||
|
def _impl_setstate(self, descr=None):
|
||||||
|
"""enables us to import from a dict
|
||||||
|
:param descr: parent :class:`tiramisu.option.OptionDescription`
|
||||||
|
"""
|
||||||
|
if descr is None:
|
||||||
|
self._cache_paths = None
|
||||||
|
self.impl_build_cache(force_no_consistencies=True)
|
||||||
|
descr = self
|
||||||
|
self._group_type = getattr(groups, self._state_group_type)
|
||||||
|
del(self._state_group_type)
|
||||||
|
super(OptionDescription, self)._impl_setstate(descr)
|
||||||
|
for option in self.impl_getchildren():
|
||||||
|
option._impl_setstate(descr)
|
||||||
|
|
||||||
|
def __setstate__(self, state):
|
||||||
|
super(OptionDescription, self).__setstate__(state)
|
||||||
|
try:
|
||||||
|
self._stated
|
||||||
|
except AttributeError:
|
||||||
|
self._impl_setstate()
|
||||||
|
|
||||||
|
|
||||||
def validate_requires_arg(requires, name):
|
def validate_requires_arg(requires, name):
|
||||||
"""check malformed requirements
|
"""check malformed requirements
|
||||||
|
@ -906,6 +1224,8 @@ def validate_requires_arg(requires, name):
|
||||||
ret_requires = {}
|
ret_requires = {}
|
||||||
config_action = {}
|
config_action = {}
|
||||||
|
|
||||||
|
# start parsing all requires given by user (has dict)
|
||||||
|
# transforme it to a tuple
|
||||||
for require in requires:
|
for require in requires:
|
||||||
if not type(require) == dict:
|
if not type(require) == dict:
|
||||||
raise ValueError(_("malformed requirements type for option:"
|
raise ValueError(_("malformed requirements type for option:"
|
||||||
|
@ -919,6 +1239,7 @@ def validate_requires_arg(requires, name):
|
||||||
'{2}'.format(name,
|
'{2}'.format(name,
|
||||||
unknown_keys,
|
unknown_keys,
|
||||||
valid_keys))
|
valid_keys))
|
||||||
|
# prepare all attributes
|
||||||
try:
|
try:
|
||||||
option = require['option']
|
option = require['option']
|
||||||
expected = require['expected']
|
expected = require['expected']
|
||||||
|
@ -967,12 +1288,43 @@ def validate_requires_arg(requires, name):
|
||||||
inverse, transitive, same_action)
|
inverse, transitive, same_action)
|
||||||
else:
|
else:
|
||||||
ret_requires[action][option][1].append(expected)
|
ret_requires[action][option][1].append(expected)
|
||||||
|
# transform dict to tuple
|
||||||
ret = []
|
ret = []
|
||||||
for opt_requires in ret_requires.values():
|
for opt_requires in ret_requires.values():
|
||||||
ret_action = []
|
ret_action = []
|
||||||
for require in opt_requires.values():
|
for require in opt_requires.values():
|
||||||
req = (require[0], tuple(require[1]), require[2], require[3],
|
ret_action.append((require[0], tuple(require[1]), require[2],
|
||||||
require[4], require[5])
|
require[3], require[4], require[5]))
|
||||||
ret_action.append(req)
|
|
||||||
ret.append(tuple(ret_action))
|
ret.append(tuple(ret_action))
|
||||||
return frozenset(config_action.keys()), tuple(ret)
|
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)))
|
||||||
|
|
|
@ -24,43 +24,92 @@ from time import time
|
||||||
from copy import copy
|
from copy import copy
|
||||||
import weakref
|
import weakref
|
||||||
from tiramisu.error import (RequirementError, PropertiesOptionError,
|
from tiramisu.error import (RequirementError, PropertiesOptionError,
|
||||||
ConstError, ConfigError)
|
ConstError)
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
"Default encoding for display a Config if raise UnicodeEncodeError"
|
||||||
default_encoding = 'utf-8'
|
default_encoding = 'utf-8'
|
||||||
|
|
||||||
|
"""If cache and expire is enable, time before cache is expired.
|
||||||
|
This delay start first time value/setting is set in cache, even if
|
||||||
|
user access several time to value/setting
|
||||||
|
"""
|
||||||
expires_time = 5
|
expires_time = 5
|
||||||
ro_remove = ('permissive', 'hidden')
|
"""List of default properties (you can add new one if needed).
|
||||||
ro_append = ('frozen', 'disabled', 'validator', 'everything_frozen',
|
|
||||||
'mandatory')
|
For common properties and personalise properties, if a propery is set for
|
||||||
rw_remove = ('permissive', 'everything_frozen', 'mandatory')
|
an Option and for the Config together, Setting raise a PropertiesOptionError
|
||||||
rw_append = ('frozen', 'disabled', 'validator', 'hidden')
|
|
||||||
default_properties = ('expire', 'validator')
|
* Common properties:
|
||||||
|
|
||||||
|
hidden
|
||||||
|
option with this property can only get value in read only mode. This
|
||||||
|
option is not available in read write mode.
|
||||||
|
|
||||||
|
disabled
|
||||||
|
option with this property cannot be set/get
|
||||||
|
|
||||||
|
frozen
|
||||||
|
cannot set value for option with this properties if 'frozen' is set in
|
||||||
|
config
|
||||||
|
|
||||||
|
mandatory
|
||||||
|
should set value for option with this properties if 'mandatory' is set in
|
||||||
|
config
|
||||||
|
|
||||||
|
|
||||||
class StorageType:
|
* Special property:
|
||||||
default_storage = 'dictionary'
|
|
||||||
storage_type = None
|
|
||||||
|
|
||||||
def set_storage(self, name):
|
permissive
|
||||||
if self.storage_type is not None:
|
option with 'permissive' cannot raise PropertiesOptionError for properties
|
||||||
raise ConfigError(_('storage_type is already set, cannot rebind it'))
|
set in permissive
|
||||||
self.storage_type = name
|
config with 'permissive', whole option in this config cannot raise
|
||||||
|
PropertiesOptionError for properties set in permissive
|
||||||
|
|
||||||
def get_storage(self):
|
* Special Config properties:
|
||||||
if self.storage_type is None:
|
|
||||||
self.storage_type = self.default_storage
|
cache
|
||||||
storage = self.storage_type
|
if set, enable cache settings and values
|
||||||
return 'tiramisu.storage.{0}.storage'.format(
|
|
||||||
storage)
|
expire
|
||||||
|
if set, settings and values in cache expire after ``expires_time``
|
||||||
|
|
||||||
|
everything_frozen
|
||||||
|
whole option in config are frozen (even if option have not frozen
|
||||||
|
property)
|
||||||
|
|
||||||
|
validator
|
||||||
|
launch validator set by user in option (this property has no effect
|
||||||
|
for internal validator)
|
||||||
|
"""
|
||||||
|
default_properties = ('cache', 'expire', 'validator')
|
||||||
|
|
||||||
|
"""Config can be in two defaut mode:
|
||||||
|
|
||||||
|
read_only
|
||||||
|
you can get all variables not disabled but you cannot set any variables
|
||||||
|
if a value has a callback without any value, callback is launch and value
|
||||||
|
of this variable can change
|
||||||
|
you cannot access to mandatory variable without values
|
||||||
|
|
||||||
|
read_write
|
||||||
|
you can get all variables not disabled and not hidden
|
||||||
|
you can set all variables not frozen
|
||||||
|
"""
|
||||||
|
ro_append = set(['frozen', 'disabled', 'validator', 'everything_frozen',
|
||||||
|
'mandatory'])
|
||||||
|
ro_remove = set(['permissive', 'hidden'])
|
||||||
|
rw_append = set(['frozen', 'disabled', 'validator', 'hidden'])
|
||||||
|
rw_remove = set(['permissive', 'everything_frozen', 'mandatory'])
|
||||||
|
|
||||||
|
|
||||||
storage_type = StorageType()
|
# ____________________________________________________________
|
||||||
|
class _NameSpace(object):
|
||||||
|
|
||||||
class _NameSpace:
|
|
||||||
"""convenient class that emulates a module
|
"""convenient class that emulates a module
|
||||||
and builds constants (that is, unique names)"""
|
and builds constants (that is, unique names)
|
||||||
|
when attribute is added, we cannot delete it
|
||||||
|
"""
|
||||||
|
|
||||||
def __setattr__(self, name, value):
|
def __setattr__(self, name, value):
|
||||||
if name in self.__dict__:
|
if name in self.__dict__:
|
||||||
|
@ -73,7 +122,6 @@ class _NameSpace:
|
||||||
raise ValueError(name)
|
raise ValueError(name)
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
|
||||||
class GroupModule(_NameSpace):
|
class GroupModule(_NameSpace):
|
||||||
"emulates a module to manage unique group (OptionDescription) names"
|
"emulates a module to manage unique group (OptionDescription) names"
|
||||||
class GroupType(str):
|
class GroupType(str):
|
||||||
|
@ -91,21 +139,8 @@ class GroupModule(_NameSpace):
|
||||||
*master* means : groups that have the 'master' attribute set
|
*master* means : groups that have the 'master' attribute set
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
# setting.groups (emulates a module)
|
|
||||||
groups = GroupModule()
|
|
||||||
|
|
||||||
|
|
||||||
def populate_groups():
|
|
||||||
"populates the available groups in the appropriate namespaces"
|
|
||||||
groups.master = groups.MasterGroupType('master')
|
|
||||||
groups.default = groups.DefaultGroupType('default')
|
|
||||||
groups.family = groups.GroupType('family')
|
|
||||||
|
|
||||||
# names are in the module now
|
|
||||||
populate_groups()
|
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
|
||||||
class OwnerModule(_NameSpace):
|
class OwnerModule(_NameSpace):
|
||||||
"""emulates a module to manage unique owner names.
|
"""emulates a module to manage unique owner names.
|
||||||
|
|
||||||
|
@ -119,28 +154,6 @@ class OwnerModule(_NameSpace):
|
||||||
class DefaultOwner(Owner):
|
class DefaultOwner(Owner):
|
||||||
"""groups that are default (typically 'default')"""
|
"""groups that are default (typically 'default')"""
|
||||||
pass
|
pass
|
||||||
# setting.owners (emulates a module)
|
|
||||||
owners = OwnerModule()
|
|
||||||
|
|
||||||
|
|
||||||
def populate_owners():
|
|
||||||
"""populates the available owners in the appropriate namespaces
|
|
||||||
|
|
||||||
- 'user' is the generic is the generic owner.
|
|
||||||
- 'default' is the config owner after init time
|
|
||||||
"""
|
|
||||||
setattr(owners, 'default', owners.DefaultOwner('default'))
|
|
||||||
setattr(owners, 'user', owners.Owner('user'))
|
|
||||||
|
|
||||||
def addowner(name):
|
|
||||||
"""
|
|
||||||
:param name: the name of the new owner
|
|
||||||
"""
|
|
||||||
setattr(owners, name, owners.Owner(name))
|
|
||||||
setattr(owners, 'addowner', addowner)
|
|
||||||
|
|
||||||
# names are in the module now
|
|
||||||
populate_owners()
|
|
||||||
|
|
||||||
|
|
||||||
class MultiTypeModule(_NameSpace):
|
class MultiTypeModule(_NameSpace):
|
||||||
|
@ -157,18 +170,79 @@ class MultiTypeModule(_NameSpace):
|
||||||
class SlaveMultiType(MultiType):
|
class SlaveMultiType(MultiType):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
multitypes = MultiTypeModule()
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
def populate_groups():
|
||||||
|
"""populates the available groups in the appropriate namespaces
|
||||||
|
|
||||||
|
groups.default
|
||||||
|
default group set when creating a new optiondescription
|
||||||
|
|
||||||
|
groups.master
|
||||||
|
master group is a special optiondescription, all suboptions should be
|
||||||
|
multi option and all values should have same length, to find master's
|
||||||
|
option, the optiondescription's name should be same than de master's
|
||||||
|
option
|
||||||
|
|
||||||
|
groups.family
|
||||||
|
example of group, no special behavior with this group's type
|
||||||
|
"""
|
||||||
|
groups.default = groups.DefaultGroupType('default')
|
||||||
|
groups.master = groups.MasterGroupType('master')
|
||||||
|
groups.family = groups.GroupType('family')
|
||||||
|
|
||||||
|
|
||||||
|
def populate_owners():
|
||||||
|
"""populates the available owners in the appropriate namespaces
|
||||||
|
|
||||||
|
default
|
||||||
|
is the config owner after init time
|
||||||
|
|
||||||
|
user
|
||||||
|
is the generic is the generic owner
|
||||||
|
"""
|
||||||
|
setattr(owners, 'default', owners.DefaultOwner('default'))
|
||||||
|
setattr(owners, 'user', owners.Owner('user'))
|
||||||
|
|
||||||
|
def addowner(name):
|
||||||
|
"""
|
||||||
|
:param name: the name of the new owner
|
||||||
|
"""
|
||||||
|
setattr(owners, name, owners.Owner(name))
|
||||||
|
setattr(owners, 'addowner', addowner)
|
||||||
|
|
||||||
|
|
||||||
def populate_multitypes():
|
def populate_multitypes():
|
||||||
"populates the master/slave namespace"
|
"""all multi option should have a type, this type is automaticly set do
|
||||||
|
not touch this
|
||||||
|
|
||||||
|
default
|
||||||
|
default's multi option set if not master or slave
|
||||||
|
|
||||||
|
master
|
||||||
|
master's option in a group with master's type, name of this option
|
||||||
|
should be the same name of the optiondescription
|
||||||
|
|
||||||
|
slave
|
||||||
|
slave's option in a group with master's type
|
||||||
|
|
||||||
|
"""
|
||||||
setattr(multitypes, 'default', multitypes.DefaultMultiType('default'))
|
setattr(multitypes, 'default', multitypes.DefaultMultiType('default'))
|
||||||
setattr(multitypes, 'master', multitypes.MasterMultiType('master'))
|
setattr(multitypes, 'master', multitypes.MasterMultiType('master'))
|
||||||
setattr(multitypes, 'slave', multitypes.SlaveMultiType('slave'))
|
setattr(multitypes, 'slave', multitypes.SlaveMultiType('slave'))
|
||||||
|
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
|
# populate groups, owners and multitypes with default attributes
|
||||||
|
groups = GroupModule()
|
||||||
|
populate_groups()
|
||||||
|
owners = OwnerModule()
|
||||||
|
populate_owners()
|
||||||
|
multitypes = MultiTypeModule()
|
||||||
populate_multitypes()
|
populate_multitypes()
|
||||||
|
|
||||||
|
|
||||||
|
# ____________________________________________________________
|
||||||
class Property(object):
|
class Property(object):
|
||||||
"a property is responsible of the option's value access rules"
|
"a property is responsible of the option's value access rules"
|
||||||
__slots__ = ('_setting', '_properties', '_opt', '_path')
|
__slots__ = ('_setting', '_properties', '_opt', '_path')
|
||||||
|
@ -191,7 +265,8 @@ class Property(object):
|
||||||
def remove(self, propname):
|
def remove(self, propname):
|
||||||
if propname in self._properties:
|
if propname in self._properties:
|
||||||
self._properties.remove(propname)
|
self._properties.remove(propname)
|
||||||
self._setting._setproperties(self._properties, self._opt, self._path)
|
self._setting._setproperties(self._properties, self._opt,
|
||||||
|
self._path)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self._setting.reset(_path=self._path)
|
self._setting.reset(_path=self._path)
|
||||||
|
@ -203,39 +278,6 @@ class Property(object):
|
||||||
return str(list(self._properties))
|
return str(list(self._properties))
|
||||||
|
|
||||||
|
|
||||||
def set_storage(name, **args):
|
|
||||||
storage_type.set_storage(name)
|
|
||||||
settings = __import__(storage_type.get_storage(), globals(), locals(),
|
|
||||||
['Setting']).Setting()
|
|
||||||
for option, value in args.items():
|
|
||||||
try:
|
|
||||||
getattr(settings, option)
|
|
||||||
setattr(settings, option, value)
|
|
||||||
except AttributeError:
|
|
||||||
raise ValueError(_('option {0} not already exists in storage {1}'
|
|
||||||
'').format(option, name))
|
|
||||||
|
|
||||||
|
|
||||||
def get_storage(context, session_id, persistent):
|
|
||||||
def gen_id(config):
|
|
||||||
return str(id(config)) + str(time())
|
|
||||||
|
|
||||||
if session_id is None:
|
|
||||||
session_id = gen_id(context)
|
|
||||||
return __import__(storage_type.get_storage(), globals(), locals(),
|
|
||||||
['Storage']).Storage(session_id, persistent)
|
|
||||||
|
|
||||||
|
|
||||||
def list_sessions():
|
|
||||||
return __import__(storage_type.get_storage(), globals(), locals(),
|
|
||||||
['list_sessions']).list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def delete_session(session_id):
|
|
||||||
return __import__(storage_type.get_storage(), globals(), locals(),
|
|
||||||
['delete_session']).delete_session(session_id)
|
|
||||||
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
class Settings(object):
|
class Settings(object):
|
||||||
"``Config()``'s configuration options"
|
"``Config()``'s configuration options"
|
||||||
|
@ -254,9 +296,7 @@ class Settings(object):
|
||||||
# generic owner
|
# generic owner
|
||||||
self._owner = owners.user
|
self._owner = owners.user
|
||||||
self.context = weakref.ref(context)
|
self.context = weakref.ref(context)
|
||||||
import_lib = 'tiramisu.storage.{0}.setting'.format(storage.storage)
|
self._p_ = storage
|
||||||
self._p_ = __import__(import_lib, globals(), locals(), ['Settings']
|
|
||||||
).Settings(storage)
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# properties methods
|
# properties methods
|
||||||
|
@ -268,7 +308,7 @@ class Settings(object):
|
||||||
return str(list(self._getproperties()))
|
return str(list(self._getproperties()))
|
||||||
|
|
||||||
def __getitem__(self, opt):
|
def __getitem__(self, opt):
|
||||||
path = self._get_opt_path(opt)
|
path = self._get_path_by_opt(opt)
|
||||||
return self._getitem(opt, path)
|
return self._getitem(opt, path)
|
||||||
|
|
||||||
def _getitem(self, opt, path):
|
def _getitem(self, opt, path):
|
||||||
|
@ -285,7 +325,7 @@ class Settings(object):
|
||||||
self._p_.reset_all_propertives()
|
self._p_.reset_all_propertives()
|
||||||
else:
|
else:
|
||||||
if opt is not None and _path is None:
|
if opt is not None and _path is None:
|
||||||
_path = self._get_opt_path(opt)
|
_path = self._get_path_by_opt(opt)
|
||||||
self._p_.reset_properties(_path)
|
self._p_.reset_properties(_path)
|
||||||
self.context().cfgimpl_reset_cache()
|
self.context().cfgimpl_reset_cache()
|
||||||
|
|
||||||
|
@ -297,18 +337,21 @@ class Settings(object):
|
||||||
raise ValueError(_('if opt is not None, path should not be'
|
raise ValueError(_('if opt is not None, path should not be'
|
||||||
' None in _getproperties'))
|
' None in _getproperties'))
|
||||||
ntime = None
|
ntime = None
|
||||||
if self._p_.hascache('property', path):
|
if 'cache' in self and self._p_.hascache(path):
|
||||||
ntime = time()
|
if 'expire' in self:
|
||||||
is_cached, props = self._p_.getcache('property', path, ntime)
|
ntime = int(time())
|
||||||
|
is_cached, props = self._p_.getcache(path, ntime)
|
||||||
if is_cached:
|
if is_cached:
|
||||||
return props
|
return props
|
||||||
props = self._p_.getproperties(path, opt._properties)
|
props = self._p_.getproperties(path, opt._properties)
|
||||||
if is_apply_req:
|
if is_apply_req:
|
||||||
props |= self.apply_requires(opt, path)
|
props |= self.apply_requires(opt, path)
|
||||||
|
if 'cache' in self:
|
||||||
if 'expire' in self:
|
if 'expire' in self:
|
||||||
if ntime is None:
|
if ntime is None:
|
||||||
ntime = time()
|
ntime = int(time())
|
||||||
self._p_.setcache('property', path, props, ntime + expires_time)
|
ntime = ntime + expires_time
|
||||||
|
self._p_.setcache(path, props, ntime)
|
||||||
return props
|
return props
|
||||||
|
|
||||||
def append(self, propname):
|
def append(self, propname):
|
||||||
|
@ -342,13 +385,17 @@ class Settings(object):
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
|
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
|
||||||
value=None, force_permissive=False,
|
value=None, force_permissive=False,
|
||||||
force_properties=None):
|
force_properties=None, force_permissives=None):
|
||||||
"""
|
"""
|
||||||
validation upon the properties related to `opt_or_descr`
|
validation upon the properties related to `opt_or_descr`
|
||||||
|
|
||||||
:param opt_or_descr: an option or an option description object
|
:param opt_or_descr: an option or an option description object
|
||||||
:param force_permissive: behaves as if the permissive property
|
:param force_permissive: behaves as if the permissive property
|
||||||
was present
|
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,
|
:param is_descr: we have to know if we are in an option description,
|
||||||
just because the mandatory property
|
just because the mandatory property
|
||||||
doesn't exist here
|
doesn't exist here
|
||||||
|
@ -365,6 +412,8 @@ class Settings(object):
|
||||||
self_properties = copy(self._getproperties())
|
self_properties = copy(self._getproperties())
|
||||||
if force_permissive is True or 'permissive' in self_properties:
|
if force_permissive is True or 'permissive' in self_properties:
|
||||||
properties -= self._p_.getpermissive()
|
properties -= self._p_.getpermissive()
|
||||||
|
if force_permissives is not None:
|
||||||
|
properties -= force_permissives
|
||||||
|
|
||||||
# global properties
|
# global properties
|
||||||
if force_properties is not None:
|
if force_properties is not None:
|
||||||
|
@ -410,7 +459,7 @@ class Settings(object):
|
||||||
instead of passing a :class:`tiramisu.option.Option()` object.
|
instead of passing a :class:`tiramisu.option.Option()` object.
|
||||||
"""
|
"""
|
||||||
if opt is not None and path is None:
|
if opt is not None and path is None:
|
||||||
path = self._get_opt_path(opt)
|
path = self._get_path_by_opt(opt)
|
||||||
if not isinstance(permissive, tuple):
|
if not isinstance(permissive, tuple):
|
||||||
raise TypeError(_('permissive must be a tuple'))
|
raise TypeError(_('permissive must be a tuple'))
|
||||||
self._p_.setpermissive(path, permissive)
|
self._p_.setpermissive(path, permissive)
|
||||||
|
@ -433,18 +482,23 @@ class Settings(object):
|
||||||
self.append(prop)
|
self.append(prop)
|
||||||
|
|
||||||
def read_only(self):
|
def read_only(self):
|
||||||
"convenience method to freeze, hidde and disable"
|
"convenience method to freeze, hide and disable"
|
||||||
self._read(ro_remove, ro_append)
|
self._read(ro_remove, ro_append)
|
||||||
|
|
||||||
def read_write(self):
|
def read_write(self):
|
||||||
"convenience method to freeze, hidde and disable"
|
"convenience method to freeze, hide and disable"
|
||||||
self._read(rw_remove, rw_append)
|
self._read(rw_remove, rw_append)
|
||||||
|
|
||||||
def reset_cache(self, only_expired):
|
def reset_cache(self, only_expired):
|
||||||
|
"""reset all settings in cache
|
||||||
|
|
||||||
|
:param only_expired: if True reset only expired cached values
|
||||||
|
:type only_expired: boolean
|
||||||
|
"""
|
||||||
if only_expired:
|
if only_expired:
|
||||||
self._p_.reset_expired_cache('property', time())
|
self._p_.reset_expired_cache(int(time()))
|
||||||
else:
|
else:
|
||||||
self._p_.reset_all_cache('property')
|
self._p_.reset_all_cache()
|
||||||
|
|
||||||
def apply_requires(self, opt, path):
|
def apply_requires(self, opt, path):
|
||||||
"""carries out the jit (just in time) requirements between options
|
"""carries out the jit (just in time) requirements between options
|
||||||
|
@ -456,12 +510,13 @@ class Settings(object):
|
||||||
|
|
||||||
let's have a look at all the tuple's items:
|
let's have a look at all the tuple's items:
|
||||||
|
|
||||||
- **option** is the target option's name or path
|
- **option** is the target option's
|
||||||
|
|
||||||
- **expected** is the target option's value that is going to trigger an action
|
- **expected** is the target option's value that is going to trigger
|
||||||
|
an action
|
||||||
|
|
||||||
- **action** is the (property) action to be accomplished if the target option
|
- **action** is the (property) action to be accomplished if the target
|
||||||
happens to have the expected value
|
option happens to have the expected value
|
||||||
|
|
||||||
- if **inverse** is `True` and if the target option's value does not
|
- if **inverse** is `True` and if the target option's value does not
|
||||||
apply, then the property action must be removed from the option's
|
apply, then the property action must be removed from the option's
|
||||||
|
@ -498,7 +553,7 @@ class Settings(object):
|
||||||
for require in requires:
|
for require in requires:
|
||||||
option, expected, action, inverse, \
|
option, expected, action, inverse, \
|
||||||
transitive, same_action = require
|
transitive, same_action = require
|
||||||
reqpath = self._get_opt_path(option)
|
reqpath = self._get_path_by_opt(option)
|
||||||
if reqpath == path or reqpath.startswith(path + '.'):
|
if reqpath == path or reqpath.startswith(path + '.'):
|
||||||
raise RequirementError(_("malformed requirements "
|
raise RequirementError(_("malformed requirements "
|
||||||
"imbrication detected for option:"
|
"imbrication detected for option:"
|
||||||
|
@ -529,5 +584,30 @@ class Settings(object):
|
||||||
break
|
break
|
||||||
return calc_properties
|
return calc_properties
|
||||||
|
|
||||||
def _get_opt_path(self, opt):
|
def _get_path_by_opt(self, opt):
|
||||||
|
"""just a wrapper to get path in optiondescription's cache
|
||||||
|
|
||||||
|
:param opt: `Option`'s object
|
||||||
|
:returns: path
|
||||||
|
"""
|
||||||
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
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'])
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# The original `Config` design model is unproudly borrowed from
|
||||||
|
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
|
# the whole pypy projet is under MIT licence
|
||||||
|
# ____________________________________________________________
|
||||||
|
|
||||||
|
"""Config's informations are, by default, volatiles. This means, all values and
|
||||||
|
settings changes will be lost.
|
||||||
|
|
||||||
|
The storage is the system Tiramisu uses to communicate with various DB.
|
||||||
|
You can specified a persistent storage.
|
||||||
|
|
||||||
|
Storage is basic components used to set Config informations in DB.
|
||||||
|
The primary "entry point" class is the StorageType and it's public
|
||||||
|
configurator ``set_storage()``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
from tiramisu.error import ConfigError
|
||||||
|
from tiramisu.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
class StorageType(object):
|
||||||
|
"""Object to store storage's type. If a Config is already set,
|
||||||
|
default storage is store as selected storage. You cannot change it
|
||||||
|
after.
|
||||||
|
"""
|
||||||
|
default_storage = 'dictionary'
|
||||||
|
storage_type = None
|
||||||
|
mod = None
|
||||||
|
|
||||||
|
def set(self, name):
|
||||||
|
if self.storage_type is not None:
|
||||||
|
if self.storage_type == name:
|
||||||
|
return
|
||||||
|
raise ConfigError(_('storage_type is already set, cannot rebind it'))
|
||||||
|
self.storage_type = name
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
if self.storage_type is None:
|
||||||
|
self.storage_type = self.default_storage
|
||||||
|
storage = self.storage_type
|
||||||
|
if self.mod is None:
|
||||||
|
modulepath = 'tiramisu.storage.{0}'.format(storage)
|
||||||
|
mod = __import__(modulepath)
|
||||||
|
for token in modulepath.split(".")[1:]:
|
||||||
|
mod = getattr(mod, token)
|
||||||
|
self.mod = mod
|
||||||
|
return self.mod
|
||||||
|
|
||||||
|
|
||||||
|
storage_type = StorageType()
|
||||||
|
|
||||||
|
|
||||||
|
def set_storage(name, **kwargs):
|
||||||
|
"""Change storage's configuration
|
||||||
|
|
||||||
|
:params name: is the storage name. If storage is already set, cannot
|
||||||
|
reset storage name
|
||||||
|
|
||||||
|
Other attributes are differents according to the selected storage's name
|
||||||
|
"""
|
||||||
|
storage_type.set(name)
|
||||||
|
setting = storage_type.get().setting
|
||||||
|
for option, value in kwargs.items():
|
||||||
|
try:
|
||||||
|
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())
|
||||||
|
|
||||||
|
if session_id is None:
|
||||||
|
session_id = gen_id(context)
|
||||||
|
imp = storage_type.get()
|
||||||
|
storage = imp.Storage(session_id, persistent)
|
||||||
|
return imp.Settings(storage), imp.Values(storage)
|
||||||
|
|
||||||
|
|
||||||
|
def list_sessions():
|
||||||
|
"""List all available session (persistent or not persistent)
|
||||||
|
"""
|
||||||
|
return storage_type.get().list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
def delete_session(session_id):
|
||||||
|
"""Delete a selected session, be careful, you can deleted a session
|
||||||
|
use by an other instance
|
||||||
|
:params session_id: id of session to delete
|
||||||
|
"""
|
||||||
|
return storage_type.get().delete_session(session_id)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = (set_storage, list_sessions, delete_session)
|
|
@ -0,0 +1,31 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# ____________________________________________________________
|
||||||
|
"""Default plugin for storage. All informations are store in a simple
|
||||||
|
dictionary in memory.
|
||||||
|
|
||||||
|
You cannot have persistente informations with this kind of storage.
|
||||||
|
|
||||||
|
The advantage of this solution is that you can easily create a Config and
|
||||||
|
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
|
||||||
|
|
||||||
|
__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
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from tiramisu.storage.dictionary.storage import Cache
|
from ..util import Cache
|
||||||
|
|
||||||
|
|
||||||
class Settings(Cache):
|
class Settings(Cache):
|
||||||
|
@ -50,12 +50,21 @@ class Settings(Cache):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def get_properties(self, context):
|
|
||||||
return self._properties
|
|
||||||
|
|
||||||
# permissive
|
# permissive
|
||||||
def setpermissive(self, path, permissive):
|
def setpermissive(self, path, permissive):
|
||||||
self._permissives[path] = frozenset(permissive)
|
self._permissives[path] = frozenset(permissive)
|
||||||
|
|
||||||
def getpermissive(self, path=None):
|
def getpermissive(self, path=None):
|
||||||
return self._permissives.get(path, frozenset())
|
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
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"default plugin for cache: set it in a simple dictionary"
|
|
||||||
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
@ -19,9 +18,12 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu.error import ConfigError
|
from tiramisu.error import ConfigError
|
||||||
|
from ..util import SerializeObject
|
||||||
|
|
||||||
|
|
||||||
class Setting(object):
|
class Setting(SerializeObject):
|
||||||
|
"""Dictionary storage has no particular setting.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,15 +40,18 @@ def delete_session(session_id):
|
||||||
|
|
||||||
|
|
||||||
class Storage(object):
|
class Storage(object):
|
||||||
__slots__ = ('session_id',)
|
__slots__ = ('session_id', 'persistent')
|
||||||
storage = 'dictionary'
|
storage = 'dictionary'
|
||||||
|
#if object could be serializable
|
||||||
|
serializable = True
|
||||||
|
|
||||||
def __init__(self, session_id, persistent):
|
def __init__(self, session_id, persistent, test=False):
|
||||||
if session_id in _list_sessions:
|
if not test and session_id in _list_sessions:
|
||||||
raise ValueError(_('session already used'))
|
raise ValueError(_('session already used'))
|
||||||
if persistent:
|
if persistent:
|
||||||
raise ValueError(_('a dictionary cannot be persistent'))
|
raise ValueError(_('a dictionary cannot be persistent'))
|
||||||
self.session_id = session_id
|
self.session_id = session_id
|
||||||
|
self.persistent = persistent
|
||||||
_list_sessions.append(self.session_id)
|
_list_sessions.append(self.session_id)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
@ -54,45 +59,3 @@ class Storage(object):
|
||||||
_list_sessions.remove(self.session_id)
|
_list_sessions.remove(self.session_id)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Cache(object):
|
|
||||||
__slots__ = ('_cache', 'storage')
|
|
||||||
key_is_path = False
|
|
||||||
|
|
||||||
def __init__(self, storage):
|
|
||||||
self._cache = {}
|
|
||||||
self.storage = storage
|
|
||||||
|
|
||||||
def setcache(self, cache_type, path, val, time):
|
|
||||||
self._cache[path] = (val, time)
|
|
||||||
|
|
||||||
def getcache(self, cache_type, path, exp):
|
|
||||||
value, created = self._cache[path]
|
|
||||||
if exp < created:
|
|
||||||
return True, value
|
|
||||||
return False, None
|
|
||||||
|
|
||||||
def hascache(self, cache_type, path):
|
|
||||||
""" path is in the cache
|
|
||||||
|
|
||||||
:param cache_type: value | property
|
|
||||||
:param path: the path's option
|
|
||||||
"""
|
|
||||||
return path in self._cache
|
|
||||||
|
|
||||||
def reset_expired_cache(self, cache_type, exp):
|
|
||||||
for key in tuple(self._cache.keys()):
|
|
||||||
val, created = self._cache[key]
|
|
||||||
if exp > created:
|
|
||||||
del(self._cache[key])
|
|
||||||
|
|
||||||
def reset_all_cache(self, cache_type):
|
|
||||||
"empty the cache"
|
|
||||||
self._cache.clear()
|
|
||||||
|
|
||||||
def get_cached(self, cache_type, context):
|
|
||||||
"""return all values in a dictionary
|
|
||||||
example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
|
|
||||||
"""
|
|
||||||
return self._cache
|
|
||||||
|
|
|
@ -18,16 +18,17 @@
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
|
||||||
from tiramisu.storage.dictionary.storage import Cache
|
from ..util import Cache
|
||||||
|
|
||||||
|
|
||||||
class Values(Cache):
|
class Values(Cache):
|
||||||
__slots__ = ('_values', '__weakref__')
|
__slots__ = ('_values', '_informations', '__weakref__')
|
||||||
|
|
||||||
def __init__(self, storage):
|
def __init__(self, storage):
|
||||||
"""init plugin means create values storage
|
"""init plugin means create values storage
|
||||||
"""
|
"""
|
||||||
self._values = {}
|
self._values = {}
|
||||||
|
self._informations = {}
|
||||||
# should init cache too
|
# should init cache too
|
||||||
super(Values, self).__init__(storage)
|
super(Values, self).__init__(storage)
|
||||||
|
|
||||||
|
@ -72,3 +73,22 @@ class Values(Cache):
|
||||||
return: owner object
|
return: owner object
|
||||||
"""
|
"""
|
||||||
return self._values.get(path, (default, None))[0]
|
return self._values.get(path, (default, None))[0]
|
||||||
|
|
||||||
|
def set_information(self, key, value):
|
||||||
|
"""updates the information's attribute
|
||||||
|
(which is a dictionary)
|
||||||
|
|
||||||
|
:param key: information's key (ex: "help", "doc"
|
||||||
|
:param value: information's value (ex: "the help string")
|
||||||
|
"""
|
||||||
|
self._informations[key] = value
|
||||||
|
|
||||||
|
def get_information(self, key):
|
||||||
|
"""retrieves one information's item
|
||||||
|
|
||||||
|
:param key: the item string (ex: "help")
|
||||||
|
"""
|
||||||
|
if key in self._informations:
|
||||||
|
return self._informations[key]
|
||||||
|
else:
|
||||||
|
raise ValueError("not found")
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# ____________________________________________________________
|
||||||
|
"""Sqlite3 plugin for storage. This storage is not made to be used in productive
|
||||||
|
environment. It was developing as proof of concept.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
__all__ = (setting, Values, Settings, Storage, list_sessions, delete_session)
|
|
@ -17,10 +17,10 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from tiramisu.storage.sqlite3.storage import Cache
|
from .sqlite3db import Sqlite3DB
|
||||||
|
|
||||||
|
|
||||||
class Settings(Cache):
|
class Settings(Sqlite3DB):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def __init__(self, storage):
|
def __init__(self, storage):
|
||||||
|
@ -29,22 +29,22 @@ class Settings(Cache):
|
||||||
permissives_table = 'CREATE TABLE IF NOT EXISTS permissive(path text '
|
permissives_table = 'CREATE TABLE IF NOT EXISTS permissive(path text '
|
||||||
permissives_table += 'primary key, permissives text)'
|
permissives_table += 'primary key, permissives text)'
|
||||||
# should init cache too
|
# should init cache too
|
||||||
super(Settings, self).__init__('property', storage)
|
super(Settings, self).__init__(storage)
|
||||||
self.storage.execute(settings_table, commit=False)
|
self._storage.execute(settings_table, commit=False)
|
||||||
self.storage.execute(permissives_table)
|
self._storage.execute(permissives_table)
|
||||||
|
|
||||||
# propertives
|
# propertives
|
||||||
def setproperties(self, path, properties):
|
def setproperties(self, path, properties):
|
||||||
path = self._sqlite_encode_path(path)
|
path = self._sqlite_encode_path(path)
|
||||||
self.storage.execute("DELETE FROM property WHERE path = ?", (path,),
|
self._storage.execute("DELETE FROM property WHERE path = ?", (path,),
|
||||||
False)
|
False)
|
||||||
self.storage.execute("INSERT INTO property(path, properties) VALUES "
|
self._storage.execute("INSERT INTO property(path, properties) VALUES "
|
||||||
"(?, ?)", (path,
|
"(?, ?)", (path,
|
||||||
self._sqlite_encode(properties)))
|
self._sqlite_encode(properties)))
|
||||||
|
|
||||||
def getproperties(self, path, default_properties):
|
def getproperties(self, path, default_properties):
|
||||||
path = self._sqlite_encode_path(path)
|
path = self._sqlite_encode_path(path)
|
||||||
value = self.storage.select("SELECT properties FROM property WHERE "
|
value = self._storage.select("SELECT properties FROM property WHERE "
|
||||||
"path = ?", (path,))
|
"path = ?", (path,))
|
||||||
if value is None:
|
if value is None:
|
||||||
return set(default_properties)
|
return set(default_properties)
|
||||||
|
@ -53,42 +53,53 @@ class Settings(Cache):
|
||||||
|
|
||||||
def hasproperties(self, path):
|
def hasproperties(self, path):
|
||||||
path = self._sqlite_encode_path(path)
|
path = self._sqlite_encode_path(path)
|
||||||
return self.storage.select("SELECT properties FROM property WHERE "
|
return self._storage.select("SELECT properties FROM property WHERE "
|
||||||
"path = ?", (path,)) is not None
|
"path = ?", (path,)) is not None
|
||||||
|
|
||||||
def reset_all_propertives(self):
|
def reset_all_propertives(self):
|
||||||
self.storage.execute("DELETE FROM property")
|
self._storage.execute("DELETE FROM property")
|
||||||
|
|
||||||
def reset_properties(self, path):
|
def reset_properties(self, path):
|
||||||
path = self._sqlite_encode_path(path)
|
path = self._sqlite_encode_path(path)
|
||||||
self.storage.execute("DELETE FROM property WHERE 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
|
|
||||||
|
|
||||||
# permissive
|
# permissive
|
||||||
def setpermissive(self, path, permissive):
|
def setpermissive(self, path, permissive):
|
||||||
path = self._sqlite_encode_path(path)
|
path = self._sqlite_encode_path(path)
|
||||||
self.storage.execute("DELETE FROM permissive WHERE path = ?", (path,),
|
self._storage.execute("DELETE FROM permissive WHERE path = ?", (path,),
|
||||||
False)
|
False)
|
||||||
self.storage.execute("INSERT INTO permissive(path, permissives) "
|
self._storage.execute("INSERT INTO permissive(path, permissives) "
|
||||||
"VALUES (?, ?)", (path,
|
"VALUES (?, ?)", (path,
|
||||||
self._sqlite_encode(permissive)
|
self._sqlite_encode(permissive)
|
||||||
))
|
))
|
||||||
|
|
||||||
def getpermissive(self, path='_none'):
|
def getpermissive(self, path='_none'):
|
||||||
permissives = self.storage.select("SELECT permissives FROM "
|
permissives = self._storage.select("SELECT permissives FROM "
|
||||||
"permissive WHERE path = ?",
|
"permissive WHERE path = ?",
|
||||||
(path,))
|
(path,))
|
||||||
if permissives is None:
|
if permissives is None:
|
||||||
return frozenset()
|
return frozenset()
|
||||||
else:
|
else:
|
||||||
return frozenset(self._sqlite_decode(permissives[0]))
|
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
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"sqlite3 cache"
|
||||||
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
# ____________________________________________________________
|
||||||
|
try:
|
||||||
|
from cPickle import loads, dumps
|
||||||
|
except ImportError:
|
||||||
|
from pickle import loads, dumps
|
||||||
|
from ..util import Cache
|
||||||
|
|
||||||
|
|
||||||
|
class Sqlite3DB(Cache):
|
||||||
|
__slots__ = tuple()
|
||||||
|
def _sqlite_decode_path(self, path):
|
||||||
|
if path == '_none':
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _sqlite_encode_path(self, path):
|
||||||
|
if path is None:
|
||||||
|
return '_none'
|
||||||
|
else:
|
||||||
|
return path
|
||||||
|
|
||||||
|
def _sqlite_decode(self, value):
|
||||||
|
return loads(value)
|
||||||
|
|
||||||
|
def _sqlite_encode(self, value):
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = list(value)
|
||||||
|
return dumps(value)
|
|
@ -18,14 +18,17 @@
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
|
||||||
from pickle import dumps, loads
|
|
||||||
from os import unlink
|
from os import unlink
|
||||||
from os.path import basename, splitext, join
|
from os.path import basename, splitext, join
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from glob import glob
|
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)
|
||||||
|
"""
|
||||||
extension = 'db'
|
extension = 'db'
|
||||||
dir_database = '/tmp'
|
dir_database = '/tmp'
|
||||||
|
|
||||||
|
@ -50,13 +53,17 @@ def delete_session(session_id):
|
||||||
|
|
||||||
|
|
||||||
class Storage(object):
|
class Storage(object):
|
||||||
__slots__ = ('_conn', '_cursor', 'persistent', '_session_id')
|
__slots__ = ('_conn', '_cursor', 'persistent', 'session_id', 'serializable')
|
||||||
storage = 'sqlite3'
|
storage = 'sqlite3'
|
||||||
|
|
||||||
def __init__(self, session_id, persistent):
|
def __init__(self, session_id, persistent, test=False):
|
||||||
self.persistent = persistent
|
self.persistent = persistent
|
||||||
self._session_id = session_id
|
if self.persistent:
|
||||||
self._conn = sqlite3.connect(_gen_filename(self._session_id))
|
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._conn.text_factory = str
|
||||||
self._cursor = self._conn.cursor()
|
self._cursor = self._conn.cursor()
|
||||||
|
|
||||||
|
@ -78,82 +85,4 @@ class Storage(object):
|
||||||
self._cursor.close()
|
self._cursor.close()
|
||||||
self._conn.close()
|
self._conn.close()
|
||||||
if not self.persistent:
|
if not self.persistent:
|
||||||
delete_session(self._session_id)
|
delete_session(self.session_id)
|
||||||
|
|
||||||
|
|
||||||
class Cache(object):
|
|
||||||
__slots__ = ('storage',)
|
|
||||||
key_is_path = True
|
|
||||||
|
|
||||||
def __init__(self, cache_type, storage):
|
|
||||||
self.storage = storage
|
|
||||||
cache_table = 'CREATE TABLE IF NOT EXISTS cache_{0}(path '.format(
|
|
||||||
cache_type)
|
|
||||||
cache_table += 'text primary key, value text, time real)'
|
|
||||||
self.storage.execute(cache_table)
|
|
||||||
|
|
||||||
# value
|
|
||||||
def _sqlite_decode_path(self, path):
|
|
||||||
if path == '_none':
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
return path
|
|
||||||
|
|
||||||
def _sqlite_encode_path(self, path):
|
|
||||||
if path is None:
|
|
||||||
return '_none'
|
|
||||||
else:
|
|
||||||
return path
|
|
||||||
|
|
||||||
def _sqlite_decode(self, value):
|
|
||||||
return loads(value)
|
|
||||||
|
|
||||||
def _sqlite_encode(self, value):
|
|
||||||
if isinstance(value, list):
|
|
||||||
value = list(value)
|
|
||||||
return dumps(value)
|
|
||||||
|
|
||||||
def setcache(self, cache_type, path, val, time):
|
|
||||||
convert_value = self._sqlite_encode(val)
|
|
||||||
path = self._sqlite_encode_path(path)
|
|
||||||
self.storage.execute("DELETE FROM cache_{0} WHERE path = ?".format(
|
|
||||||
cache_type), (path,), False)
|
|
||||||
self.storage.execute("INSERT INTO cache_{0}(path, value, time) "
|
|
||||||
"VALUES (?, ?, ?)".format(cache_type),
|
|
||||||
(path, convert_value, time))
|
|
||||||
|
|
||||||
def getcache(self, cache_type, path, exp):
|
|
||||||
path = self._sqlite_encode_path(path)
|
|
||||||
cached = self.storage.select("SELECT value FROM cache_{0} WHERE "
|
|
||||||
"path = ? AND time >= ?".format(
|
|
||||||
cache_type), (path, exp))
|
|
||||||
if cached is None:
|
|
||||||
return False, None
|
|
||||||
else:
|
|
||||||
return True, self._sqlite_decode(cached[0])
|
|
||||||
|
|
||||||
def hascache(self, cache_type, path):
|
|
||||||
path = self._sqlite_encode_path(path)
|
|
||||||
return self.storage.select("SELECT value FROM cache_{0} WHERE "
|
|
||||||
"path = ?".format(cache_type),
|
|
||||||
(path,)) is not None
|
|
||||||
|
|
||||||
def reset_expired_cache(self, cache_type, exp):
|
|
||||||
self.storage.execute("DELETE FROM cache_{0} WHERE time < ?".format(
|
|
||||||
cache_type), (exp,))
|
|
||||||
|
|
||||||
def reset_all_cache(self, cache_type):
|
|
||||||
self.storage.execute("DELETE FROM cache_{0}".format(cache_type))
|
|
||||||
|
|
||||||
def get_cached(self, cache_type, context):
|
|
||||||
"""return all values in a dictionary
|
|
||||||
example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
|
|
||||||
"""
|
|
||||||
ret = {}
|
|
||||||
for path, value, time in self.storage.select("SELECT * FROM cache_{0}"
|
|
||||||
"".format(cache_type),
|
|
||||||
only_one=False):
|
|
||||||
path = self._sqlite_decode_path(path)
|
|
||||||
value = self._sqlite_decode(value)
|
|
||||||
ret[path] = (value, time)
|
|
||||||
return ret
|
|
||||||
|
|
|
@ -18,22 +18,25 @@
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
|
||||||
from tiramisu.storage.sqlite3.storage import Cache
|
from .sqlite3db import Sqlite3DB
|
||||||
from tiramisu.setting import owners
|
from tiramisu.setting import owners
|
||||||
|
|
||||||
|
|
||||||
class Values(Cache):
|
class Values(Sqlite3DB):
|
||||||
__slots__ = ('__weakref__',)
|
__slots__ = ('__weakref__',)
|
||||||
|
|
||||||
def __init__(self, storage):
|
def __init__(self, storage):
|
||||||
"""init plugin means create values storage
|
"""init plugin means create values storage
|
||||||
"""
|
"""
|
||||||
# should init cache too
|
# should init cache too
|
||||||
super(Values, self).__init__('value', storage)
|
super(Values, self).__init__(storage)
|
||||||
values_table = 'CREATE TABLE IF NOT EXISTS value(path text primary '
|
values_table = 'CREATE TABLE IF NOT EXISTS value(path text primary '
|
||||||
values_table += 'key, value text, owner text)'
|
values_table += 'key, value text, owner text)'
|
||||||
self.storage.execute(values_table)
|
self._storage.execute(values_table, commit=False)
|
||||||
for owner in self.storage.select("SELECT DISTINCT owner FROM value", tuple(), 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):
|
||||||
try:
|
try:
|
||||||
getattr(owners, owner[0])
|
getattr(owners, owner[0])
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -41,7 +44,7 @@ class Values(Cache):
|
||||||
|
|
||||||
# sqlite
|
# sqlite
|
||||||
def _sqlite_select(self, path):
|
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,))
|
(path,))
|
||||||
|
|
||||||
# value
|
# value
|
||||||
|
@ -51,7 +54,7 @@ class Values(Cache):
|
||||||
"""
|
"""
|
||||||
self.resetvalue(path)
|
self.resetvalue(path)
|
||||||
path = self._sqlite_encode_path(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),
|
"(?, ?, ?)", (path, self._sqlite_encode(value),
|
||||||
str(owner)))
|
str(owner)))
|
||||||
|
|
||||||
|
@ -73,14 +76,14 @@ class Values(Cache):
|
||||||
"""remove value means delete value in storage
|
"""remove value means delete value in storage
|
||||||
"""
|
"""
|
||||||
path = self._sqlite_encode_path(path)
|
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):
|
def get_modified_values(self):
|
||||||
"""return all values in a dictionary
|
"""return all values in a dictionary
|
||||||
example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
|
example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
|
||||||
"""
|
"""
|
||||||
ret = {}
|
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):
|
only_one=False):
|
||||||
path = self._sqlite_decode_path(path)
|
path = self._sqlite_decode_path(path)
|
||||||
owner = getattr(owners, owner)
|
owner = getattr(owners, owner)
|
||||||
|
@ -94,7 +97,7 @@ class Values(Cache):
|
||||||
"""change owner for an option
|
"""change owner for an option
|
||||||
"""
|
"""
|
||||||
path = self._sqlite_encode_path(path)
|
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))
|
(str(owner), path))
|
||||||
|
|
||||||
def getowner(self, path, default):
|
def getowner(self, path, default):
|
||||||
|
@ -102,7 +105,7 @@ class Values(Cache):
|
||||||
return: owner object
|
return: owner object
|
||||||
"""
|
"""
|
||||||
path = self._sqlite_encode_path(path)
|
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,))
|
(path,))
|
||||||
if owner is None:
|
if owner is None:
|
||||||
return default
|
return default
|
||||||
|
@ -114,3 +117,27 @@ class Values(Cache):
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
owners.addowner(owner)
|
owners.addowner(owner)
|
||||||
return getattr(owners, owner)
|
return getattr(owners, owner)
|
||||||
|
|
||||||
|
def set_information(self, key, value):
|
||||||
|
"""updates the information's attribute
|
||||||
|
(which is a dictionary)
|
||||||
|
|
||||||
|
: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,),
|
||||||
|
False)
|
||||||
|
self._storage.execute("INSERT INTO information(key, value) VALUES "
|
||||||
|
"(?, ?)", (key, self._sqlite_encode(value)))
|
||||||
|
|
||||||
|
def get_information(self, key):
|
||||||
|
"""retrieves one information's item
|
||||||
|
|
||||||
|
:param key: the item string (ex: "help")
|
||||||
|
"""
|
||||||
|
value = self._storage.select("SELECT value FROM information WHERE key = ?",
|
||||||
|
(key,))
|
||||||
|
if value is None:
|
||||||
|
raise ValueError("not found")
|
||||||
|
else:
|
||||||
|
return self._sqlite_decode(value[0])
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"default plugin for cache: set it in a simple dictionary"
|
||||||
|
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# 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')
|
||||||
|
key_is_path = False
|
||||||
|
|
||||||
|
def __init__(self, storage):
|
||||||
|
self._cache = {}
|
||||||
|
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)
|
||||||
|
|
||||||
|
def getcache(self, path, exp):
|
||||||
|
value, created = self._cache[path]
|
||||||
|
if created is None or exp <= created:
|
||||||
|
return True, value
|
||||||
|
return False, None
|
||||||
|
|
||||||
|
def hascache(self, path):
|
||||||
|
""" path is in the cache
|
||||||
|
|
||||||
|
:param path: the path's option
|
||||||
|
"""
|
||||||
|
return path in self._cache
|
||||||
|
|
||||||
|
def reset_expired_cache(self, exp):
|
||||||
|
for key in tuple(self._cache.keys()):
|
||||||
|
val, created = self._cache[key]
|
||||||
|
if created is not None and exp > created:
|
||||||
|
del(self._cache[key])
|
||||||
|
|
||||||
|
def reset_all_cache(self):
|
||||||
|
"empty the cache"
|
||||||
|
self._cache.clear()
|
||||||
|
|
||||||
|
def get_cached(self, context):
|
||||||
|
"""return all values in a dictionary
|
||||||
|
example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
|
||||||
|
"""
|
||||||
|
return self._cache
|
|
@ -44,9 +44,7 @@ class Values(object):
|
||||||
"""
|
"""
|
||||||
self.context = weakref.ref(context)
|
self.context = weakref.ref(context)
|
||||||
# the storage type is dictionary or sqlite3
|
# the storage type is dictionary or sqlite3
|
||||||
import_lib = 'tiramisu.storage.{0}.value'.format(storage.storage)
|
self._p_ = storage
|
||||||
self._p_ = __import__(import_lib, globals(), locals(), ['Values'],
|
|
||||||
).Values(storage)
|
|
||||||
|
|
||||||
def _getdefault(self, opt):
|
def _getdefault(self, opt):
|
||||||
"""
|
"""
|
||||||
|
@ -126,7 +124,7 @@ class Values(object):
|
||||||
return True
|
return True
|
||||||
return False
|
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
|
retrieves a value for the options that have a callback
|
||||||
|
|
||||||
|
@ -141,7 +139,7 @@ class Values(object):
|
||||||
return carry_out_calculation(opt._name, config=self.context(),
|
return carry_out_calculation(opt._name, config=self.context(),
|
||||||
callback=callback,
|
callback=callback,
|
||||||
callback_params=callback_params,
|
callback_params=callback_params,
|
||||||
index=index)
|
index=index, max_len=max_len)
|
||||||
|
|
||||||
def __getitem__(self, opt):
|
def __getitem__(self, opt):
|
||||||
"enables us to use the pythonic dictionary-like access to values"
|
"enables us to use the pythonic dictionary-like access to values"
|
||||||
|
@ -149,25 +147,28 @@ class Values(object):
|
||||||
|
|
||||||
def getitem(self, opt, path=None, validate=True, force_permissive=False,
|
def getitem(self, opt, path=None, validate=True, force_permissive=False,
|
||||||
force_properties=None, validate_properties=True):
|
force_properties=None, validate_properties=True):
|
||||||
ntime = None
|
|
||||||
if path is None:
|
if path is None:
|
||||||
path = self._get_opt_path(opt)
|
path = self._get_opt_path(opt)
|
||||||
if self._p_.hascache('value', path):
|
ntime = None
|
||||||
ntime = time()
|
setting = self.context().cfgimpl_get_settings()
|
||||||
is_cached, value = self._p_.getcache('value', path, ntime)
|
if 'cache' in setting and self._p_.hascache(path):
|
||||||
|
if 'expire' in setting:
|
||||||
|
ntime = int(time())
|
||||||
|
is_cached, value = self._p_.getcache(path, ntime)
|
||||||
if is_cached:
|
if is_cached:
|
||||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||||
#load value so don't need to validate if is not a Multi
|
#load value so don't need to validate if is not a Multi
|
||||||
value = Multi(value, self.context, opt, path, validate=False)
|
value = Multi(value, self.context, opt, path, validate=False)
|
||||||
return value
|
return value
|
||||||
val = self._getitem(opt, path, validate, force_permissive, force_properties,
|
val = self._getitem(opt, path, validate, force_permissive,
|
||||||
validate_properties)
|
force_properties, validate_properties)
|
||||||
if 'expire' in self.context().cfgimpl_get_settings() and validate and \
|
if 'cache' in setting and validate and validate_properties and \
|
||||||
validate_properties and force_permissive is False and \
|
force_permissive is False and force_properties is None:
|
||||||
force_properties is None:
|
if 'expire' in setting:
|
||||||
if ntime is None:
|
if ntime is None:
|
||||||
ntime = time()
|
ntime = int(time())
|
||||||
self._p_.setcache('value', path, val, ntime + expires_time)
|
ntime = ntime + expires_time
|
||||||
|
self._p_.setcache(path, val, ntime)
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
@ -176,11 +177,20 @@ class Values(object):
|
||||||
# options with callbacks
|
# options with callbacks
|
||||||
setting = self.context().cfgimpl_get_settings()
|
setting = self.context().cfgimpl_get_settings()
|
||||||
is_frozen = 'frozen' in setting[opt]
|
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
|
# if value is callback and is not set
|
||||||
# or frozen with force_default_on_freeze
|
# or frozen with force_default_on_freeze
|
||||||
if opt.impl_has_callback() and (
|
if opt.impl_has_callback() and (
|
||||||
self._is_default_owner(path) or
|
self._is_default_owner(path) or
|
||||||
(is_frozen and 'force_default_on_freeze' in setting[opt])):
|
(is_frozen and 'force_default_on_freeze' in setting[opt])):
|
||||||
|
lenmaster = None
|
||||||
no_value_slave = False
|
no_value_slave = False
|
||||||
if (opt.impl_is_multi() and
|
if (opt.impl_is_multi() and
|
||||||
opt.impl_get_multitype() == multitypes.slave):
|
opt.impl_get_multitype() == multitypes.slave):
|
||||||
|
@ -192,11 +202,21 @@ class Values(object):
|
||||||
no_value_slave = True
|
no_value_slave = True
|
||||||
|
|
||||||
if not no_value_slave:
|
if not no_value_slave:
|
||||||
value = self._getcallback_value(opt)
|
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
|
if (opt.impl_is_multi() and
|
||||||
opt.impl_get_multitype() == multitypes.slave):
|
opt.impl_get_multitype() == multitypes.slave):
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
value = [value for i in range(lenmaster)]
|
value = [value for i in range(lenmaster)]
|
||||||
|
if config_error is None:
|
||||||
if opt.impl_is_multi():
|
if opt.impl_is_multi():
|
||||||
value = Multi(value, self.context, opt, path, validate)
|
value = Multi(value, self.context, opt, path, validate)
|
||||||
# suppress value if already set
|
# suppress value if already set
|
||||||
|
@ -208,15 +228,18 @@ class Values(object):
|
||||||
value = Multi(value, self.context, opt, path, validate)
|
value = Multi(value, self.context, opt, path, validate)
|
||||||
else:
|
else:
|
||||||
value = self._getvalue(opt, path, validate)
|
value = self._getvalue(opt, path, validate)
|
||||||
if validate:
|
if config_error is None and validate:
|
||||||
opt.impl_validate(value, self.context(), 'validator' in setting)
|
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]:
|
'force_store_value' in setting[opt]:
|
||||||
self.setitem(opt, value, path, is_write=False)
|
self.setitem(opt, value, path, is_write=False)
|
||||||
if validate_properties:
|
if validate_properties:
|
||||||
setting.validate_properties(opt, False, False, value=value, path=path,
|
setting.validate_properties(opt, False, False, value=value, path=path,
|
||||||
force_permissive=force_permissive,
|
force_permissive=force_permissive,
|
||||||
force_properties=force_properties)
|
force_properties=force_properties,
|
||||||
|
force_permissives=force_permissives)
|
||||||
|
if config_error is not None:
|
||||||
|
raise ConfigError(config_error)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __setitem__(self, opt, value):
|
def __setitem__(self, opt, value):
|
||||||
|
@ -230,7 +253,7 @@ class Values(object):
|
||||||
opt.impl_validate(value, self.context(),
|
opt.impl_validate(value, self.context(),
|
||||||
'validator' in self.context().cfgimpl_get_settings())
|
'validator' in self.context().cfgimpl_get_settings())
|
||||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
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,
|
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||||
is_write=is_write)
|
is_write=is_write)
|
||||||
|
|
||||||
|
@ -302,9 +325,9 @@ class Values(object):
|
||||||
clears the cache if necessary
|
clears the cache if necessary
|
||||||
"""
|
"""
|
||||||
if only_expired:
|
if only_expired:
|
||||||
self._p_.reset_expired_cache('value', time())
|
self._p_.reset_expired_cache(int(time()))
|
||||||
else:
|
else:
|
||||||
self._p_.reset_all_cache('value')
|
self._p_.reset_all_cache()
|
||||||
|
|
||||||
def _get_opt_path(self, opt):
|
def _get_opt_path(self, opt):
|
||||||
"""
|
"""
|
||||||
|
@ -315,6 +338,38 @@ class Values(object):
|
||||||
"""
|
"""
|
||||||
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||||
|
|
||||||
|
# information
|
||||||
|
def set_information(self, key, value):
|
||||||
|
"""updates the information's attribute
|
||||||
|
|
||||||
|
:param key: information's key (ex: "help", "doc"
|
||||||
|
:param value: information's value (ex: "the help string")
|
||||||
|
"""
|
||||||
|
self._p_.set_information(key, value)
|
||||||
|
|
||||||
|
def get_information(self, key, default=None):
|
||||||
|
"""retrieves one information's item
|
||||||
|
|
||||||
|
:param key: the item string (ex: "help")
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return self._p_.get_information(key)
|
||||||
|
except ValueError:
|
||||||
|
if default is not None:
|
||||||
|
return default
|
||||||
|
else:
|
||||||
|
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
|
# multi types
|
||||||
|
|
||||||
|
@ -324,11 +379,13 @@ class Multi(list):
|
||||||
that support item notation for the values of multi options"""
|
that support item notation for the values of multi options"""
|
||||||
__slots__ = ('opt', 'path', 'context')
|
__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 value: the Multi wraps a list value
|
||||||
:param context: the home config that has the values
|
:param context: the home config that has the values
|
||||||
:param opt: the option object that have this Multi value
|
:param opt: the option object that have this Multi value
|
||||||
|
:param setitem: only if set a value
|
||||||
"""
|
"""
|
||||||
self.opt = opt
|
self.opt = opt
|
||||||
self.path = path
|
self.path = path
|
||||||
|
@ -338,26 +395,34 @@ class Multi(list):
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
value = [value]
|
value = [value]
|
||||||
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
||||||
value = self._valid_slave(value)
|
value = self._valid_slave(value, setitem)
|
||||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
elif validate and self.opt.impl_get_multitype() == multitypes.master:
|
||||||
self._valid_master(value)
|
self._valid_master(value)
|
||||||
super(Multi, self).__init__(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
|
#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(
|
masterp = self.context().cfgimpl_get_description().impl_get_path_by_opt(
|
||||||
self.opt.impl_get_master_slaves())
|
self.opt.impl_get_master_slaves())
|
||||||
mastervalue = getattr(self.context(), masterp)
|
mastervalue = getattr(self.context(), masterp)
|
||||||
masterlen = len(mastervalue)
|
masterlen = len(mastervalue)
|
||||||
valuelen = len(value)
|
valuelen = len(value)
|
||||||
|
is_default_owner = not values._is_default_owner(self.path) or setitem
|
||||||
if valuelen > masterlen or (valuelen < masterlen and
|
if valuelen > masterlen or (valuelen < masterlen and
|
||||||
not self.context().cfgimpl_get_values(
|
is_default_owner):
|
||||||
)._is_default_owner(self.path)):
|
|
||||||
raise SlaveError(_("invalid len for the slave: {0}"
|
raise SlaveError(_("invalid len for the slave: {0}"
|
||||||
" which has {1} as master").format(
|
" which has {1} as master").format(
|
||||||
self.opt._name, masterp))
|
self.opt._name, masterp))
|
||||||
elif valuelen < masterlen:
|
elif valuelen < masterlen:
|
||||||
for num in range(0, masterlen - valuelen):
|
for num in range(0, masterlen - valuelen):
|
||||||
|
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())
|
value.append(self.opt.impl_getdefault_multi())
|
||||||
#else: same len so do nothing
|
#else: same len so do nothing
|
||||||
return value
|
return value
|
||||||
|
@ -376,6 +441,15 @@ class Multi(list):
|
||||||
self.opt._name, slave._name))
|
self.opt._name, slave._name))
|
||||||
elif len(value_slave) < masterlen:
|
elif len(value_slave) < masterlen:
|
||||||
for num in range(0, masterlen - len(value_slave)):
|
for num in range(0, masterlen - len(value_slave)):
|
||||||
|
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(),
|
value_slave.append(slave.impl_getdefault_multi(),
|
||||||
force=True)
|
force=True)
|
||||||
|
|
||||||
|
@ -470,12 +544,15 @@ class Multi(list):
|
||||||
"").format(str(value),
|
"").format(str(value),
|
||||||
self.opt._name, err))
|
self.opt._name, err))
|
||||||
|
|
||||||
def pop(self, key, force=False):
|
def pop(self, index, force=False):
|
||||||
"""the list value can be updated (poped)
|
"""the list value can be updated (poped)
|
||||||
only if the option is a master
|
only if the option is a master
|
||||||
|
|
||||||
:param key: index of the element to pop
|
:param index: remove item a index
|
||||||
:return: the requested element
|
:type index: int
|
||||||
|
:param force: force pop item (withoud check master/slave)
|
||||||
|
:type force: boolean
|
||||||
|
:returns: item at index
|
||||||
"""
|
"""
|
||||||
if not force:
|
if not force:
|
||||||
if self.opt.impl_get_multitype() == multitypes.slave:
|
if self.opt.impl_get_multitype() == multitypes.slave:
|
||||||
|
@ -488,8 +565,8 @@ class Multi(list):
|
||||||
#get multi without valid properties
|
#get multi without valid properties
|
||||||
values.getitem(slave,
|
values.getitem(slave,
|
||||||
validate_properties=False
|
validate_properties=False
|
||||||
).pop(key, force=True)
|
).pop(index, force=True)
|
||||||
#set value without valid properties
|
#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)
|
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -2,7 +2,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2013-07-18 15:20+CEST\n"
|
"POT-Creation-Date: 2013-08-31 09:52+CEST\n"
|
||||||
"PO-Revision-Date: \n"
|
"PO-Revision-Date: \n"
|
||||||
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -11,18 +11,18 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Poedit 1.5.4\n"
|
"X-Generator: Poedit 1.5.4\n"
|
||||||
|
|
||||||
#: tiramisu/autolib.py:49
|
#: tiramisu/autolib.py:58
|
||||||
msgid "no config specified but needed"
|
msgid "no config specified but needed"
|
||||||
msgstr "aucune config spécifié alors que c'est nécessaire"
|
msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||||
|
|
||||||
#: tiramisu/autolib.py:56
|
#: tiramisu/autolib.py:65
|
||||||
msgid ""
|
msgid ""
|
||||||
"unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
"unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"impossible d'effectuer le calcul, l'option {0} a les propriétés : {1} pour : "
|
"impossible d'effectuer le calcul, l'option {0} a les propriétés : {1} pour : "
|
||||||
"{2}"
|
"{2}"
|
||||||
|
|
||||||
#: tiramisu/autolib.py:65
|
#: tiramisu/autolib.py:74
|
||||||
msgid ""
|
msgid ""
|
||||||
"unable to carry out a calculation, option value with multi types must have "
|
"unable to carry out a calculation, option value with multi types must have "
|
||||||
"same length for: {0}"
|
"same length for: {0}"
|
||||||
|
@ -30,86 +30,79 @@ msgstr ""
|
||||||
"impossible d'effectuer le calcul, valeur d'un option avec le type multi doit "
|
"impossible d'effectuer le calcul, valeur d'un option avec le type multi doit "
|
||||||
"avoir la même longueur pour : {0}"
|
"avoir la même longueur pour : {0}"
|
||||||
|
|
||||||
#: tiramisu/config.py:45
|
#: tiramisu/config.py:47
|
||||||
msgid "descr must be an optiondescription, not {0}"
|
msgid "descr must be an optiondescription, not {0}"
|
||||||
msgstr "descr doit être une optiondescription pas un {0}"
|
msgstr "descr doit être une optiondescription pas un {0}"
|
||||||
|
|
||||||
#: tiramisu/config.py:118
|
#: tiramisu/config.py:121
|
||||||
msgid "unknown group_type: {0}"
|
msgid "unknown group_type: {0}"
|
||||||
msgstr "group_type inconnu: {0}"
|
msgstr "group_type inconnu: {0}"
|
||||||
|
|
||||||
#: tiramisu/config.py:154
|
#: tiramisu/config.py:157
|
||||||
msgid "no optiondescription for this config (may be metaconfig without meta)"
|
msgid ""
|
||||||
|
"no option description found for this config (may be metaconfig without meta)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"pas d'optiondescription pour cette config (par exemple metaconfig sans meta)"
|
"pas d'option description pour cette config (peut être une metaconfig sans "
|
||||||
|
"meta)"
|
||||||
|
|
||||||
#: tiramisu/config.py:312
|
#: tiramisu/config.py:311
|
||||||
msgid "unknown type_ type {0} for _find"
|
msgid "unknown type_ type {0}for _find"
|
||||||
msgstr "type_ type {0} pour _find inconnu"
|
msgstr "type_ type {0} pour _find inconnu"
|
||||||
|
|
||||||
#: tiramisu/config.py:351
|
#: tiramisu/config.py:350
|
||||||
msgid "no option found in config with these criteria"
|
msgid "no option found in config with these criteria"
|
||||||
msgstr "aucune option trouvée dans la config avec ces critères"
|
msgstr "aucune option trouvée dans la config avec ces critères"
|
||||||
|
|
||||||
#: tiramisu/config.py:394
|
#: tiramisu/config.py:400
|
||||||
msgid "make_dict can't filtering with value without option"
|
msgid "make_dict can't filtering with value without option"
|
||||||
msgstr "make_dict ne peut filtrer sur une valeur mais sans option"
|
msgstr "make_dict ne peut filtrer sur une valeur mais sans option"
|
||||||
|
|
||||||
#: tiramisu/config.py:414
|
#: tiramisu/config.py:421
|
||||||
msgid "unexpected path {0}, should start with {1}"
|
msgid "unexpected path {0}, should start with {1}"
|
||||||
msgstr "chemin imprévu {0}, devrait commencer par {1}"
|
msgstr "chemin imprévu {0}, devrait commencer par {1}"
|
||||||
|
|
||||||
#: tiramisu/config.py:527
|
#: tiramisu/config.py:481
|
||||||
msgid "metaconfig's children must be a list"
|
msgid "opt in getowner must be an option not {0}"
|
||||||
msgstr "enfants d'une metaconfig doit être une liste"
|
msgstr "opt dans getowner doit être une option pas {0}"
|
||||||
|
|
||||||
#: tiramisu/config.py:532
|
#: tiramisu/option.py:71
|
||||||
msgid "metaconfig's children must be config, not {0}"
|
|
||||||
msgstr "enfants d'une metaconfig doit être une config, pas {0}"
|
|
||||||
|
|
||||||
#: tiramisu/config.py:537
|
|
||||||
msgid "all config in metaconfig must have same optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
"toutes les configs d'une metaconfig doivent avoir la même optiondescription"
|
|
||||||
|
|
||||||
#: tiramisu/config.py:540
|
|
||||||
msgid "child has already a metaconfig's"
|
|
||||||
msgstr "enfant a déjà une metaconfig"
|
|
||||||
|
|
||||||
#: tiramisu/option.py:70
|
|
||||||
msgid "{0} has no attribute impl_set_information"
|
msgid "{0} has no attribute impl_set_information"
|
||||||
msgstr "{0} n'a pas d'attribut impl_set_information"
|
msgstr "{0} n'a pas d'attribut impl_set_information"
|
||||||
|
|
||||||
#: tiramisu/option.py:84
|
|
||||||
msgid "Information's item not found: {0}"
|
|
||||||
msgstr "l'élément information non trouvé: {0}"
|
|
||||||
|
|
||||||
#: tiramisu/option.py:86
|
#: 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"
|
msgid "{0} has no attribute impl_get_information"
|
||||||
msgstr "{0} n'a pas d'attribut impl_get_information"
|
msgstr "{0} n'a pas d'attribut impl_get_information"
|
||||||
|
|
||||||
#: tiramisu/option.py:124
|
#: 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
|
||||||
msgid "invalid name: {0} for option"
|
msgid "invalid name: {0} for option"
|
||||||
msgstr "nom invalide : {0} pour l'option"
|
msgstr "nom invalide : {0} pour l'option"
|
||||||
|
|
||||||
#: tiramisu/option.py:134
|
#: tiramisu/option.py:169
|
||||||
msgid "validator must be a function"
|
msgid "validator must be a function"
|
||||||
msgstr "validator doit être une fonction"
|
msgstr "validator doit être une fonction"
|
||||||
|
|
||||||
#: tiramisu/option.py:141
|
#: tiramisu/option.py:176
|
||||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"une default_multi est renseigné alors que multi est False dans l'option : {0}"
|
"une default_multi est renseigné alors que multi est False dans l'option : {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:147
|
#: tiramisu/option.py:182
|
||||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||||
msgstr "la valeur default_multi est invalide {0} pour l'option {1} : {2}"
|
msgstr "la valeur default_multi est invalide {0} pour l'option {1} : {2}"
|
||||||
|
|
||||||
#: tiramisu/option.py:150
|
#: tiramisu/option.py:187
|
||||||
msgid "default value not allowed if option: {0} is calculated"
|
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é"
|
||||||
|
|
||||||
#: tiramisu/option.py:153
|
#: tiramisu/option.py:190
|
||||||
msgid ""
|
msgid ""
|
||||||
"params defined for a callback function but no callback defined yet for "
|
"params defined for a callback function but no callback defined yet for "
|
||||||
"option {0}"
|
"option {0}"
|
||||||
|
@ -117,183 +110,183 @@ msgstr ""
|
||||||
"params définit pour une fonction callback mais par de callback défini encore "
|
"params définit pour une fonction callback mais par de callback défini encore "
|
||||||
"pour l'option {0}"
|
"pour l'option {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:174 tiramisu/option.py:718
|
#: tiramisu/option.py:212 tiramisu/option.py:753
|
||||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||||
msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
|
msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
|
||||||
|
|
||||||
#: tiramisu/option.py:273
|
#: tiramisu/option.py:285
|
||||||
msgid "invalid value {0} for option {1} for object {2}"
|
msgid "invalid value {0} for option {1} for object {2}"
|
||||||
msgstr "valeur invalide {0} pour l'option {1} pour l'objet {2}"
|
msgstr "valeur invalide {0} pour l'option {1} pour l'objet {2}"
|
||||||
|
|
||||||
#: tiramisu/option.py:278 tiramisu/value.py:368
|
#: tiramisu/option.py:293 tiramisu/value.py:468
|
||||||
msgid "invalid value {0} for option {1}: {2}"
|
msgid "invalid value {0} for option {1}: {2}"
|
||||||
msgstr "valeur invalide {0} pour l'option {1} : {2}"
|
msgstr "valeur invalide {0} pour l'option {1} : {2}"
|
||||||
|
|
||||||
#: tiramisu/option.py:290
|
#: tiramisu/option.py:305
|
||||||
msgid "invalid value {0} for option {1} which must be a list"
|
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"
|
msgstr "valeur invalide {0} pour l'option {1} qui doit être une liste"
|
||||||
|
|
||||||
#: tiramisu/option.py:354
|
#: tiramisu/option.py:374
|
||||||
msgid "invalid value {0} for option {1} must be different as {2} option"
|
msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"valeur invalide {0} pour l'option {1} doit être différent que l'option {2}"
|
"valeur invalide {0} pour l'option {1} doit être différent que l'option {2}"
|
||||||
|
|
||||||
#: tiramisu/option.py:376
|
#: tiramisu/option.py:396
|
||||||
msgid "values must be a tuple for {0}"
|
msgid "values must be a tuple for {0}"
|
||||||
msgstr "values doit être un tuple pour {0}"
|
msgstr "values doit être un tuple pour {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:379
|
#: tiramisu/option.py:399
|
||||||
msgid "open_values must be a boolean for {0}"
|
msgid "open_values must be a boolean for {0}"
|
||||||
msgstr "open_values doit être un booléen pour {0}"
|
msgstr "open_values doit être un booléen pour {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:400
|
#: tiramisu/option.py:420
|
||||||
msgid "value {0} is not permitted, only {1} is allowed"
|
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 permit, seules {1} sont autorisées"
|
||||||
|
|
||||||
#: tiramisu/option.py:411
|
#: tiramisu/option.py:432
|
||||||
msgid "value must be a boolean"
|
msgid "value must be a boolean"
|
||||||
msgstr "valeur doit être un booléen"
|
msgstr "valeur doit être un booléen"
|
||||||
|
|
||||||
#: tiramisu/option.py:421
|
#: tiramisu/option.py:442
|
||||||
msgid "value must be an integer"
|
msgid "value must be an integer"
|
||||||
msgstr "valeur doit être un numbre"
|
msgstr "valeur doit être un numbre"
|
||||||
|
|
||||||
#: tiramisu/option.py:431
|
#: tiramisu/option.py:452
|
||||||
msgid "value must be a float"
|
msgid "value must be a float"
|
||||||
msgstr "valeur doit être un nombre flottant"
|
msgstr "valeur doit être un nombre flottant"
|
||||||
|
|
||||||
#: tiramisu/option.py:441
|
#: tiramisu/option.py:462
|
||||||
msgid "value must be a string"
|
msgid "value must be a string, not {0}"
|
||||||
msgstr "valeur doit être une chaîne"
|
msgstr "valeur doit être une chaîne, pas {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:452
|
#: tiramisu/option.py:480
|
||||||
msgid "value must be an unicode"
|
msgid "value must be an unicode"
|
||||||
msgstr "valeur doit être une valeur unicode"
|
msgstr "valeur doit être une valeur unicode"
|
||||||
|
|
||||||
#: tiramisu/option.py:463
|
#: tiramisu/option.py:490
|
||||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
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:497
|
#: tiramisu/option.py:526
|
||||||
msgid "IP mustn't not be in reserved class"
|
msgid "IP shall not be in reserved class"
|
||||||
msgstr "IP ne doit pas être d'une classe reservée"
|
msgstr "IP ne doit pas être d'une classe reservée"
|
||||||
|
|
||||||
#: tiramisu/option.py:499
|
#: tiramisu/option.py:528
|
||||||
msgid "IP must be in private class"
|
msgid "IP must be in private class"
|
||||||
msgstr "IP doit être dans la classe privée"
|
msgstr "IP doit être dans la classe privée"
|
||||||
|
|
||||||
#: tiramisu/option.py:535
|
#: tiramisu/option.py:566
|
||||||
msgid "inconsistency in allowed range"
|
msgid "inconsistency in allowed range"
|
||||||
msgstr "inconsistence dans la plage autorisée"
|
msgstr "inconsistence dans la plage autorisée"
|
||||||
|
|
||||||
#: tiramisu/option.py:540
|
#: tiramisu/option.py:571
|
||||||
msgid "max value is empty"
|
msgid "max value is empty"
|
||||||
msgstr "valeur maximum est vide"
|
msgstr "valeur maximum est vide"
|
||||||
|
|
||||||
#: tiramisu/option.py:576
|
#: tiramisu/option.py:608
|
||||||
msgid "network mustn't not be in reserved class"
|
msgid "network shall not be in reserved class"
|
||||||
msgstr "réseau ne doit pas être dans la classe reservée"
|
msgstr "réseau ne doit pas être dans la classe reservée"
|
||||||
|
|
||||||
#: tiramisu/option.py:608
|
#: tiramisu/option.py:640
|
||||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
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"
|
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3}), ce réseau est une IP"
|
||||||
|
|
||||||
#: tiramisu/option.py:612
|
#: tiramisu/option.py:645
|
||||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
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"
|
msgstr "IP invalide {0} ({1}) avec masque {2} ({3}), cette IP est un réseau"
|
||||||
|
|
||||||
#: tiramisu/option.py:617
|
#: tiramisu/option.py:650
|
||||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||||
msgstr "IP invalide {0} ({1}) avec masque {2} ({3})"
|
msgstr "IP invalide {0} ({1}) avec masque {2} ({3})"
|
||||||
|
|
||||||
#: tiramisu/option.py:619
|
#: tiramisu/option.py:652
|
||||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||||
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3})"
|
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3})"
|
||||||
|
|
||||||
#: tiramisu/option.py:639
|
#: tiramisu/option.py:672
|
||||||
msgid "unknown type_ {0} for hostname"
|
msgid "unknown type_ {0} for hostname"
|
||||||
msgstr "type_ inconnu {0} pour le nom d'hôte"
|
msgstr "type_ inconnu {0} pour le nom d'hôte"
|
||||||
|
|
||||||
#: tiramisu/option.py:642
|
#: tiramisu/option.py:675
|
||||||
msgid "allow_ip must be a boolean"
|
msgid "allow_ip must be a boolean"
|
||||||
msgstr "allow_ip doit être un booléen"
|
msgstr "allow_ip doit être un booléen"
|
||||||
|
|
||||||
#: tiramisu/option.py:671
|
#: tiramisu/option.py:704
|
||||||
msgid "invalid value for {0}, must have dot"
|
msgid "invalid value for {0}, must have dot"
|
||||||
msgstr "valeur invalide pour {0}, doit avoir un point"
|
msgstr "valeur invalide pour {0}, doit avoir un point"
|
||||||
|
|
||||||
#: tiramisu/option.py:674
|
#: tiramisu/option.py:707
|
||||||
msgid "invalid domainname's length for {0} (max {1})"
|
msgid "invalid domainname's length for {0} (max {1})"
|
||||||
msgstr "longueur du nom de domaine invalide pour {0} (maximum {1})"
|
msgstr "longueur du nom de domaine invalide pour {0} (maximum {1})"
|
||||||
|
|
||||||
#: tiramisu/option.py:676
|
#: tiramisu/option.py:710
|
||||||
msgid "invalid domainname's length for {0} (min 2)"
|
msgid "invalid domainname's length for {0} (min 2)"
|
||||||
msgstr "longueur du nom de domaine invalide pour {0} (minimum 2)"
|
msgstr "longueur du nom de domaine invalide pour {0} (minimum 2)"
|
||||||
|
|
||||||
#: tiramisu/option.py:680
|
#: tiramisu/option.py:714
|
||||||
msgid "invalid domainname"
|
msgid "invalid domainname"
|
||||||
msgstr "nom de domaine invalide"
|
msgstr "nom de domaine invalide"
|
||||||
|
|
||||||
#: tiramisu/option.py:696
|
#: tiramisu/option.py:731
|
||||||
msgid "invalid name: {0} for optiondescription"
|
msgid "invalid name: {0} for optiondescription"
|
||||||
msgstr "nom invalide : {0} pour l'optiondescription"
|
msgstr "nom invalide : {0} pour l'optiondescription"
|
||||||
|
|
||||||
#: tiramisu/option.py:707
|
#: tiramisu/option.py:743
|
||||||
msgid "duplicate option name: {0}"
|
msgid "duplicate option name: {0}"
|
||||||
msgstr "nom de l'option dupliqué : {0}"
|
msgstr "nom de l'option dupliqué : {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:731
|
#: tiramisu/option.py:769
|
||||||
msgid "unknown Option {0} in OptionDescription {1}"
|
msgid "unknown Option {0} in OptionDescription {1}"
|
||||||
msgstr "Option {} inconnue pour l'OptionDescription{}"
|
msgstr "Option {} inconnue pour l'OptionDescription{}"
|
||||||
|
|
||||||
#: tiramisu/option.py:795
|
#: tiramisu/option.py:820
|
||||||
msgid "duplicate option: {0}"
|
msgid "duplicate option: {0}"
|
||||||
msgstr "option dupliquée : {0}"
|
msgstr "option dupliquée : {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:805
|
#: tiramisu/option.py:850
|
||||||
msgid "no option for path {0}"
|
msgid "no option for path {0}"
|
||||||
msgstr "pas d'option pour le chemin {0}"
|
msgstr "pas d'option pour le chemin {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:811
|
#: tiramisu/option.py:856
|
||||||
msgid "no option {0} found"
|
msgid "no option {0} found"
|
||||||
msgstr "pas d'option {0} trouvée"
|
msgstr "pas d'option {0} trouvée"
|
||||||
|
|
||||||
#: tiramisu/option.py:821
|
#: tiramisu/option.py:866
|
||||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
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})"
|
msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})"
|
||||||
|
|
||||||
#: tiramisu/option.py:833
|
#: tiramisu/option.py:879
|
||||||
msgid "master group {0} shall not have a subgroup"
|
msgid "master group {0} shall not have a subgroup"
|
||||||
msgstr "groupe maître {0} ne doit pas avoir de sous-groupe"
|
msgstr "groupe maître {0} ne doit pas avoir de sous-groupe"
|
||||||
|
|
||||||
#: tiramisu/option.py:836
|
#: tiramisu/option.py:882
|
||||||
msgid "master group {0} shall not have a symlinkoption"
|
msgid "master group {0} shall not have a symlinkoption"
|
||||||
msgstr "groupe maître {0} ne doit pas avoir de symlinkoption"
|
msgstr "groupe maître {0} ne doit pas avoir de symlinkoption"
|
||||||
|
|
||||||
#: tiramisu/option.py:839
|
#: tiramisu/option.py:885
|
||||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"option non autorisée {0} dans le groupe {1} : cette option n'est pas une "
|
"option non autorisée {0} dans le groupe {1} : cette option n'est pas une "
|
||||||
"multi"
|
"multi"
|
||||||
|
|
||||||
#: tiramisu/option.py:849
|
#: tiramisu/option.py:896
|
||||||
msgid "master group with wrong master name for {0}"
|
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 éroné pour {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:857
|
#: tiramisu/option.py:905
|
||||||
msgid "no child has same nom has master group for: {0}"
|
msgid "no child has same nom has master group for: {0}"
|
||||||
msgstr "pas d'enfant avec le nom du groupe maître pour {0} "
|
msgstr "pas d'enfant avec le nom du groupe maître pour {0} "
|
||||||
|
|
||||||
#: tiramisu/option.py:860
|
#: tiramisu/option.py:908
|
||||||
msgid "not allowed group_type : {0}"
|
msgid "group_type: {0} not allowed"
|
||||||
msgstr "group_type non autorisé : {0}"
|
msgstr "group_type : {0} non autorisé"
|
||||||
|
|
||||||
#: tiramisu/option.py:889
|
#: tiramisu/option.py:946
|
||||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
|
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
|
||||||
|
|
||||||
#: tiramisu/option.py:905
|
#: tiramisu/option.py:962
|
||||||
msgid ""
|
msgid ""
|
||||||
"malformed requirements for option: {0} require must have option, expected "
|
"malformed requirements for option: {0} require must have option, expected "
|
||||||
"and action keys"
|
"and action keys"
|
||||||
|
@ -301,68 +294,87 @@ msgstr ""
|
||||||
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
|
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
|
||||||
"option, exptected et action"
|
"option, exptected et action"
|
||||||
|
|
||||||
#: tiramisu/option.py:910
|
#: tiramisu/option.py:967
|
||||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
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 malformé pour l'option : {0} inverse doit être un booléen"
|
||||||
|
|
||||||
#: tiramisu/option.py:914
|
#: tiramisu/option.py:971
|
||||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||||
msgstr "requirements malformé pour l'option : {0} transitive doit être booléen"
|
msgstr "requirements malformé pour l'option : {0} transitive doit être booléen"
|
||||||
|
|
||||||
#: tiramisu/option.py:918
|
#: tiramisu/option.py:975
|
||||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"requirements malformé pour l'option : {0} same_action doit être un booléen"
|
"requirements malformé pour l'option : {0} same_action doit être un booléen"
|
||||||
|
|
||||||
#: tiramisu/option.py:923
|
#: tiramisu/option.py:979
|
||||||
msgid "malformed requirements must be an option in option {0}"
|
msgid "malformed requirements must be an option in option {0}"
|
||||||
msgstr "requirements malformé doit être une option dans l'option {0}"
|
msgstr "requirements malformé doit être une option dans l'option {0}"
|
||||||
|
|
||||||
#: tiramisu/option.py:926
|
#: tiramisu/option.py:982
|
||||||
msgid "malformed requirements option {0} should not be a multi"
|
msgid "malformed requirements option {0} should not be a multi"
|
||||||
msgstr "requirements malformé l'option {0} ne doit pas être une multi"
|
msgstr "requirements malformé l'option {0} ne doit pas être une multi"
|
||||||
|
|
||||||
#: tiramisu/option.py:932
|
#: tiramisu/option.py:988
|
||||||
msgid ""
|
msgid ""
|
||||||
"malformed requirements second argument must be valid for option {0}: {1}"
|
"malformed requirements second argument must be valid for option {0}: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"requirements malformé deuxième argument doit être valide pour l'option {0} : "
|
"requirements malformé deuxième argument doit être valide pour l'option {0} : "
|
||||||
"{1}"
|
"{1}"
|
||||||
|
|
||||||
#: tiramisu/option.py:936
|
#: tiramisu/option.py:993
|
||||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||||
msgstr "incohérence dans les types action pour l'option : {0} action {1}"
|
msgstr "incohérence dans les types action pour l'option : {0} action {1}"
|
||||||
|
|
||||||
#: tiramisu/setting.py:45
|
#: tiramisu/setting.py:47
|
||||||
msgid "can't rebind group ({})"
|
msgid "storage_type is already set, cannot rebind it"
|
||||||
msgstr "ne peut reconsolider un groupe ({0})"
|
msgstr "storage_type est déjà défini, impossible de le redéfinir"
|
||||||
|
|
||||||
#: tiramisu/setting.py:50
|
#: tiramisu/setting.py:67
|
||||||
msgid "can't unbind group ({})"
|
msgid "can't rebind {0}"
|
||||||
msgstr "ne peut délier un groupe ({0})"
|
msgstr "ne peut redéfinir ({0})"
|
||||||
|
|
||||||
#: tiramisu/setting.py:210
|
#: tiramisu/setting.py:72
|
||||||
|
msgid "can't unbind {0}"
|
||||||
|
msgstr "ne peut supprimer ({0})"
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:185
|
||||||
|
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
|
||||||
msgid "opt and all_properties must not be set together in reset"
|
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"
|
msgstr "opt et all_properties ne doit pas être renseigné ensemble dans reset"
|
||||||
|
|
||||||
#: tiramisu/setting.py:294
|
#: tiramisu/setting.py:297
|
||||||
|
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
|
||||||
msgid "cannot change the value for option {0} this option is frozen"
|
msgid "cannot change the value for option {0} this option is frozen"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ne peut modifié la valeur de l'option {0} cette option n'est pas modifiable"
|
"ne peut modifié la valeur de l'option {0} cette option n'est pas modifiable"
|
||||||
|
|
||||||
#: tiramisu/setting.py:298
|
#: tiramisu/setting.py:397
|
||||||
msgid "trying to access to an option named: {0} with properties {1}"
|
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}"
|
msgstr "tentative d'accès à une option nommée : {0} avec les propriétés {1}"
|
||||||
|
|
||||||
#: tiramisu/setting.py:307
|
#: tiramisu/setting.py:415
|
||||||
msgid "permissive must be a tuple"
|
msgid "permissive must be a tuple"
|
||||||
msgstr "permissive doit être un tuple"
|
msgstr "permissive doit être un tuple"
|
||||||
|
|
||||||
#: tiramisu/setting.py:314 tiramisu/value.py:208
|
#: tiramisu/setting.py:422 tiramisu/value.py:277
|
||||||
msgid "invalid generic owner {0}"
|
msgid "invalid generic owner {0}"
|
||||||
msgstr "invalide owner générique {0}"
|
msgstr "invalide owner générique {0}"
|
||||||
|
|
||||||
#: tiramisu/setting.py:367
|
#: tiramisu/setting.py:503
|
||||||
msgid ""
|
msgid ""
|
||||||
"malformed requirements imbrication detected for option: '{0}' with "
|
"malformed requirements imbrication detected for option: '{0}' with "
|
||||||
"requirement on: '{1}'"
|
"requirement on: '{1}'"
|
||||||
|
@ -370,48 +382,81 @@ msgstr ""
|
||||||
"imbrication de requirements malformé detectée pour l'option : '{0}' avec "
|
"imbrication de requirements malformé detectée pour l'option : '{0}' avec "
|
||||||
"requirement sur : '{1}'"
|
"requirement sur : '{1}'"
|
||||||
|
|
||||||
#: tiramisu/setting.py:377
|
#: tiramisu/setting.py:515
|
||||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
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}"
|
msgstr "l'option '{0}' a une erreur de propriété pour le requirement : {1} {2}"
|
||||||
|
|
||||||
#: tiramisu/setting.py:383
|
#: tiramisu/storage/dictionary/storage.py:37
|
||||||
msgid "required option not found: {0}"
|
msgid "dictionary storage cannot delete session"
|
||||||
msgstr "option requise non trouvée : {0}"
|
msgstr ""
|
||||||
|
"impossible de supprimer une session dans un espace de stockage dictionary"
|
||||||
|
|
||||||
#: tiramisu/value.py:206
|
#: tiramisu/storage/dictionary/storage.py:46
|
||||||
|
msgid "session already used"
|
||||||
|
msgstr "session déjà utilisée"
|
||||||
|
|
||||||
|
#: tiramisu/storage/dictionary/storage.py:48
|
||||||
|
msgid "a dictionary cannot be persistent"
|
||||||
|
msgstr "un espace de stockage dictionary ne peut être persistant"
|
||||||
|
|
||||||
|
#: tiramisu/value.py:284
|
||||||
msgid "no value for {0} cannot change owner to {1}"
|
msgid "no value for {0} cannot change owner to {1}"
|
||||||
msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
|
msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
|
||||||
|
|
||||||
#: tiramisu/value.py:270
|
#: tiramisu/value.py:356
|
||||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
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"
|
msgstr "longueur invalide pour une esclave : {0} qui a {1} comme maître"
|
||||||
|
|
||||||
#: tiramisu/value.py:286
|
#: tiramisu/value.py:373
|
||||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"longueur invalide pour un maître : {0} qui a {1} une esclave avec une plus "
|
"longueur invalide pour un maître : {0} qui a {1} une esclave avec une plus "
|
||||||
"grande longueur"
|
"grande longueur"
|
||||||
|
|
||||||
#: tiramisu/value.py:306
|
#: tiramisu/value.py:394
|
||||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
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"
|
msgstr "ne peut ajouter une valeur sur l'option multi {0} qui est une esclave"
|
||||||
|
|
||||||
#: tiramisu/value.py:334
|
#: tiramisu/value.py:429
|
||||||
msgid "cannot sort multi option {0} if master or slave"
|
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"
|
msgstr "ne peut trier une option multi {0} pour une maître ou une esclave"
|
||||||
|
|
||||||
#: tiramisu/value.py:342
|
#: tiramisu/value.py:433
|
||||||
|
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
|
||||||
msgid "cannot reverse multi option {0} if master or slave"
|
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"
|
msgstr "ne peut inverser une option multi {0} pour une maître ou une esclave"
|
||||||
|
|
||||||
#: tiramisu/value.py:350
|
#: tiramisu/value.py:450
|
||||||
msgid "cannot insert multi option {0} if master or slave"
|
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"
|
msgstr "ne peut insérer une option multi {0} pour une maître ou une esclave"
|
||||||
|
|
||||||
#: tiramisu/value.py:358
|
#: tiramisu/value.py:458
|
||||||
msgid "cannot extend multi option {0} if master or slave"
|
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"
|
msgstr "ne peut étendre une option multi {0} pour une maître ou une esclave"
|
||||||
|
|
||||||
#: tiramisu/value.py:381
|
#: tiramisu/value.py:482
|
||||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
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"
|
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 "metaconfig's children must be config, not {0}"
|
||||||
|
#~ msgstr "enfants d'une metaconfig doit être une config, pas {0}"
|
||||||
|
|
||||||
|
#~ msgid "all config in metaconfig must have same optiondescription"
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "toutes les configs d'une metaconfig doivent avoir la même "
|
||||||
|
#~ "optiondescription"
|
||||||
|
|
||||||
|
#~ msgid "child has already a metaconfig's"
|
||||||
|
#~ msgstr "enfant a déjà une metaconfig"
|
||||||
|
|
||||||
|
#~ msgid "not allowed group_type : {0}"
|
||||||
|
#~ msgstr "group_type non autorisé : {0}"
|
||||||
|
|
||||||
|
#~ msgid "required option not found: {0}"
|
||||||
|
#~ msgstr "option requise non trouvée : {0}"
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"POT-Creation-Date: 2013-07-18 15:20+CEST\n"
|
"POT-Creation-Date: 2013-09-02 11:30+CEST\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -15,375 +15,395 @@ msgstr ""
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:49
|
#: tiramisu/autolib.py:58
|
||||||
msgid "no config specified but needed"
|
msgid "no config specified but needed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/autolib.py:56
|
#: tiramisu/autolib.py:65
|
||||||
msgid "unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
msgid "unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/autolib.py:65
|
#: tiramisu/autolib.py:74
|
||||||
msgid "unable to carry out a calculation, option value with multi types must have same length for: {0}"
|
msgid "unable to carry out a calculation, option value with multi types must have same length for: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:45
|
#: tiramisu/config.py:47
|
||||||
msgid "descr must be an optiondescription, not {0}"
|
msgid "descr must be an optiondescription, not {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:118
|
#: tiramisu/config.py:121
|
||||||
msgid "unknown group_type: {0}"
|
msgid "unknown group_type: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:154
|
#: tiramisu/config.py:157
|
||||||
msgid "no optiondescription for this config (may be metaconfig without meta)"
|
msgid "no option description found for this config (may be metaconfig without meta)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:312
|
#: tiramisu/config.py:311
|
||||||
msgid "unknown type_ type {0} for _find"
|
msgid "unknown type_ type {0}for _find"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:351
|
#: tiramisu/config.py:350
|
||||||
msgid "no option found in config with these criteria"
|
msgid "no option found in config with these criteria"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:394
|
#: tiramisu/config.py:400
|
||||||
msgid "make_dict can't filtering with value without option"
|
msgid "make_dict can't filtering with value without option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:414
|
#: tiramisu/config.py:421
|
||||||
msgid "unexpected path {0}, should start with {1}"
|
msgid "unexpected path {0}, should start with {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:527
|
#: tiramisu/config.py:481
|
||||||
msgid "metaconfig's children must be a list"
|
msgid "opt in getowner must be an option not {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/config.py:532
|
#: tiramisu/option.py:71
|
||||||
msgid "metaconfig's children must be config, not {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:537
|
|
||||||
msgid "all config in metaconfig must have same optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:540
|
|
||||||
msgid "child has already a metaconfig's"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option.py:70
|
|
||||||
msgid "{0} has no attribute impl_set_information"
|
msgid "{0} has no attribute impl_set_information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:84
|
#: tiramisu/option.py:86
|
||||||
msgid "Information's item not found: {0}"
|
msgid "information's item not found: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:86
|
#: tiramisu/option.py:89
|
||||||
msgid "{0} has no attribute impl_get_information"
|
msgid "{0} has no attribute impl_get_information"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:124
|
#: tiramisu/option.py:117
|
||||||
|
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option.py:208
|
||||||
msgid "invalid name: {0} for option"
|
msgid "invalid name: {0} for option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:134
|
#: tiramisu/option.py:218
|
||||||
msgid "validator must be a function"
|
msgid "validator must be a function"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:141
|
#: tiramisu/option.py:225
|
||||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:147
|
#: tiramisu/option.py:231
|
||||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:150
|
#: tiramisu/option.py:236
|
||||||
msgid "default value not allowed if option: {0} is calculated"
|
msgid "default value not allowed if option: {0} is calculated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:153
|
#: tiramisu/option.py:239
|
||||||
msgid "params defined for a callback function but no callback defined yet for option {0}"
|
msgid "params defined for a callback function but no callback defined yet for option {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:174 tiramisu/option.py:718
|
#: tiramisu/option.py:261 tiramisu/option.py:809
|
||||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:273
|
#: tiramisu/option.py:334
|
||||||
msgid "invalid value {0} for option {1} for object {2}"
|
msgid "invalid value {0} for option {1} for object {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:278 tiramisu/value.py:368
|
#: tiramisu/option.py:342 tiramisu/value.py:468
|
||||||
msgid "invalid value {0} for option {1}: {2}"
|
msgid "invalid value {0} for option {1}: {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:290
|
#: tiramisu/option.py:354
|
||||||
msgid "invalid value {0} for option {1} which must be a list"
|
msgid "invalid value {0} for option {1} which must be a list"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:354
|
#: tiramisu/option.py:423
|
||||||
msgid "invalid value {0} for option {1} must be different as {2} option"
|
msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:376
|
#: tiramisu/option.py:445
|
||||||
msgid "values must be a tuple for {0}"
|
msgid "values must be a tuple for {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:379
|
#: tiramisu/option.py:448
|
||||||
msgid "open_values must be a boolean for {0}"
|
msgid "open_values must be a boolean for {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:400
|
#: tiramisu/option.py:469
|
||||||
msgid "value {0} is not permitted, only {1} is allowed"
|
msgid "value {0} is not permitted, only {1} is allowed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:411
|
#: tiramisu/option.py:481
|
||||||
msgid "value must be a boolean"
|
msgid "value must be a boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:421
|
#: tiramisu/option.py:491
|
||||||
msgid "value must be an integer"
|
msgid "value must be an integer"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:431
|
#: tiramisu/option.py:501
|
||||||
msgid "value must be a float"
|
msgid "value must be a float"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:441
|
#: tiramisu/option.py:511
|
||||||
msgid "value must be a string"
|
msgid "value must be a string, not {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:452
|
#: tiramisu/option.py:529
|
||||||
msgid "value must be an unicode"
|
msgid "value must be an unicode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:463
|
#: tiramisu/option.py:539
|
||||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:497
|
#: tiramisu/option.py:581
|
||||||
msgid "IP mustn't not be in reserved class"
|
msgid "IP shall not be in reserved class"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:499
|
#: tiramisu/option.py:583
|
||||||
msgid "IP must be in private class"
|
msgid "IP must be in private class"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:535
|
#: tiramisu/option.py:621
|
||||||
msgid "inconsistency in allowed range"
|
msgid "inconsistency in allowed range"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:540
|
#: tiramisu/option.py:626
|
||||||
msgid "max value is empty"
|
msgid "max value is empty"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:576
|
#: tiramisu/option.py:663
|
||||||
msgid "network mustn't not be in reserved class"
|
msgid "network shall not be in reserved class"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:608
|
#: tiramisu/option.py:695
|
||||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:612
|
#: tiramisu/option.py:700
|
||||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:617
|
#: tiramisu/option.py:705
|
||||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:619
|
#: tiramisu/option.py:707
|
||||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:639
|
#: tiramisu/option.py:727
|
||||||
msgid "unknown type_ {0} for hostname"
|
msgid "unknown type_ {0} for hostname"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:642
|
#: tiramisu/option.py:730
|
||||||
msgid "allow_ip must be a boolean"
|
msgid "allow_ip must be a boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:671
|
#: tiramisu/option.py:759
|
||||||
msgid "invalid value for {0}, must have dot"
|
msgid "invalid value for {0}, must have dot"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:674
|
#: tiramisu/option.py:762
|
||||||
msgid "invalid domainname's length for {0} (max {1})"
|
msgid "invalid domainname's length for {0} (max {1})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:676
|
#: tiramisu/option.py:765
|
||||||
msgid "invalid domainname's length for {0} (min 2)"
|
msgid "invalid domainname's length for {0} (min 2)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:680
|
#: tiramisu/option.py:769
|
||||||
msgid "invalid domainname"
|
msgid "invalid domainname"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:696
|
#: tiramisu/option.py:787
|
||||||
msgid "invalid name: {0} for optiondescription"
|
msgid "invalid name: {0} for optiondescription"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:707
|
#: tiramisu/option.py:799
|
||||||
msgid "duplicate option name: {0}"
|
msgid "duplicate option name: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:731
|
#: tiramisu/option.py:825
|
||||||
msgid "unknown Option {0} in OptionDescription {1}"
|
msgid "unknown Option {0} in OptionDescription {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:795
|
#: tiramisu/option.py:874
|
||||||
msgid "duplicate option: {0}"
|
msgid "duplicate option: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:805
|
#: tiramisu/option.py:904
|
||||||
msgid "no option for path {0}"
|
msgid "no option for path {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:811
|
#: tiramisu/option.py:910
|
||||||
msgid "no option {0} found"
|
msgid "no option {0} found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:821
|
#: tiramisu/option.py:920
|
||||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:833
|
#: tiramisu/option.py:933
|
||||||
msgid "master group {0} shall not have a subgroup"
|
msgid "master group {0} shall not have a subgroup"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:836
|
#: tiramisu/option.py:936
|
||||||
msgid "master group {0} shall not have a symlinkoption"
|
msgid "master group {0} shall not have a symlinkoption"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:839
|
#: tiramisu/option.py:939
|
||||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:849
|
#: tiramisu/option.py:950
|
||||||
msgid "master group with wrong master name for {0}"
|
msgid "master group with wrong master name for {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:857
|
#: tiramisu/option.py:959
|
||||||
msgid "no child has same nom has master group for: {0}"
|
msgid "no child has same nom has master group for: {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:860
|
#: tiramisu/option.py:962
|
||||||
msgid "not allowed group_type : {0}"
|
msgid "group_type: {0} not allowed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:889
|
#: tiramisu/option.py:1021
|
||||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:905
|
#: tiramisu/option.py:1037
|
||||||
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
|
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:910
|
#: tiramisu/option.py:1042
|
||||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:914
|
#: tiramisu/option.py:1046
|
||||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:918
|
#: tiramisu/option.py:1050
|
||||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:923
|
#: tiramisu/option.py:1054
|
||||||
msgid "malformed requirements must be an option in option {0}"
|
msgid "malformed requirements must be an option in option {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:926
|
#: tiramisu/option.py:1057
|
||||||
msgid "malformed requirements option {0} should not be a multi"
|
msgid "malformed requirements option {0} should not be a multi"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:932
|
#: tiramisu/option.py:1063
|
||||||
msgid "malformed requirements second argument must be valid for option {0}: {1}"
|
msgid "malformed requirements second argument must be valid for option {0}: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/option.py:936
|
#: tiramisu/option.py:1068
|
||||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:45
|
#: tiramisu/setting.py:47
|
||||||
msgid "can't rebind group ({})"
|
msgid "storage_type is already set, cannot rebind it"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:50
|
#: tiramisu/setting.py:67
|
||||||
msgid "can't unbind group ({})"
|
msgid "can't rebind {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:210
|
#: tiramisu/setting.py:72
|
||||||
|
msgid "can't unbind {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:185
|
||||||
|
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
|
||||||
msgid "opt and all_properties must not be set together in reset"
|
msgid "opt and all_properties must not be set together in reset"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:294
|
#: tiramisu/setting.py:297
|
||||||
|
msgid "if opt is not None, path should not be None in _getproperties"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:391
|
||||||
msgid "cannot change the value for option {0} this option is frozen"
|
msgid "cannot change the value for option {0} this option is frozen"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:298
|
#: tiramisu/setting.py:397
|
||||||
msgid "trying to access to an option named: {0} with properties {1}"
|
msgid "trying to access to an option named: {0} with properties {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:307
|
#: tiramisu/setting.py:415
|
||||||
msgid "permissive must be a tuple"
|
msgid "permissive must be a tuple"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:314 tiramisu/value.py:208
|
#: tiramisu/setting.py:422 tiramisu/value.py:277
|
||||||
msgid "invalid generic owner {0}"
|
msgid "invalid generic owner {0}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:367
|
#: tiramisu/setting.py:503
|
||||||
msgid "malformed requirements imbrication detected for option: '{0}' with requirement on: '{1}'"
|
msgid "malformed requirements imbrication detected for option: '{0}' with requirement on: '{1}'"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:377
|
#: tiramisu/setting.py:515
|
||||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
msgid "option '{0}' has requirement's property error: {1} {2}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/setting.py:383
|
#: tiramisu/storage/dictionary/storage.py:37
|
||||||
msgid "required option not found: {0}"
|
msgid "dictionary storage cannot delete session"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:206
|
#: tiramisu/storage/dictionary/storage.py:46
|
||||||
|
msgid "session already used"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/storage/dictionary/storage.py:48
|
||||||
|
msgid "a dictionary cannot be persistent"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/value.py:284
|
||||||
msgid "no value for {0} cannot change owner to {1}"
|
msgid "no value for {0} cannot change owner to {1}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:270
|
#: tiramisu/value.py:356
|
||||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
msgid "invalid len for the slave: {0} which has {1} as master"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:286
|
#: tiramisu/value.py:373
|
||||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:306
|
#: tiramisu/value.py:394
|
||||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
msgid "cannot append a value on a multi option {0} which is a slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:334
|
#: tiramisu/value.py:429
|
||||||
msgid "cannot sort multi option {0} if master or slave"
|
msgid "cannot sort multi option {0} if master or slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:342
|
#: tiramisu/value.py:433
|
||||||
|
msgid "cmp is not permitted in python v3 or greater"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/value.py:442
|
||||||
msgid "cannot reverse multi option {0} if master or slave"
|
msgid "cannot reverse multi option {0} if master or slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:350
|
#: tiramisu/value.py:450
|
||||||
msgid "cannot insert multi option {0} if master or slave"
|
msgid "cannot insert multi option {0} if master or slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:358
|
#: tiramisu/value.py:458
|
||||||
msgid "cannot extend multi option {0} if master or slave"
|
msgid "cannot extend multi option {0} if master or slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tiramisu/value.py:381
|
#: tiramisu/value.py:482
|
||||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
msgid "cannot pop a value on a multi option {0} which is a slave"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue