Compare commits
No commits in common. "main" and "feature/5.0" have entirely different histories.
main
...
feature/5.
83 changed files with 11537 additions and 12755 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
*~
|
*~
|
||||||
*#
|
*#
|
||||||
*.pyc
|
*.pyc
|
||||||
|
*.mo
|
||||||
*.swp
|
*.swp
|
||||||
build/
|
build/
|
||||||
|
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -1,31 +1,3 @@
|
||||||
## 5.1.0rc0 (2024-11-06)
|
|
||||||
|
|
||||||
### Feat
|
|
||||||
|
|
||||||
- add min_len, max_len, forbidden_char for password option
|
|
||||||
|
|
||||||
## 5.0.0 (2024-11-01)
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- add changelog_merge_prerelease to commitizen
|
|
||||||
|
|
||||||
## 5.0.0rc0 (2024-11-01)
|
|
||||||
|
|
||||||
### Feat
|
|
||||||
|
|
||||||
- return propertyerror in function
|
|
||||||
- mandatory for a variable and replace suffix to identifier
|
|
||||||
- reorganise code
|
|
||||||
|
|
||||||
### Fix
|
|
||||||
|
|
||||||
- translation + black
|
|
||||||
- regexp tests
|
|
||||||
- update documentation
|
|
||||||
- better permissive support
|
|
||||||
- 4.1.0
|
|
||||||
|
|
||||||
## 4.0.2 (2024-02-20)
|
## 4.0.2 (2024-02-20)
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|
8
MANIFEST.in
Normal file
8
MANIFEST.in
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Include the README
|
||||||
|
include *.rst
|
||||||
|
|
||||||
|
# Include the license file
|
||||||
|
include LICENSE.txt
|
||||||
|
|
||||||
|
# Include the data files
|
||||||
|
recursive-include tiramisu *.py *.mo
|
18
README.md
18
README.md
|
@ -1,25 +1,13 @@
|
||||||
![Logo Tiramisu](logo.png "logo Tiramisu")
|
![Logo Tiramisu](logo.png "logo Tiramisu")
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
|
||||||
[Documentations](doc/README.md)
|
[Documentations](doc/README.md)
|
||||||
|
|
||||||
|
|
||||||
# LICENSES
|
# LICENSES
|
||||||
|
|
||||||
See [COPYING](COPYING) for the licences of the code and the documentation.
|
See COPYING for the licences of the code and the documentation.
|
||||||
|
|
||||||
See [AUTHORS](AUTHORS) for the details about the tiramisu's team.
|
See AUTHORS for the details about the tiramisu's team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -83,20 +83,20 @@ Here is how to print our :class:`Config` details:
|
||||||
|
|
||||||
Root config object that enables us to handle the configuration options
|
Root config object that enables us to handle the configuration options
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
forcepermissive Access to option without verifying permissive properties
|
||||||
|
unrestraint Access to option without property restriction
|
||||||
|
nowarnings Do not warnings during validation
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
description Get option description
|
cache Manage config cache
|
||||||
dict Convert config and option to tiramisu format
|
config Actions to Config
|
||||||
get Get Tiramisu option
|
information Manage config informations
|
||||||
has_dependency Test if option has dependency
|
option Select an option
|
||||||
isdynamic Test if option is a dynamic optiondescription
|
owner Global owner
|
||||||
isleadership Test if option is a leader or a follower
|
permissive Manage config permissives
|
||||||
isoptiondescription Test if option is an optiondescription
|
property Manage config properties
|
||||||
list List options (by default list only option)
|
value Manage config value
|
||||||
name Get option name
|
|
||||||
option Select an option by path
|
|
||||||
path Get option path
|
|
||||||
type Get de option type
|
|
||||||
updates Updates value with tiramisu format
|
|
||||||
|
|
||||||
Then let's print our :class:`Option` details.
|
Then let's print our :class:`Option` details.
|
||||||
|
|
||||||
|
@ -105,34 +105,15 @@ Then let's print our :class:`Option` details.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
Manage selected option
|
Select an option
|
||||||
|
|
||||||
|
Call: Select an option by path
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
dependencies Get dependencies from this option
|
|
||||||
description Get option description
|
|
||||||
dict Convert config and option to tiramisu format
|
dict Convert config and option to tiramisu format
|
||||||
extra Get de option extra
|
find Find an or a list of options
|
||||||
followers Get the followers option for a leadership
|
list List options (by default list only option)
|
||||||
get Get Tiramisu option
|
name get the name
|
||||||
group_type Get type for an optiondescription (only for optiondescription)
|
|
||||||
has_dependency Test if option has dependency
|
|
||||||
identifiers Get identifiers for dynamic option
|
|
||||||
index Get index of option
|
|
||||||
isdynamic Test if option is a dynamic optiondescription
|
|
||||||
isfollower Test if option is a follower
|
|
||||||
isleader Test if option is a leader
|
|
||||||
isleadership Test if option is a leader or a follower
|
|
||||||
ismulti Test if option could have multi value
|
|
||||||
isoptiondescription Test if option is an optiondescription
|
|
||||||
issubmulti Test if option could have submulti value
|
|
||||||
issymlinkoption Test if option is a symlink option
|
|
||||||
leader Get the leader option for a leadership or a follower option
|
|
||||||
list List options inside an option description (by default list only option)
|
|
||||||
name Get option name
|
|
||||||
option For OptionDescription get sub option, for symlinkoption get the linked option
|
|
||||||
path Get option path
|
|
||||||
pattern Get the option pattern
|
|
||||||
type Get de option type
|
|
||||||
updates Updates value with tiramisu format
|
updates Updates value with tiramisu format
|
||||||
|
|
||||||
Finaly, let's print the :class:`Config`.
|
Finaly, let's print the :class:`Config`.
|
||||||
|
@ -142,7 +123,7 @@ Finaly, let's print the :class:`Config`.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
<Config path=None>
|
<tiramisu.api.Config object at 0x7f3ee6204278>
|
||||||
|
|
||||||
:download:`download the getting started code <src/getting_started.py>`
|
:download:`download the getting started code <src/getting_started.py>`
|
||||||
|
|
||||||
|
|
|
@ -25,32 +25,26 @@ Dynamic option description is an :class:`OptionDescription` which multiplies acc
|
||||||
|
|
||||||
Note:: the option can be an :doc:`option` or an other option description
|
Note:: the option can be an :doc:`option` or an other option description
|
||||||
|
|
||||||
* - identifiers
|
* - suffixes
|
||||||
- Identifiers is a :doc:`calculation` that return the list of identifiers used to create dynamic option description.
|
- Suffixes is a :doc:`calculation` that return the list of suffixes used to create dynamic option description.
|
||||||
|
|
||||||
* - properties
|
* - properties
|
||||||
- A list of :doc:`property` (inside a frozenset().
|
- A list of :doc:`property` (inside a frozenset().
|
||||||
|
|
||||||
* - informations
|
|
||||||
- We can add default informations to this option description.
|
|
||||||
|
|
||||||
* - group_type
|
|
||||||
- Type for this group.
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
==============
|
==============
|
||||||
|
|
||||||
Let's try:
|
Let's try:
|
||||||
|
|
||||||
>>> from tiramisu import StrOption, DynOptionDescription, Calculation
|
>>> from tiramisu import StrOption, DynOptionDescription, Calculation
|
||||||
>>> def return_identifiers():
|
>>> def return_suffixes():
|
||||||
... return ['1', '2']
|
... return ['1', '2']
|
||||||
>>> child1 = StrOption('first', 'First basic option ')
|
>>> child1 = StrOption('first', 'First basic option ')
|
||||||
>>> child2 = StrOption('second', 'Second basic option ')
|
>>> child2 = StrOption('second', 'Second basic option ')
|
||||||
>>> DynOptionDescription('basic ',
|
>>> DynOptionDescription('basic ',
|
||||||
... 'Basic options ',
|
... 'Basic options ',
|
||||||
... [child1, child2],
|
... [child1, child2],
|
||||||
... Calculation(return_identifiers))
|
... Calculation(return_suffixes))
|
||||||
|
|
||||||
This example will construct:
|
This example will construct:
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,6 @@ The leadership
|
||||||
* - properties
|
* - properties
|
||||||
- A list of :doc:`property` (inside a frozenset().
|
- A list of :doc:`property` (inside a frozenset().
|
||||||
|
|
||||||
* - informations
|
|
||||||
- We can add default informations to this option description.
|
|
||||||
|
|
||||||
Example
|
Example
|
||||||
====================
|
====================
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ Option
|
||||||
* - doc
|
* - doc
|
||||||
- The `description` allows the user to understand where this option will be used for.
|
- The `description` allows the user to understand where this option will be used for.
|
||||||
|
|
||||||
|
* - multi
|
||||||
|
- There are cases where it can be interesting to have a list of values rather than just one.
|
||||||
|
|
||||||
* - default
|
* - default
|
||||||
- For each option, we can defined a default value. This value will be the value of this option until user customize it.
|
- For each option, we can defined a default value. This value will be the value of this option until user customize it.
|
||||||
|
|
||||||
|
@ -32,20 +35,14 @@ Option
|
||||||
|
|
||||||
The default_multi value can be a :doc:`calculation`.
|
The default_multi value can be a :doc:`calculation`.
|
||||||
|
|
||||||
* - multi
|
|
||||||
- There are cases where it can be interesting to have a list of values rather than just one.
|
|
||||||
|
|
||||||
* - validators
|
* - validators
|
||||||
- A list of :doc:`validator`.
|
- A list of :doc:`validator`.
|
||||||
|
|
||||||
* - properties
|
|
||||||
- A list of :doc:`property` (inside a frozenset().
|
|
||||||
|
|
||||||
* - warnings_only
|
* - warnings_only
|
||||||
- Only emit warnings if not type validation is invalid.
|
- Only emit warnings if not type validation is invalid.
|
||||||
|
|
||||||
* - informations
|
* - properties
|
||||||
- We can add default informations to this option.
|
- A list of :doc:`property` (inside a frozenset().
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
|
|
|
@ -25,12 +25,6 @@ Option description
|
||||||
* - properties
|
* - properties
|
||||||
- A list of :doc:`property` (inside a frozenset().
|
- A list of :doc:`property` (inside a frozenset().
|
||||||
|
|
||||||
* - informations
|
|
||||||
- We can add default informations to this option description.
|
|
||||||
|
|
||||||
* - group_type
|
|
||||||
- Type for this group.
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ Network options
|
||||||
-
|
-
|
||||||
|
|
||||||
* - BroadcastOption
|
* - BroadcastOption
|
||||||
- The last address within a network broadcast transmission to all hosts on the link. This option allow you to enter a broadcast.
|
- The last address within a network broadcast transmission to all hosts on the link. This option allow you to enter a broadcast:
|
||||||
-
|
-
|
||||||
|
|
||||||
* - PortOption
|
* - PortOption
|
||||||
|
@ -114,10 +114,6 @@ Network options
|
||||||
- allow_wellknown: by default, the well-known ports (also known as system ports) those from 1 through 1023 are allowed, you can disabled it
|
- allow_wellknown: by default, the well-known ports (also known as system ports) those from 1 through 1023 are allowed, you can disabled it
|
||||||
- allow_registred: by default, the registered ports are those from 1024 through 49151 are allowed, you can disabled it
|
- allow_registred: by default, the registered ports are those from 1024 through 49151 are allowed, you can disabled it
|
||||||
- allow_private: allow dynamic or private ports, which are those from 49152 through 65535, one common use for this range is for ephemeral ports
|
- allow_private: allow dynamic or private ports, which are those from 49152 through 65535, one common use for this range is for ephemeral ports
|
||||||
- allow_protocol: allow to define protocol in value, it should be something like tcp:80 or udp:53
|
|
||||||
|
|
||||||
* - MACOption
|
|
||||||
- MAC address for a network card.
|
|
||||||
|
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
|
@ -280,35 +276,18 @@ Unix options
|
||||||
|
|
||||||
* - Type
|
* - Type
|
||||||
- Comments
|
- Comments
|
||||||
- Extra parameters
|
|
||||||
|
|
||||||
* - UsernameOption
|
* - UsernameOption
|
||||||
- An unix username option is a 32 characters maximum length with lowercase ASCII characters, number, '_' or '-'. The username have to start with lowercase ASCII characters or "_".
|
- An unix username option is a 32 characters maximum length with lowercase ASCII characters, number, '_' or '-'. The username have to start with lowercase ASCII characters or "_".
|
||||||
-
|
|
||||||
|
|
||||||
* - GroupnameOption
|
* - GroupnameOption
|
||||||
- Same conditions has username
|
- Same conditions has username
|
||||||
-
|
|
||||||
|
|
||||||
* - PasswordOption
|
* - PasswordOption
|
||||||
- Simple string with no other restriction:
|
- Simple string with no other restriction:
|
||||||
-
|
|
||||||
- min_len: minimum length autorise for a password
|
|
||||||
- max_len: maximum length autorise for a passwword
|
|
||||||
- forbidden_char: list of forbidden characters for a password
|
|
||||||
|
|
||||||
* - FilenameOption
|
* - FilenameOption
|
||||||
- For this option, only lowercase and uppercas ASCII character, "-", ".", "_", "~", and "/" are allowed.
|
- For this option, only lowercase and uppercas ASCII character, "-", ".", "_", "~", and "/" are allowed.
|
||||||
-
|
|
||||||
- allow_relative: filename should starts with "/" (something like /etc/passwd), we can, with this option to allow relative name
|
|
||||||
- test_existence: file or directory should exists
|
|
||||||
- types
|
|
||||||
- file: it should be a file
|
|
||||||
- directory: it should be a directory
|
|
||||||
|
|
||||||
* - PermissionsOption
|
|
||||||
- Permissions for Unix file. It could be something like 644 or 1644.
|
|
||||||
-
|
|
||||||
|
|
||||||
>>> from tiramisu import UsernameOption
|
>>> from tiramisu import UsernameOption
|
||||||
>>> UsernameOption('user', 'user', 'my_user')
|
>>> UsernameOption('user', 'user', 'my_user')
|
||||||
|
|
|
@ -14,6 +14,6 @@ cfg = Config(descr)
|
||||||
# the global help about the config
|
# the global help about the config
|
||||||
cfg.help()
|
cfg.help()
|
||||||
# help about an option
|
# help about an option
|
||||||
cfg.option("bool").help()
|
cfg.option.help()
|
||||||
# the config's __repr__
|
# the config's __repr__
|
||||||
print(cfg)
|
print(cfg)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,823 +0,0 @@
|
||||||
# SOME DESCRIPTIVE TITLE.
|
|
||||||
# Copyright (C) YEAR ORGANIZATION
|
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
|
||||||
#
|
|
||||||
msgid ""
|
|
||||||
msgstr ""
|
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
|
||||||
"POT-Creation-Date: 2024-11-05 08:52+0100\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
|
||||||
"MIME-Version: 1.0\n"
|
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
|
||||||
"Generated-By: pygettext.py 1.5\n"
|
|
||||||
|
|
||||||
|
|
||||||
#: tiramisu/api.py:79
|
|
||||||
msgid "Settings:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:83
|
|
||||||
msgid "Access to option without verifying permissive properties"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:88
|
|
||||||
msgid "Access to option without property restriction"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:93
|
|
||||||
msgid "Do not warnings during validation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:97
|
|
||||||
msgid "Commands:"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:111 tiramisu/api.py:1840
|
|
||||||
msgid "please specify a valid sub function ({0}.{1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:194
|
|
||||||
msgid "please do not specify index ({0}.{1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:199 tiramisu/api.py:844
|
|
||||||
msgid "please specify index with a follower option ({0}.{1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:220
|
|
||||||
msgid "please specify a valid sub function ({0}.{1}): {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:431
|
|
||||||
msgid "the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:517
|
|
||||||
msgid "cannot get option from a follower symlink without index"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:592
|
|
||||||
msgid "cannot add this property: \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:619
|
|
||||||
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:623
|
|
||||||
msgid "cannot find \"{0}\" in option \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:628
|
|
||||||
msgid "cannot remove option's property \"{0}\", use permissive instead in option \"{1}\" at index \"{2}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:632
|
|
||||||
msgid "cannot find \"{0}\" in option \"{1}\" at index \"{2}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:676
|
|
||||||
msgid "cannot find \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:808
|
|
||||||
msgid "cannot reduce length of the leader {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:861
|
|
||||||
msgid "only multi value has defaultmulti"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:1020
|
|
||||||
msgid "please specify a valid sub function ({0}.{1}) for {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:1407
|
|
||||||
msgid "properties must be a frozenset"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:1411 tiramisu/api.py:1438
|
|
||||||
msgid "unknown when {} (must be in append or remove)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:1424 tiramisu/api.py:1448 tiramisu/config.py:1680
|
|
||||||
msgid "unknown type {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/api.py:1812
|
|
||||||
msgid "do not use unrestraint, nowarnings or forcepermissive together"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:80
|
|
||||||
msgid "args in params must be a tuple"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:83 tiramisu/autolib.py:88
|
|
||||||
msgid "arg in params must be a Param"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:85
|
|
||||||
msgid "kwargs in params must be a dict"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:113
|
|
||||||
msgid "paramoption needs an option not {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:119
|
|
||||||
msgid "param must have a boolean not a {} for notraisepropertyerror"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:122
|
|
||||||
msgid "param must have a boolean not a {} for raisepropertyerror"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:212
|
|
||||||
msgid "option in ParamInformation cannot be a symlinkoption"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:215
|
|
||||||
msgid "option in ParamInformation cannot be a follower"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:218
|
|
||||||
msgid "option in ParamInformation cannot be a dynamic option"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:279
|
|
||||||
msgid "first argument ({0}) must be a function"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:283
|
|
||||||
msgid "help_function ({0}) must be a function"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:452 tiramisu/autolib.py:514
|
|
||||||
msgid "unable to carry out a calculation for {}, {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:461 tiramisu/autolib.py:521
|
|
||||||
msgid "the option {0} is used in a calculation but is invalid ({1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:477 tiramisu/autolib.py:535 tiramisu/autolib.py:584
|
|
||||||
msgid "unable to get value for calculating {0}, {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:601
|
|
||||||
msgid "option {0} is not a dynoptiondescription or in a dynoptiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:848
|
|
||||||
msgid "the \"{}\" function with positional arguments \"{}\" and keyword arguments \"{}\" must not return a list (\"{}\") for the follower option {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:863
|
|
||||||
msgid "the \"{}\" function must not return a list (\"{}\") for the follower option {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:904
|
|
||||||
msgid "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and \"{4}\" for option {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/autolib.py:915
|
|
||||||
msgid "unexpected error \"{0}\" in function \"{1}\" for option {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:419
|
|
||||||
msgid "index \"{0}\" is greater than the leadership length \"{1}\" for option {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:579
|
|
||||||
msgid "there is no option description for this config (may be GroupConfig)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:668
|
|
||||||
msgid "no option found in config with these criteria"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:871
|
|
||||||
msgid "the follower option {0} has greater length ({1}) than the leader length ({2})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:982 tiramisu/option/optiondescription.py:74
|
|
||||||
msgid "option description seems to be part of an other config"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1144
|
|
||||||
msgid "parent of {0} not already exists"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1191
|
|
||||||
msgid "cannot set leadership object has root optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1194
|
|
||||||
msgid "cannot set dynoptiondescription object has root optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1246
|
|
||||||
msgid "config name must be uniq in groupconfig for \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1457
|
|
||||||
msgid "unknown config \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1482
|
|
||||||
msgid "child must be a Config, MixConfig or MetaConfig"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1517
|
|
||||||
msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1527
|
|
||||||
msgid "force_default and force_dont_change_value cannot be set together"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1676
|
|
||||||
msgid "config name must be uniq in groupconfig for {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1721
|
|
||||||
msgid "config added has no name, the name is mandatory"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1726
|
|
||||||
msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1744 tiramisu/config.py:1750
|
|
||||||
msgid "cannot find the config {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1776
|
|
||||||
msgid "MetaConfig with optiondescription must have string has child, not {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1788
|
|
||||||
msgid "child must be a Config or MetaConfig"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1793
|
|
||||||
msgid "all config in metaconfig must have the same optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/config.py:1810
|
|
||||||
msgid "metaconfig must have the same optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:31
|
|
||||||
msgid "and"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:33
|
|
||||||
msgid "or"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:55
|
|
||||||
msgid " {} "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:108
|
|
||||||
msgid "property"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:110
|
|
||||||
msgid "properties"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:113
|
|
||||||
msgid "cannot modify the {0} {1} because \"{2}\" has {3} {4}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:115
|
|
||||||
msgid "cannot modify the {0} {1} because has {2} {3}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:118
|
|
||||||
msgid "cannot access to {0} {1} because \"{2}\" has {3} {4}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:120
|
|
||||||
msgid "cannot access to {0} {1} because has {2} {3}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:192
|
|
||||||
msgid "invalid value"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:201
|
|
||||||
msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/error.py:219 tiramisu/error.py:228
|
|
||||||
msgid "\"{0}\" is an invalid {1} for \"{2}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:65
|
|
||||||
msgid "network \"{0}\" ({1}) does not match with this netmask"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:83
|
|
||||||
msgid "IP \"{0}\" ({1}) with this netmask is in fact a network address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:88
|
|
||||||
msgid "IP \"{0}\" ({1}) with this netmask is in fact a broadcast address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:106
|
|
||||||
msgid "broadcast invalid with network {0} ({1}) and netmask {2} ({3})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:134
|
|
||||||
msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:136
|
|
||||||
msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]}) with netmask {netmask[\"value\"]} ({netmask[\"name\"]})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:143
|
|
||||||
msgid "this IP with the network {0} ({1}) is in fact a network address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:148
|
|
||||||
msgid "this IP with the network {0} ({1}) is in fact a broadcast address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:165
|
|
||||||
msgid "value is identical to {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:400
|
|
||||||
msgid "unexpected value in calc_value with join attribute \"{0}\" with invalid length \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:527
|
|
||||||
msgid "unexpected {0} condition_operator in calc_value"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:591
|
|
||||||
msgid "unexpected condition_{0} must have \"todict\" argument"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:602
|
|
||||||
msgid "the value of \"{0}\" is {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/function.py:604
|
|
||||||
msgid "the value of \"{0}\" is not {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:75 tiramisu/option/symlinkoption.py:44
|
|
||||||
msgid "\"{0}\" is an invalid name for an option"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:88
|
|
||||||
msgid "invalid properties type {0} for {1}, must be a frozenset"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:98
|
|
||||||
msgid "invalid property type {0} for {1}, must be a string or a Calculation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:249
|
|
||||||
msgid "information's item for {0} not found: \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:267
|
|
||||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:308
|
|
||||||
msgid "\"{}\" ({}) object attribute \"{}\" is read-only"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/baseoption.py:320
|
|
||||||
msgid "{0} not part of any Config"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/broadcastoption.py:41
|
|
||||||
msgid "invalid string"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/choiceoption.py:47
|
|
||||||
msgid "values must be a tuple or a calculation for {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/choiceoption.py:70
|
|
||||||
msgid "the calculated values \"{0}\" for \"{1}\" is not a list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/choiceoption.py:101
|
|
||||||
msgid "only \"{0}\" is allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/choiceoption.py:103
|
|
||||||
msgid "only {0} are allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:60
|
|
||||||
msgid "unknown type {0} for hostname"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:63
|
|
||||||
msgid "allow_ip must be a boolean"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:65
|
|
||||||
msgid "allow_cidr_network must be a boolean"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:67
|
|
||||||
msgid "allow_without_dot must be a boolean"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:69
|
|
||||||
msgid "allow_startswith_dot must be a boolean"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:81
|
|
||||||
msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:84
|
|
||||||
msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are recommanded"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:88
|
|
||||||
#: tiramisu/option/domainnameoption.py:89
|
|
||||||
msgid "could be a IP, otherwise {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:134
|
|
||||||
msgid "invalid length (min 1)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:137
|
|
||||||
msgid "invalid length (max {0})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:143
|
|
||||||
msgid "must have dot"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:145
|
|
||||||
msgid "invalid length (max 255)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:163
|
|
||||||
msgid "must not be an IP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/domainnameoption.py:186
|
|
||||||
msgid "some characters are uppercase"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/dynoptiondescription.py:131
|
|
||||||
msgid "DynOptionDescription identifiers for option {0}, is not a list ({1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/dynoptiondescription.py:142
|
|
||||||
msgid "invalid identifier \"{}\" for option {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/dynoptiondescription.py:150
|
|
||||||
msgid "DynOptionDescription \"{0}\" identifiers return a list with same values \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/filenameoption.py:47
|
|
||||||
msgid "types parameter must be a list, not \"{0}\" for \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/filenameoption.py:67
|
|
||||||
msgid "must starts with \"/\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/filenameoption.py:78
|
|
||||||
msgid "cannot find {0} \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/intoption.py:52
|
|
||||||
msgid "value should be equal or greater than \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/intoption.py:54
|
|
||||||
msgid "value must be equal or greater than \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/intoption.py:59
|
|
||||||
msgid "value should be less than \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/intoption.py:61
|
|
||||||
msgid "value must be less than \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:57
|
|
||||||
msgid "it's in fact a network address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:59
|
|
||||||
msgid "it's in fact a broacast address"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:71
|
|
||||||
msgid "CIDR address must have a \"/\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:80
|
|
||||||
msgid "shouldn't be reserved IP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:82
|
|
||||||
msgid "mustn't be reserved IP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:86
|
|
||||||
msgid "should be private IP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/ipoption.py:88
|
|
||||||
msgid "must be private IP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:55
|
|
||||||
msgid "cannot set \"group_type\" attribute for a Leadership"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:67
|
|
||||||
msgid "a leader and a follower are mandatories in leadership \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:89
|
|
||||||
msgid "leader cannot have \"{}\" property"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:101
|
|
||||||
msgid "leadership {0} shall not have a symlinkoption"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:108
|
|
||||||
msgid "leadership {0} shall not have a subgroup"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:114
|
|
||||||
msgid "only multi option allowed in leadership {0} but option {1} is not a multi"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/leadership.py:141
|
|
||||||
msgid "not allowed default value for follower option {0} in leadership {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/networkoption.py:45
|
|
||||||
msgid "must use CIDR notation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/networkoption.py:60
|
|
||||||
msgid "shouldn't be reserved network"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/networkoption.py:62
|
|
||||||
msgid "mustn't be reserved network"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:73
|
|
||||||
msgid "default_multi is set whereas multi is False in option: {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:93
|
|
||||||
msgid "invalid multi type \"{}\" for \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:112
|
|
||||||
msgid "validators must be a list of Calculation for \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:117
|
|
||||||
msgid "validators must be a Calculation for \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:146
|
|
||||||
msgid "invalid default_multi value \"{0}\" for option {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:154
|
|
||||||
msgid "invalid default_multi value \"{0}\" for option {1}, {2}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:167
|
|
||||||
msgid "invalid default_multi value \"{0}\" for option {1}, must be a list for a submulti"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:290
|
|
||||||
msgid "the value \"{}\" is not unique"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:352
|
|
||||||
msgid "which must not be a list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:404 tiramisu/option/option.py:430
|
|
||||||
msgid "which must be a list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/option.py:424
|
|
||||||
msgid "which \"{}\" must be a list of list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:109
|
|
||||||
msgid "duplicate option: {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:244
|
|
||||||
msgid "unknown option \"{0}\" in root optiondescription (it's a dynamic option)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:279
|
|
||||||
msgid "unknown option \"{0}\" in root optiondescription"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:282
|
|
||||||
msgid "unknown option \"{0}\" in optiondescription {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:338
|
|
||||||
msgid "children in optiondescription \"{}\" must be a list"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:366
|
|
||||||
msgid "duplicate option name: \"{0}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:372
|
|
||||||
msgid "the option's name \"{0}\" start as the dynoptiondescription's name \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:415
|
|
||||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/optiondescription.py:420
|
|
||||||
msgid "group_type: {0} not allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/passwordoption.py:49
|
|
||||||
msgid "at least {0} characters are required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/passwordoption.py:52
|
|
||||||
msgid "maximum {0} characters required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/passwordoption.py:57
|
|
||||||
msgid "must not have the characters {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:52
|
|
||||||
msgid "only 3 or 4 octal digits are allowed"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:63
|
|
||||||
msgid "user"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:64
|
|
||||||
#: tiramisu/option/permissionsoption.py:66
|
|
||||||
msgid "group"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:67
|
|
||||||
msgid "other"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:68
|
|
||||||
msgid "{0} has more right than {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/permissionsoption.py:71
|
|
||||||
msgid "too weak"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:74
|
|
||||||
msgid "inconsistency in allowed range"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:79
|
|
||||||
msgid "max value is empty"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:92
|
|
||||||
msgid "range must have two values only"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:95
|
|
||||||
msgid "first port in range must be smaller than the second one"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:121
|
|
||||||
msgid "should be between {0} and {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/portoption.py:123
|
|
||||||
msgid "must be between {0} and {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/symlinkoption.py:51
|
|
||||||
msgid "malformed symlink second parameters must be an option for \"{0}\", not {1}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/urloption.py:91
|
|
||||||
msgid "must start with http:// or https://"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/option/urloption.py:119
|
|
||||||
msgid "must ends with a valid resource name"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:255
|
|
||||||
msgid "can't rebind {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:262
|
|
||||||
msgid "can't unbind {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:464
|
|
||||||
msgid "invalid property type {type(new_prop)} for {subconfig.option.impl_getname()} with {prop.function.__name__} function"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:476
|
|
||||||
msgid "leader cannot have \"{new_prop}\" property"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:564
|
|
||||||
msgid "leader cannot have \"{0}\" property"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:573
|
|
||||||
msgid "a leader ({0}) cannot have \"force_default_on_freeze\" or \"force_metaconfig_on_freeze\" property without \"frozen\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:607
|
|
||||||
msgid "permissive must be a frozenset"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:617
|
|
||||||
msgid "cannot add those permissives: {0}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:654
|
|
||||||
msgid "can't reset properties to the symlinkoption \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/setting.py:667
|
|
||||||
msgid "can't reset permissives to the symlinkoption \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:395
|
|
||||||
msgid "option {} only works when remotable is not \"none\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:561
|
|
||||||
msgid "unable to transform tiramisu object to dict: {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:876 tiramisu/todict.py:1033
|
|
||||||
msgid "unknown form {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:923
|
|
||||||
msgid "not in current area"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:947
|
|
||||||
msgid "only multi option can have action \"add\", but \"{}\" is not a multi"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/todict.py:953
|
|
||||||
msgid "unknown action {}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/value.py:564 tiramisu/value.py:861
|
|
||||||
msgid "set owner \"{0}\" is forbidden"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/value.py:571
|
|
||||||
msgid "\"{0}\" is a default value, so we cannot change owner to \"{1}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/value.py:740
|
|
||||||
msgid "index {index} is greater than the length {length} for option {subconfig.option.impl_get_display_name(with_quote=True)}"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: tiramisu/value.py:847
|
|
||||||
msgid "information's item not found \"{}\""
|
|
||||||
msgstr ""
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
[build-system]
|
|
||||||
build-backend = "flit_core.buildapi"
|
|
||||||
requires = ["flit_core >=3.8.0,<4"]
|
|
||||||
|
|
||||||
[project]
|
|
||||||
name = "tiramisu"
|
|
||||||
version = "5.1.0"
|
|
||||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
|
||||||
readme = "README.md"
|
|
||||||
description = "an options controller tool"
|
|
||||||
requires-python = ">=3.8"
|
|
||||||
license = {file = "LICENSE"}
|
|
||||||
classifiers = [
|
|
||||||
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"Programming Language :: Python :: 3.8",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Programming Language :: Python :: 3.11",
|
|
||||||
"Programming Language :: Python :: 3.12",
|
|
||||||
"Programming Language :: Python :: 3",
|
|
||||||
"Operating System :: OS Independent",
|
|
||||||
"Natural Language :: English",
|
|
||||||
"Natural Language :: French",
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
[project.urls]
|
|
||||||
Home = "https://forge.cloud.silique.fr/stove/tiramisu"
|
|
||||||
|
|
||||||
[tool.commitizen]
|
|
||||||
name = "cz_conventional_commits"
|
|
||||||
tag_format = "$version"
|
|
||||||
version_scheme = "pep440"
|
|
||||||
version_provider = "pep621"
|
|
||||||
#update_changelog_on_bump = true
|
|
||||||
changelog_merge_prerelease = true
|
|
52
setup.py
Normal file
52
setup.py
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from setuptools import setup
|
||||||
|
import os
|
||||||
|
from tiramisu import __version__
|
||||||
|
|
||||||
|
|
||||||
|
ORI_PACKAGE_NAME = 'tiramisu'
|
||||||
|
PACKAGE_NAME = os.environ.get('PACKAGE_DST', ORI_PACKAGE_NAME)
|
||||||
|
|
||||||
|
if PACKAGE_NAME != ORI_PACKAGE_NAME:
|
||||||
|
package_dir = {PACKAGE_NAME: ORI_PACKAGE_NAME}
|
||||||
|
else:
|
||||||
|
package_dir = None
|
||||||
|
|
||||||
|
setup(
|
||||||
|
version=__version__,
|
||||||
|
author="Tiramisu's team",
|
||||||
|
author_email='gnunux@gnunux.info',
|
||||||
|
name=PACKAGE_NAME,
|
||||||
|
description='an options controller tool',
|
||||||
|
url='https://framagit.org/tiramisu/tiramisu',
|
||||||
|
license='GNU Library or Lesser General Public License (LGPL)',
|
||||||
|
provides=['tiramisu_api'],
|
||||||
|
install_requires=['setuptools'],
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Natural Language :: English",
|
||||||
|
"Natural Language :: French",
|
||||||
|
],
|
||||||
|
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 3.5 or later.
|
||||||
|
""",
|
||||||
|
include_package_data=True,
|
||||||
|
package_dir=package_dir,
|
||||||
|
packages=[PACKAGE_NAME],
|
||||||
|
)
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"options.unicode": null
|
||||||
|
}
|
|
@ -32,9 +32,6 @@ def list_data(ext='.py'):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
# if filename.endswith(ext) and not filename.startswith('__'):
|
# if filename.endswith(ext) and not filename.startswith('__'):
|
||||||
if filename.endswith(ext) and not filename.startswith('__') and not 'not_equal' in filename and not 'callback' in filename and not filename == 'unicode2_copy.py' and not filename == 'unicode2_multi_copy.py':
|
if filename.endswith(ext) and not filename.startswith('__') and not 'not_equal' in filename and not 'callback' in filename and not filename == 'unicode2_copy.py' and not filename == 'unicode2_multi_copy.py':
|
||||||
# if 'leadership' in filename:
|
|
||||||
# print('FIXME')
|
|
||||||
# continue
|
|
||||||
ret.append(filename)
|
ret.append(filename)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
@ -61,7 +58,7 @@ def load_config(filename,
|
||||||
form.extend(mod.get_form(add_extra_od))
|
form.extend(mod.get_form(add_extra_od))
|
||||||
config.property.read_write()
|
config.property.read_write()
|
||||||
if root is None:
|
if root is None:
|
||||||
values = loads(dumps(config.dict(remotable=remote, clearable=clearable, form=form)))
|
values = loads(dumps(config.option.dict(remotable=remote, clearable=clearable, form=form)))
|
||||||
else:
|
else:
|
||||||
values = loads(dumps(config.option(root).dict(remotable=remote, clearable=clearable, form=form)))
|
values = loads(dumps(config.option(root).dict(remotable=remote, clearable=clearable, form=form)))
|
||||||
return values
|
return values
|
||||||
|
@ -383,12 +380,11 @@ def test_updates(filename_mod):
|
||||||
if dico_ori is None:
|
if dico_ori is None:
|
||||||
if clearable == 'minimum' and remote == 'minimum':
|
if clearable == 'minimum' and remote == 'minimum':
|
||||||
with open(join(datadir, modulepath + '.dict'), 'w') as fh:
|
with open(join(datadir, modulepath + '.dict'), 'w') as fh:
|
||||||
pouet
|
dump(config.value.dict(), fh, indent=2)
|
||||||
dump(config.value.get(), fh, indent=2)
|
|
||||||
else:
|
else:
|
||||||
assert config.value.get() == dico_ori, "clearable {}, remote: {}, filename: {}".format(clearable, remote, filename_mod)
|
assert config.value.dict() == dico_ori, "clearable {}, remote: {}, filename: {}".format(clearable, remote, filename_mod)
|
||||||
if root is None:
|
if root is None:
|
||||||
suboption = config
|
suboption = config.option
|
||||||
else:
|
else:
|
||||||
suboption = config.option(root)
|
suboption = config.option(root)
|
||||||
if with_model:
|
if with_model:
|
||||||
|
|
|
@ -81,10 +81,10 @@ def test_cache_importation_property():
|
||||||
def test_cache_importation_permissive():
|
def test_cache_importation_permissive():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.option('u2').permissive.add('prop')
|
cfg.option('u2').permissive.set(frozenset(['prop']))
|
||||||
export = cfg.permissive.exportation()
|
export = cfg.permissive.exportation()
|
||||||
assert cfg.option('u2').permissive.get() == {'prop'}
|
assert cfg.option('u2').permissive.get() == {'prop'}
|
||||||
cfg.option('u2').permissive.add('prop2')
|
cfg.option('u2').permissive.set(frozenset(['prop', 'prop2']))
|
||||||
assert cfg.option('u2').permissive.get() == {'prop', 'prop2'}
|
assert cfg.option('u2').permissive.get() == {'prop', 'prop2'}
|
||||||
cfg.permissive.importation(export)
|
cfg.permissive.importation(export)
|
||||||
assert cfg.option('u2').permissive.get() == {'prop'}
|
assert cfg.option('u2').permissive.get() == {'prop'}
|
||||||
|
@ -266,7 +266,7 @@ def test_cache_leadership():
|
||||||
#assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None]
|
#assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None]
|
||||||
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
|
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
|
||||||
cache = settings.get_cached()
|
cache = settings.get_cached()
|
||||||
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
||||||
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
||||||
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
||||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == {0}
|
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == {0}
|
||||||
|
@ -284,7 +284,7 @@ def test_cache_leadership():
|
||||||
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
|
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
|
||||||
#assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None
|
#assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None
|
||||||
cache = settings.get_cached()
|
cache = settings.get_cached()
|
||||||
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
||||||
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
||||||
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
||||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, 1])
|
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, 1])
|
||||||
|
@ -376,7 +376,8 @@ def test_cache_leader_and_followers():
|
||||||
idx_val2 = None
|
idx_val2 = None
|
||||||
values = cfg._config_bag.context._impl_values_cache
|
values = cfg._config_bag.context._impl_values_cache
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.properties_cache
|
||||||
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
|
compare(settings.get_cached(), {None: {None: (global_props, None)},
|
||||||
|
'val1': {None: (val1_props, None)},
|
||||||
'val1.val1': {None: (val1_val1_props, None)},
|
'val1.val1': {None: (val1_val1_props, None)},
|
||||||
})
|
})
|
||||||
# len is 0 so don't get any value
|
# len is 0 so don't get any value
|
||||||
|
@ -384,14 +385,17 @@ def test_cache_leader_and_followers():
|
||||||
#
|
#
|
||||||
cfg.option('val1.val1').value.set([None])
|
cfg.option('val1.val1').value.set([None])
|
||||||
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
||||||
compare(settings.get_cached(), {'val1.val1': {None: ({'empty', 'unique'}, None, True)}})
|
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
|
||||||
|
# 'val1.val1': {None: (val1_val1_props, None)},
|
||||||
|
})
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
#has value
|
#has value
|
||||||
idx_val2 = 0
|
idx_val2 = 0
|
||||||
val_val2 = None
|
val_val2 = None
|
||||||
val_val2_props = {idx_val2: (val1_val2_props, None)}
|
val_val2_props = {idx_val2: (val1_val2_props, None)}
|
||||||
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
|
compare(settings.get_cached(), {None: {None: (global_props, None)},
|
||||||
|
'val1': {None: (val1_props, None)},
|
||||||
'val1.val1': {None: (val1_val1_props, None)},
|
'val1.val1': {None: (val1_val1_props, None)},
|
||||||
'val1.val2': val_val2_props})
|
'val1.val2': val_val2_props})
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None)},
|
compare(values.get_cached(), {'val1.val1': {None: ([None], None)},
|
||||||
|
@ -400,7 +404,7 @@ def test_cache_leader_and_followers():
|
||||||
cfg.option('val1.val1').value.set([None, None])
|
cfg.option('val1.val1').value.set([None, None])
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
cfg.option('val1.val2', 1).value.set('oui')
|
cfg.option('val1.val2', 1).value.set('oui')
|
||||||
compare(settings.get_cached(), {})
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}})
|
||||||
compare(values.get_cached(), {'val1.val2': {1: ('oui', None, True)}})
|
compare(values.get_cached(), {'val1.val2': {1: ('oui', None, True)}})
|
||||||
val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)}
|
val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
@ -424,12 +428,15 @@ def test_cache_leader_callback():
|
||||||
val1_val2_props = frozenset(val1_val2_props)
|
val1_val2_props = frozenset(val1_val2_props)
|
||||||
values = cfg._config_bag.context._impl_values_cache
|
values = cfg._config_bag.context._impl_values_cache
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.properties_cache
|
||||||
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
|
compare(settings.get_cached(), {None: {None: (global_props, None)},
|
||||||
|
'val1': {None: (val1_props, None)},
|
||||||
'val1.val1': {None: (val1_val1_props, None)},
|
'val1.val1': {None: (val1_val1_props, None)},
|
||||||
})
|
})
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
|
||||||
cfg.option('val1.val1').value.set([None])
|
cfg.option('val1.val1').value.set([None])
|
||||||
compare(settings.get_cached(), {'val1.val1': {None: ({'unique', 'empty'}, None, True)}})
|
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
|
||||||
|
# 'val1.val1': {None: (val1_val1_props, None)},
|
||||||
|
})
|
||||||
|
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
|
@ -451,33 +458,38 @@ def test_cache_requires():
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.properties_cache
|
||||||
assert values.get_cached() == {}
|
assert values.get_cached() == {}
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.option('ip_address_service').value.set('1.1.1.1')
|
cfg.option('ip_address_service').value.set('1.1.1.1')
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)}})
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (True, None)}, 'ip_address_service': {None: ('1.1.1.1', None, True)}})
|
compare(values.get_cached(), {'activate_service': {None: (True, None)}, 'ip_address_service': {None: ('1.1.1.1', None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
|
compare(values.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.option('activate_service').value.set(False)
|
cfg.option('activate_service').value.set(False)
|
||||||
compare(settings.get_cached(), {})
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set(['disabled']), None)}})
|
'ip_address_service': {None: (set(['disabled']), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
||||||
|
@ -499,18 +511,21 @@ def test_cache_global_properties():
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.properties_cache
|
||||||
assert values.get_cached() == {}
|
assert values.get_cached() == {}
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.property.remove('disabled')
|
cfg.property.remove('disabled')
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
cfg.property.add('test')
|
cfg.property.add('test')
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
compare(settings.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test', 'force_store_value']), None)},
|
||||||
|
'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: (set([]), None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
|
from py.test import raises
|
||||||
|
|
||||||
from .autopath import do_autopath
|
from .autopath import do_autopath
|
||||||
do_autopath()
|
do_autopath()
|
||||||
from .config import config_type, get_config, value_list, global_owner, parse_od_get
|
from .config import config_type, get_config, value_list, global_owner
|
||||||
|
|
||||||
from pytest import raises
|
|
||||||
from tiramisu import ChoiceOption, StrOption, OptionDescription, Config, owners, Calculation, \
|
from tiramisu import ChoiceOption, StrOption, OptionDescription, Config, owners, Calculation, \
|
||||||
undefined, Params, ParamValue, ParamOption
|
undefined, Params, ParamValue, ParamOption
|
||||||
from tiramisu.error import ConfigError
|
from tiramisu.error import ConfigError
|
||||||
|
@ -72,30 +73,6 @@ def test_choiceoption_function(config_type):
|
||||||
assert cfg.option('choice').owner.isdefault()
|
assert cfg.option('choice').owner.isdefault()
|
||||||
#
|
#
|
||||||
assert value_list(cfg.option('choice').value.list()) == ('val1', 'val2')
|
assert value_list(cfg.option('choice').value.list()) == ('val1', 'val2')
|
||||||
assert isinstance(cfg.option('choice').value.list(uncalculated=True), Calculation)
|
|
||||||
# assert not list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_subfunction(config_type):
|
|
||||||
choice = ChoiceOption('choice', '', values=(Calculation(return_val, Params(ParamValue('val1'))), Calculation(return_val, Params(ParamValue('val2')))))
|
|
||||||
od1 = OptionDescription('od', '', [choice])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
owner = global_owner(cfg, config_type)
|
|
||||||
assert cfg.option('choice').owner.isdefault()
|
|
||||||
#
|
|
||||||
cfg.option('choice').value.set('val1')
|
|
||||||
assert cfg.option('choice').owner.get() == owner
|
|
||||||
#
|
|
||||||
cfg.option('choice').value.reset()
|
|
||||||
assert cfg.option('choice').owner.isdefault()
|
|
||||||
#
|
|
||||||
with raises(ValueError):
|
|
||||||
cfg.option('choice').value.set('no')
|
|
||||||
assert cfg.option('choice').owner.isdefault()
|
|
||||||
#
|
|
||||||
assert value_list(cfg.option('choice').value.list()) == ('val1', 'val2')
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,13 +262,3 @@ def test_choiceoption_calc_not_list():
|
||||||
with raises(ConfigError):
|
with raises(ConfigError):
|
||||||
cfg.option('choice').value.set(['val1'])
|
cfg.option('choice').value.set(['val1'])
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_calc_default_value():
|
|
||||||
var1 = StrOption("var1", '', default="val1")
|
|
||||||
var2 = StrOption("var2", '', default="val2")
|
|
||||||
choice = ChoiceOption("choice", '', values=(Calculation(return_val, Params((ParamOption(var1)))), Calculation(return_val, Params((ParamOption(var2))))), default="val1")
|
|
||||||
od2 = OptionDescription("rougail", '', children=[var1, var2, choice])
|
|
||||||
od1 = OptionDescription("baseoption", "", children=[od2])
|
|
||||||
cfg = Config(od1)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'rougail.var1': 'val1', 'rougail.var2': 'val2', 'rougail.choice': 'val1'}
|
|
||||||
|
|
|
@ -9,14 +9,10 @@ do_autopath()
|
||||||
from .config import config_type, get_config, value_list, global_owner
|
from .config import config_type, get_config, value_list, global_owner
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from tiramisu import Config, Calculation, Params, ParamSelfInformation, calc_value
|
from tiramisu import Config
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu import Config, IntOption, FloatOption, ChoiceOption, \
|
from tiramisu import Config, IntOption, FloatOption, ChoiceOption, \
|
||||||
BoolOption, StrOption, SymLinkOption, OptionDescription, undefined, \
|
BoolOption, StrOption, SymLinkOption, OptionDescription, undefined
|
||||||
DomainnameOption, EmailOption, URLOption, RegexpOption, IPOption, \
|
|
||||||
PortOption, NetworkOption, NetmaskOption, BroadcastOption, UsernameOption, \
|
|
||||||
GroupnameOption, DateOption, FilenameOption, PasswordOption, MACOption, \
|
|
||||||
PermissionsOption
|
|
||||||
from tiramisu.error import ConflictError, ConfigError, PropertiesOptionError
|
from tiramisu.error import ConflictError, ConfigError, PropertiesOptionError
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,7 +26,8 @@ def make_description():
|
||||||
floatoption = FloatOption('float', 'Test float option', default=2.3)
|
floatoption = FloatOption('float', 'Test float option', default=2.3)
|
||||||
stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', ))
|
stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', ))
|
||||||
boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',))
|
boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',))
|
||||||
wantref_option = BoolOption('wantref', 'Test requires', default=False, informations={'info': 'default value'})
|
wantref_option = BoolOption('wantref', 'Test requires', default=False)
|
||||||
|
wantref_option.impl_set_information('info', 'default value')
|
||||||
wantframework_option = BoolOption('wantframework', 'Test requires',
|
wantframework_option = BoolOption('wantframework', 'Test requires',
|
||||||
default=False)
|
default=False)
|
||||||
|
|
||||||
|
@ -133,29 +130,6 @@ def test_not_valid_properties():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_information_load():
|
|
||||||
ChoiceOption('a', '', ('a', 'b'), informations={'info': 'value'})
|
|
||||||
BoolOption('a', '', informations={'info': 'value'})
|
|
||||||
IntOption('a', '', informations={'info': 'value'})
|
|
||||||
FloatOption('a', '', informations={'info': 'value'})
|
|
||||||
StrOption('a', '', informations={'info': 'value'})
|
|
||||||
RegexpOption('a', '', informations={'info': 'value'})
|
|
||||||
IPOption('a', '', informations={'info': 'value'})
|
|
||||||
PortOption('a', '', informations={'info': 'value'})
|
|
||||||
NetworkOption('a', '', informations={'info': 'value'})
|
|
||||||
NetmaskOption('a', '', informations={'info': 'value'})
|
|
||||||
BroadcastOption('a', '', informations={'info': 'value'})
|
|
||||||
DomainnameOption('a', '', informations={'info': 'value'})
|
|
||||||
EmailOption('a', '', informations={'info': 'value'})
|
|
||||||
URLOption('a', '', informations={'info': 'value'})
|
|
||||||
UsernameOption('a', '', informations={'info': 'value'})
|
|
||||||
GroupnameOption('a', '', informations={'info': 'value'})
|
|
||||||
DateOption('a', '', informations={'info': 'value'})
|
|
||||||
FilenameOption('a', '', informations={'info': 'value'})
|
|
||||||
PasswordOption('a', '', informations={'info': 'value'})
|
|
||||||
MACOption('a', '', informations={'info': 'value'})
|
|
||||||
PermissionsOption('a', '', informations={'info': 'value'})
|
|
||||||
|
|
||||||
def test_information_config():
|
def test_information_config():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
|
@ -169,11 +143,11 @@ def test_information_config():
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.information.get('noinfo')
|
cfg.information.get('noinfo')
|
||||||
assert cfg.information.get('noinfo', 'default') == 'default'
|
assert cfg.information.get('noinfo', 'default') == 'default'
|
||||||
cfg.information.remove('info')
|
cfg.information.reset('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.information.remove('info')
|
cfg.information.get('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.information.remove('noinfo')
|
cfg.information.reset('noinfo')
|
||||||
assert list(cfg.information.list()) == ['doc']
|
assert list(cfg.information.list()) == ['doc']
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -220,23 +194,26 @@ def test_information_option():
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc.name').information.get('noinfo')
|
cfg.option('gc.name').information.get('noinfo')
|
||||||
assert cfg.option('gc.name').information.get('noinfo', 'default') == 'default'
|
assert cfg.option('gc.name').information.get('noinfo', 'default') == 'default'
|
||||||
cfg.option('gc.name').information.remove('info')
|
cfg.option('gc.name').information.reset('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc.name').information.get('info')
|
cfg.option('gc.name').information.get('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc.name').information.remove('noinfo')
|
cfg.option('gc.name').information.reset('noinfo')
|
||||||
assert list(cfg.option('gc.name').information.list()) == ['doc']
|
assert list(cfg.option('gc.name').information.list()) == ['doc']
|
||||||
#
|
#
|
||||||
assert cfg.option('wantref').information.get('info') == 'default value'
|
assert cfg.option('wantref').information.get('info') == 'default value'
|
||||||
cfg.option('wantref').information.set('info', 'default value')
|
cfg.option('wantref').information.set('info', 'default value')
|
||||||
assert cfg.option('wantref').information.get('info') == 'default value'
|
assert cfg.option('wantref').information.get('info') == 'default value'
|
||||||
cfg.option('wantref').information.remove('info')
|
cfg.option('wantref').information.reset('info')
|
||||||
assert cfg.option('wantref').information.get('info') == 'default value'
|
assert cfg.option('wantref').information.get('info') == 'default value'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_information_option_2():
|
def test_information_option_2():
|
||||||
i1 = IntOption('test1', '', informations={'info': 'value'})
|
i1 = IntOption('test1', '')
|
||||||
|
i1.impl_set_information('info', 'value')
|
||||||
|
# it's a dict
|
||||||
|
assert set(i1.impl_list_information()) == {'info', 'doc'}
|
||||||
od1 = OptionDescription('test', '', [i1])
|
od1 = OptionDescription('test', '', [i1])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
# it's tuples
|
# it's tuples
|
||||||
|
@ -244,17 +221,6 @@ def test_information_option_2():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_information_option_symlink():
|
|
||||||
i1 = IntOption('test1', '', Calculation(calc_value, Params(ParamSelfInformation('info'))), informations={'info': 'value'})
|
|
||||||
i2 = SymLinkOption('test2', i1)
|
|
||||||
od1 = OptionDescription('test', '', [i2, i1])
|
|
||||||
cfg = Config(od1)
|
|
||||||
# it's tuples
|
|
||||||
assert set(cfg.option('test1').information.list()) == {'info', 'doc'}
|
|
||||||
assert set(cfg.option('test2').information.list()) == {'info', 'doc'}
|
|
||||||
# assert not list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def test_information_optiondescription():
|
def test_information_optiondescription():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
|
@ -268,11 +234,11 @@ def test_information_optiondescription():
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc').information.get('noinfo')
|
cfg.option('gc').information.get('noinfo')
|
||||||
assert cfg.option('gc').information.get('noinfo', 'default') == 'default'
|
assert cfg.option('gc').information.get('noinfo', 'default') == 'default'
|
||||||
cfg.option('gc').information.remove('info')
|
cfg.option('gc').information.reset('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc').information.get('info')
|
cfg.option('gc').information.get('info')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('gc').information.remove('noinfo')
|
cfg.option('gc').information.reset('noinfo')
|
||||||
assert list(cfg.option('gc').information.list()) == ['doc']
|
assert list(cfg.option('gc').information.list()) == ['doc']
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -446,7 +412,7 @@ def test_config_od_name(config_type):
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert cfg.option('val.i').name() == 'i'
|
assert cfg.option('val.i').name() == 'i'
|
||||||
assert cfg.option('val.s').name() == 's'
|
assert cfg.option('val.s').name() == 's'
|
||||||
assert cfg.option('val.s').type() == 'integer'
|
assert cfg.option('val.s').type() == _('integer')
|
||||||
assert cfg.option('val').type() == 'optiondescription'
|
assert cfg.option('val').type() == 'optiondescription'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -458,7 +424,7 @@ def test_config_od_type(config_type):
|
||||||
cfg = Config(o2)
|
cfg = Config(o2)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert cfg.option('val').type() == 'optiondescription'
|
assert cfg.option('val').type() == 'optiondescription'
|
||||||
assert cfg.option('val.i').type() == 'integer'
|
assert cfg.option('val.i').type() == _('integer')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -412,6 +412,7 @@ def test_help():
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
cfg.help(_display=False)
|
cfg.help(_display=False)
|
||||||
cfg.config.help(_display=False)
|
cfg.config.help(_display=False)
|
||||||
|
cfg.option.help(_display=False)
|
||||||
cfg.option('o').help(_display=False)
|
cfg.option('o').help(_display=False)
|
||||||
cfg.option('o.s').help(_display=False)
|
cfg.option('o.s').help(_display=False)
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
@ -429,7 +430,7 @@ def test_config_reset():
|
||||||
#
|
#
|
||||||
cfg.option('gc.gc2.bool').value.set(True)
|
cfg.option('gc.gc2.bool').value.set(True)
|
||||||
cfg.option('boolop').property.add('test')
|
cfg.option('boolop').property.add('test')
|
||||||
cfg.option('float').permissive.add('test')
|
cfg.option('float').permissive.set(frozenset(['test']))
|
||||||
cfg.option('wantref').information.set('info', 'info')
|
cfg.option('wantref').information.set('info', 'info')
|
||||||
assert cfg.option('gc.gc2.bool').value.get()
|
assert cfg.option('gc.gc2.bool').value.get()
|
||||||
assert cfg.option('boolop').property.get()
|
assert cfg.option('boolop').property.get()
|
||||||
|
|
|
@ -201,7 +201,7 @@ def test_deref_symlink():
|
||||||
def test_deref_dyn():
|
def test_deref_dyn():
|
||||||
a = StrOption('a', '', ['val1', 'val2'], multi=True)
|
a = StrOption('a', '', ['val1', 'val2'], multi=True)
|
||||||
b = StrOption('b', '')
|
b = StrOption('b', '')
|
||||||
dod = DynOptionDescription('dod', '', [b], identifiers=Calculation(funcname, Params((ParamOption(a),))))
|
dod = DynOptionDescription('dod', '', [b], suffixes=Calculation(funcname, Params((ParamOption(a),))))
|
||||||
o = OptionDescription('od', '', [dod, a])
|
o = OptionDescription('od', '', [dod, a])
|
||||||
cfg = Config(o)
|
cfg = Config(o)
|
||||||
w = weakref.ref(a)
|
w = weakref.ref(a)
|
||||||
|
|
|
@ -59,27 +59,27 @@ def test_copy_information():
|
||||||
ncfg = cfg.config.copy()
|
ncfg = cfg.config.copy()
|
||||||
assert ncfg.information.get('key') == 'value'
|
assert ncfg.information.get('key') == 'value'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_copy_force_store_value():
|
#def test_copy_force_store_value():
|
||||||
od1 = make_description()
|
# od1 = make_description()
|
||||||
conf = Config(od1)
|
# conf = Config(od1)
|
||||||
conf2 = Config(od1)
|
# conf2 = Config(od1)
|
||||||
assert conf.value.exportation() == {}
|
# assert conf.value.exportation() == {}
|
||||||
assert conf2.value.exportation() == {}
|
# assert conf2.value.exportation() == {}
|
||||||
#
|
# #
|
||||||
conf.property.read_write()
|
# conf.property.read_write()
|
||||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
assert conf2.value.exportation() == {}
|
# assert conf2.value.exportation() == {}
|
||||||
#
|
# #
|
||||||
conf2.property.read_only()
|
# conf2.property.read_only()
|
||||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
# assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
#
|
# #
|
||||||
conf.option('creole.general.wantref').value.set(True)
|
# conf.option('creole.general.wantref').value.set(True)
|
||||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
|
# assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
|
||||||
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
# assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#def test_copy_force_store_value_metaconfig():
|
#def test_copy_force_store_value_metaconfig():
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -160,57 +160,57 @@ def test_freeze_multi():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_force_store_value():
|
#def test_force_store_value():
|
||||||
od1 = make_description_freeze()
|
# od1 = make_description_freeze()
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
compare(cfg.value.exportation(), {})
|
# compare(cfg.value.exportation(), {})
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
# compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
cfg.option('bool').value.set(False)
|
# cfg.option('bool').value.set(False)
|
||||||
cfg.option('wantref').value.set(True)
|
# cfg.option('wantref').value.set(True)
|
||||||
cfg.option('bool').value.reset()
|
# cfg.option('bool').value.reset()
|
||||||
compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
# compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
cfg.option('bool').value.set(False)
|
# cfg.option('bool').value.set(False)
|
||||||
cfg.option('wantref').value.reset()
|
# cfg.option('wantref').value.reset()
|
||||||
cfg.option('bool').value.reset()
|
# cfg.option('bool').value.reset()
|
||||||
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
# compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_force_store_value_leadership_sub():
|
#def test_force_store_value_leadership_sub():
|
||||||
b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',))
|
# b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',))
|
||||||
c = StrOption('str', 'Test string option', multi=True)
|
# c = StrOption('str', 'Test string option', multi=True)
|
||||||
descr = Leadership("int", "", [b, c])
|
# descr = Leadership("int", "", [b, c])
|
||||||
od1 = OptionDescription('odr', '', [descr])
|
# od1 = OptionDescription('odr', '', [descr])
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}})
|
# compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}})
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_force_store_value_callback():
|
#def test_force_store_value_callback():
|
||||||
b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',))
|
# b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',))
|
||||||
od1 = OptionDescription("int", "", [b])
|
# od1 = OptionDescription("int", "", [b])
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}})
|
# compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}})
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_force_store_value_callback_params():
|
#def test_force_store_value_callback_params():
|
||||||
b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamValue(2)})), properties=('force_store_value',))
|
# b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamValue(2)})), properties=('force_store_value',))
|
||||||
od1 = OptionDescription("int", "", [b])
|
# od1 = OptionDescription("int", "", [b])
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
|
# compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_force_store_value_callback_params_with_opt():
|
#def test_force_store_value_callback_params_with_opt():
|
||||||
a = IntOption('val1', "", 2)
|
# a = IntOption('val1', "", 2)
|
||||||
b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',))
|
# b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',))
|
||||||
od1 = OptionDescription("int", "", [a, b])
|
# od1 = OptionDescription("int", "", [a, b])
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
|
# compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
|
|
@ -159,7 +159,7 @@ def test_iter_on_empty_group():
|
||||||
od1 = OptionDescription("name", "descr", [])
|
od1 = OptionDescription("name", "descr", [])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
result = list(cfg.list())
|
result = list(cfg.option.list())
|
||||||
assert result == []
|
assert result == []
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ def test_groups_is_leader(config_type):
|
||||||
assert not cfg.option('leadership.netmask_admin_eth0').isleader()
|
assert not cfg.option('leadership.netmask_admin_eth0').isleader()
|
||||||
assert cfg.option('leadership.netmask_admin_eth0').isfollower()
|
assert cfg.option('leadership.netmask_admin_eth0').isfollower()
|
||||||
assert cfg.option('leadership.netmask_admin_eth0').path() == 'leadership.netmask_admin_eth0'
|
assert cfg.option('leadership.netmask_admin_eth0').path() == 'leadership.netmask_admin_eth0'
|
||||||
assert cfg.option('leadership.netmask_admin_eth0').value.defaultmulti() == 'value'
|
assert cfg.option('leadership.netmask_admin_eth0').defaultmulti() == 'value'
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
@ -207,7 +207,7 @@ def test_leader_list(config_type):
|
||||||
od1 = OptionDescription('od', '', [interface1])
|
od1 = OptionDescription('od', '', [interface1])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
ret = cfg.list()
|
ret = cfg.option.list()
|
||||||
assert len(ret) == 1
|
assert len(ret) == 1
|
||||||
assert ret[0].name() == 'leadership'
|
assert ret[0].name() == 'leadership'
|
||||||
#
|
#
|
||||||
|
@ -983,65 +983,65 @@ def test_follower_not_multi():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_follower_force_store_value_none():
|
#def test_follower_force_store_value_none():
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('force_store_value',))
|
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('force_store_value',))
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od1 = OptionDescription('od', '', [interface0])
|
# od1 = OptionDescription('od', '', [interface0])
|
||||||
od2 = OptionDescription('toto', '', [od1])
|
# od2 = OptionDescription('toto', '', [od1])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
# assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_follower_force_store_value():
|
#def test_follower_force_store_value():
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od1 = OptionDescription('od', '', [interface0])
|
# od1 = OptionDescription('od', '', [interface0])
|
||||||
od2 = OptionDescription('toto', '', [od1])
|
# od2 = OptionDescription('toto', '', [od1])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_follower_force_store_value_read_only():
|
#def test_follower_force_store_value_read_only():
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od1 = OptionDescription('od', '', [interface0])
|
# od1 = OptionDescription('od', '', [interface0])
|
||||||
od2 = OptionDescription('toto', '', [od1])
|
# od2 = OptionDescription('toto', '', [od1])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_follower_force_store_value_reset():
|
#def test_follower_force_store_value_reset():
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od1 = OptionDescription('od', '', [interface0])
|
# od1 = OptionDescription('od', '', [interface0])
|
||||||
od2 = OptionDescription('toto', '', [od1])
|
# od2 = OptionDescription('toto', '', [od1])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
cfg.option('od.interface0.ip_admin_eth0').value.set(['1.1.1.1', '192.168.0.0'])
|
# cfg.option('od.interface0.ip_admin_eth0').value.set(['1.1.1.1', '192.168.0.0'])
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
|
||||||
#
|
# #
|
||||||
cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset()
|
# cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset()
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
|
||||||
#
|
# #
|
||||||
cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
|
# cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
|
||||||
cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
|
# cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
|
||||||
assert cfg.option('od.interface0.ip_admin_eth0').value.get() == []
|
# assert cfg.option('od.interface0.ip_admin_eth0').value.get() == []
|
||||||
cfg.option('od.interface0.ip_admin_eth0').value.reset()
|
# cfg.option('od.interface0.ip_admin_eth0').value.reset()
|
||||||
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
#def test_follower_properties():
|
#def test_follower_properties():
|
||||||
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, properties=('aproperty',))
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('aproperty',))
|
||||||
|
|
|
@ -681,7 +681,7 @@ def test_mandatory_od_disabled():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def return_list(val=None, identifier=None):
|
def return_list(val=None, suffix=None):
|
||||||
if val:
|
if val:
|
||||||
return val
|
return val
|
||||||
else:
|
else:
|
||||||
|
@ -690,7 +690,7 @@ def return_list(val=None, identifier=None):
|
||||||
|
|
||||||
#def test_mandatory_dyndescription():
|
#def test_mandatory_dyndescription():
|
||||||
# st = StrOption('st', '', properties=('mandatory',))
|
# st = StrOption('st', '', properties=('mandatory',))
|
||||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||||
# od = OptionDescription('od', '', [dod])
|
# od = OptionDescription('od', '', [dod])
|
||||||
# od2 = OptionDescription('od', '', [od])
|
# od2 = OptionDescription('od', '', [od])
|
||||||
# cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
|
@ -701,7 +701,7 @@ def return_list(val=None, identifier=None):
|
||||||
#def test_mandatory_dyndescription_context():
|
#def test_mandatory_dyndescription_context():
|
||||||
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||||
# st = StrOption('st', '', properties=('mandatory',))
|
# st = StrOption('st', '', properties=('mandatory',))
|
||||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||||
# od = OptionDescription('od', '', [dod, val1])
|
# od = OptionDescription('od', '', [dod, val1])
|
||||||
# od2 = OptionDescription('od', '', [od])
|
# od2 = OptionDescription('od', '', [od])
|
||||||
# cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
|
|
|
@ -20,7 +20,7 @@ def a_func():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def display_name(*args, with_quote=False):
|
def display_name(*args):
|
||||||
return 'display_name'
|
return 'display_name'
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,20 @@ def test_option_valid_name():
|
||||||
i = SymLinkOption("test1", i)
|
i = SymLinkOption("test1", i)
|
||||||
|
|
||||||
|
|
||||||
|
def test_option_get_information():
|
||||||
|
description = "it's ok"
|
||||||
|
string = 'some informations'
|
||||||
|
i = IntOption('test', description)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
i.impl_get_information('noinfo')
|
||||||
|
i.impl_set_information('info', string)
|
||||||
|
assert i.impl_get_information('info') == string
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
i.impl_get_information('noinfo')
|
||||||
|
assert i.impl_get_information('noinfo', 'default') == 'default'
|
||||||
|
assert i.impl_get_information('doc') == description
|
||||||
|
|
||||||
|
|
||||||
def test_option_get_information_config():
|
def test_option_get_information_config():
|
||||||
description = "it's ok"
|
description = "it's ok"
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
|
@ -41,16 +55,21 @@ def test_option_get_information_config():
|
||||||
od = OptionDescription('od', '', [i])
|
od = OptionDescription('od', '', [i])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('test').information.get('noinfo')
|
i.impl_get_information('noinfo')
|
||||||
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
|
with pytest.raises(AttributeError):
|
||||||
assert cfg.option('test').information.get('doc') == description
|
i.impl_set_information('info', string)
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
i.impl_get_information('noinfo')
|
||||||
|
assert i.impl_get_information('noinfo', 'default') == 'default'
|
||||||
|
assert i.impl_get_information('doc') == description
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_option_unknown():
|
def test_option_unknown():
|
||||||
description = "it's ok"
|
description = "it's ok"
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
i = IntOption('test', description, informations={'noinfo': 'optdefault'})
|
i = IntOption('test', description)
|
||||||
|
i.impl_set_information('noinfo', 'optdefault')
|
||||||
od = OptionDescription('od', '', [i])
|
od = OptionDescription('od', '', [i])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
#
|
#
|
||||||
|
@ -74,7 +93,8 @@ def test_option_description():
|
||||||
def test_option_get_information_default():
|
def test_option_get_information_default():
|
||||||
description = "it's ok"
|
description = "it's ok"
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
i = IntOption('test', description, informations={'noinfo': 'optdefault'})
|
i = IntOption('test', description)
|
||||||
|
i.impl_set_information('noinfo', 'optdefault')
|
||||||
od = OptionDescription('od', '', [i])
|
od = OptionDescription('od', '', [i])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
#
|
#
|
||||||
|
@ -88,30 +108,32 @@ def test_option_get_information_default():
|
||||||
def test_option_get_information_config2():
|
def test_option_get_information_config2():
|
||||||
description = "it's ok"
|
description = "it's ok"
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
i = IntOption('test', description, informations={'info': string})
|
i = IntOption('test', description)
|
||||||
|
i.impl_set_information('info', string)
|
||||||
od = OptionDescription('od', '', [i])
|
od = OptionDescription('od', '', [i])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('test').information.get('noinfo')
|
i.impl_get_information('noinfo')
|
||||||
assert cfg.option('test').information.get('info') == string
|
with pytest.raises(AttributeError):
|
||||||
|
i.impl_set_information('info', 'hello')
|
||||||
|
assert i.impl_get_information('info') == string
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('test').information.get('noinfo')
|
i.impl_get_information('noinfo')
|
||||||
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
|
assert i.impl_get_information('noinfo', 'default') == 'default'
|
||||||
assert cfg.option('test').information.get('doc') == description
|
assert i.impl_get_information('doc') == description
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_optiondescription_get_information():
|
def test_optiondescription_get_information():
|
||||||
description = "it's ok"
|
description = "it's ok"
|
||||||
string = 'some informations'
|
string = 'some informations'
|
||||||
o = OptionDescription('test', description, [], informations={'info': string})
|
o = OptionDescription('test', description, [])
|
||||||
od = OptionDescription('od', '', [o])
|
o.impl_set_information('info', string)
|
||||||
cfg = Config(od)
|
assert o.impl_get_information('info') == string
|
||||||
assert cfg.option('test').information.get('info') == string
|
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('test').information.get('noinfo')
|
o.impl_get_information('noinfo')
|
||||||
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
|
assert o.impl_get_information('noinfo', 'default') == 'default'
|
||||||
assert cfg.option('test').information.get('doc') == description
|
assert o.impl_get_information('doc') == description
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,7 +218,7 @@ def test_optiondescription_group():
|
||||||
od3.impl_set_group_type(groups.notfamily)
|
od3.impl_set_group_type(groups.notfamily)
|
||||||
od2 = OptionDescription('od', '', [od1, od3])
|
od2 = OptionDescription('od', '', [od1, od3])
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
assert len(list(cfg.list())) == 2
|
assert len(list(cfg.option.list())) == 2
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,4 +321,4 @@ def test_option_display_name():
|
||||||
display_name=display_name,
|
display_name=display_name,
|
||||||
)
|
)
|
||||||
assert cfg.option('test1').name() == 'test1'
|
assert cfg.option('test1').name() == 'test1'
|
||||||
assert cfg.option('test1').description() == 'display_name'
|
assert cfg.option('test1').doc() == 'display_name'
|
||||||
|
|
|
@ -289,12 +289,11 @@ def test_callback(config_type):
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert isinstance(cfg.option('val1').value.get(uncalculated=True), Calculation)
|
|
||||||
assert cfg.option('val1').value.get() == 'val'
|
assert cfg.option('val1').value.get() == 'val'
|
||||||
cfg.option('val1').value.set('new-val')
|
cfg.option('val1').value.set('new-val')
|
||||||
assert cfg.option('val1').value.get() == 'new-val'
|
assert cfg.option('val1').value.get() == 'new-val'
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
assert cfg.option('val1').value.defaultmulti() == None
|
assert cfg.option('val1').defaultmulti() == None
|
||||||
cfg.option('val1').value.reset()
|
cfg.option('val1').value.reset()
|
||||||
assert cfg.option('val1').value.get() == 'val'
|
assert cfg.option('val1').value.get() == 'val'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
@ -416,7 +415,8 @@ def test_callback_information(config_type):
|
||||||
|
|
||||||
def test_callback_information2(config_type):
|
def test_callback_information2(config_type):
|
||||||
val1 = StrOption('val1', "", Calculation(return_value, Params(ParamSelfInformation('information', 'no_value'))))
|
val1 = StrOption('val1', "", Calculation(return_value, Params(ParamSelfInformation('information', 'no_value'))))
|
||||||
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamSelfInformation('information'))), informations={'information': 'new_value'})
|
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamSelfInformation('information'))))
|
||||||
|
val2.impl_set_information('information', 'new_value')
|
||||||
val3 = StrOption('val3', "", Calculation(return_value, Params(ParamSelfInformation('information'))))
|
val3 = StrOption('val3', "", Calculation(return_value, Params(ParamSelfInformation('information'))))
|
||||||
od1 = OptionDescription('rootconfig', '', [val1, val2, val3])
|
od1 = OptionDescription('rootconfig', '', [val1, val2, val3])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
|
@ -432,8 +432,9 @@ def test_callback_information2(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_callback_information3(config_type):
|
def test_callback_information3(config_type):
|
||||||
val1 = StrOption('val1', "", informations={'information': 'new_value'})
|
val1 = StrOption('val1', "")
|
||||||
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamInformation('information', option=val1))))
|
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamInformation('information', option=val1))))
|
||||||
|
val1.impl_set_information('information', 'new_value')
|
||||||
od1 = OptionDescription('rootconfig', '', [val1, val2])
|
od1 = OptionDescription('rootconfig', '', [val1, val2])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -548,7 +549,7 @@ def test_callback_multi(config_type):
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert cfg.option('val1').value.get() == ['val']
|
assert cfg.option('val1').value.get() == ['val']
|
||||||
cfg.option('val1').value.set(['new-val'])
|
cfg.option('val1').value.set(['new-val'])
|
||||||
assert cfg.option('val1').value.defaultmulti() == None
|
assert cfg.option('val1').defaultmulti() == None
|
||||||
assert cfg.option('val1').value.get() == ['new-val']
|
assert cfg.option('val1').value.get() == ['new-val']
|
||||||
cfg.option('val1').value.set(['new-val', 'new-val2'])
|
cfg.option('val1').value.set(['new-val', 'new-val2'])
|
||||||
assert cfg.option('val1').value.get() == ['new-val', 'new-val2']
|
assert cfg.option('val1').value.get() == ['new-val', 'new-val2']
|
||||||
|
@ -945,7 +946,7 @@ def test_consistency_leader_and_followers_leader_mandatory_transitive():
|
||||||
try:
|
try:
|
||||||
cfg.option('val1.val2', 0).value.get()
|
cfg.option('val1.val2', 0).value.get()
|
||||||
except PropertiesOptionError as error:
|
except PropertiesOptionError as error:
|
||||||
assert str(error) == str(_('cannot access to {0} {1} because has {2} {3}').format('option', '"val2"', _('property'), '"disabled"'))
|
assert str(error) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'val2', _('property'), '"disabled"'))
|
||||||
else:
|
else:
|
||||||
raise Exception('must raises')
|
raise Exception('must raises')
|
||||||
assert list(cfg.value.mandatory()) == []
|
assert list(cfg.value.mandatory()) == []
|
||||||
|
@ -963,7 +964,7 @@ def test_callback_leader_and_followers_leader_list(config_type):
|
||||||
assert cfg.option('val1.val1').value.get() == ['val', 'val']
|
assert cfg.option('val1.val1').value.get() == ['val', 'val']
|
||||||
assert cfg.option('val1.val2', 0).value.get() == None
|
assert cfg.option('val1.val2', 0).value.get() == None
|
||||||
assert cfg.option('val1.val2', 1).value.get() == None
|
assert cfg.option('val1.val2', 1).value.get() == None
|
||||||
default_multi = cfg.option('val1.val1').value.defaultmulti()
|
default_multi = cfg.option('val1.val1').defaultmulti()
|
||||||
cfg.option('val1.val1').value.set(['val', 'val', default_multi])
|
cfg.option('val1.val1').value.set(['val', 'val', default_multi])
|
||||||
assert cfg.option('val1.val1').value.get() == ['val', 'val', None]
|
assert cfg.option('val1.val1').value.get() == ['val', 'val', None]
|
||||||
assert cfg.option('val1.val2', 0).value.get() == None
|
assert cfg.option('val1.val2', 0).value.get() == None
|
||||||
|
@ -1502,22 +1503,6 @@ def test_leadership_callback_description(config_type):
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_leadership_callback_outside(config_type):
|
|
||||||
st1 = StrOption('st1', "", multi=True)
|
|
||||||
st2 = StrOption('st2', "", multi=True, default_multi='val2')
|
|
||||||
stm = Leadership('st1', '', [st1, st2])
|
|
||||||
st3 = StrOption('st3', "", Calculation(return_value, Params(ParamOption(st2))), multi=True)
|
|
||||||
st = OptionDescription('st', '', [stm, st3])
|
|
||||||
od = OptionDescription('od', '', [st])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
owner = cfg.owner.get()
|
|
||||||
cfg.option('od.st.st1.st1').value.set(['yes'])
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.st.st1.st1': [{'od.st.st1.st1': 'yes', 'od.st.st1.st2': 'val2'}], 'od.st.st3': ['val2']}
|
|
||||||
## assert not list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def test_callback_raise():
|
def test_callback_raise():
|
||||||
opt1 = BoolOption('opt1', 'Option 1', Calculation(return_raise))
|
opt1 = BoolOption('opt1', 'Option 1', Calculation(return_raise))
|
||||||
opt2 = BoolOption('opt2', 'Option 2', Calculation(return_valueerror))
|
opt2 = BoolOption('opt2', 'Option 2', Calculation(return_valueerror))
|
||||||
|
@ -1706,38 +1691,3 @@ def test_calc_dependencies(config_type):
|
||||||
def test_callback__kwargs_wrong(config_type):
|
def test_callback__kwargs_wrong(config_type):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
Params(kwargs='string')
|
Params(kwargs='string')
|
||||||
|
|
||||||
|
|
||||||
def test_callback_information_parent(config_type):
|
|
||||||
information = ParamInformation('information')
|
|
||||||
val1 = StrOption('val1', "", Calculation(return_value, Params(information)))
|
|
||||||
od2 = OptionDescription('od', '', [val1], informations={'information': 'new_value'})
|
|
||||||
information.set_option(od2)
|
|
||||||
od1 = OptionDescription('rootconfig', '', [od2])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
assert cfg.option('od.val1').value.get() == 'new_value'
|
|
||||||
cfg.option('od').information.set('information', 'new_value2')
|
|
||||||
assert cfg.option('od.val1').value.get() == 'new_value2'
|
|
||||||
|
|
||||||
|
|
||||||
def test_callback_information_redefined(config_type):
|
|
||||||
val1 = StrOption('val1', "")
|
|
||||||
information = ParamInformation('information', option=val1)
|
|
||||||
val2 = StrOption('val2', "", Calculation(return_value, Params(information)))
|
|
||||||
od2 = OptionDescription('od', '', [val1, val2], informations={'information': 'new_value'})
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
information.set_option(od2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_callback_information_redefined_after(config_type):
|
|
||||||
information = ParamInformation('information')
|
|
||||||
val1 = StrOption('val1', "", Calculation(return_value, Params(information)))
|
|
||||||
od2 = OptionDescription('od', '', [val1], informations={'information': 'new_value'})
|
|
||||||
od1 = OptionDescription('rootconfig', '', [od2])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
information.set_option(od2)
|
|
||||||
|
|
|
@ -166,6 +166,28 @@ def test_force_default_on_freeze_multi():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
def test_force_default_on_freeze_leader_frozen():
|
||||||
|
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_default_on_freeze', 'frozen'))
|
||||||
|
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
||||||
|
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||||
|
od1 = OptionDescription("root", "", [descr])
|
||||||
|
cfg = Config(od1)
|
||||||
|
with pytest.raises(LeadershipError):
|
||||||
|
cfg.option('dummy1.dummy1').property.remove('frozen')
|
||||||
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
def test_force_metaconfig_on_freeze_leader_frozen():
|
||||||
|
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze', 'frozen'))
|
||||||
|
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
||||||
|
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||||
|
od1 = OptionDescription("root", "", [descr])
|
||||||
|
cfg = Config(od1)
|
||||||
|
with pytest.raises(LeadershipError):
|
||||||
|
cfg.option('dummy1.dummy1').property.remove('frozen')
|
||||||
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_force_default_on_freeze_follower(config_type):
|
def test_force_default_on_freeze_follower(config_type):
|
||||||
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('notunique',))
|
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('notunique',))
|
||||||
dummy2 = BoolOption('dummy2', 'Test string option', multi=True, properties=('force_default_on_freeze',))
|
dummy2 = BoolOption('dummy2', 'Test string option', multi=True, properties=('force_default_on_freeze',))
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
""" RegexpOption
|
|
||||||
"""
|
|
||||||
from .autopath import do_autopath
|
|
||||||
do_autopath()
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from tiramisu import RegexpOption, OptionDescription, Config
|
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
class ColorOption(RegexpOption):
|
|
||||||
__slots__ = tuple()
|
|
||||||
_type = 'Color'
|
|
||||||
_regexp = re.compile(r"^#(?:[0-9a-f]{3}){1,2}$")
|
|
||||||
|
|
||||||
|
|
||||||
def test_regexp_option():
|
|
||||||
r = ColorOption('test', 'test')
|
|
||||||
od = OptionDescription('od', 'od', [r])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.option('test').value.set('#ff0000')
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('test').value.set('not a color')
|
|
|
@ -82,7 +82,7 @@ def test_mod_read_only_write():
|
||||||
'empty',
|
'empty',
|
||||||
}
|
}
|
||||||
#
|
#
|
||||||
# config.property.setdefault(frozenset(['cache']))
|
config.property.setdefault(frozenset(['cache']))
|
||||||
config.property.setdefault(type='read_only', when='append', properties=frozenset(['disabled']))
|
config.property.setdefault(type='read_only', when='append', properties=frozenset(['disabled']))
|
||||||
config.property.setdefault(type='read_only', when='remove', properties=frozenset(['hidden']))
|
config.property.setdefault(type='read_only', when='remove', properties=frozenset(['hidden']))
|
||||||
config.property.setdefault(type='read_write', when='append', properties=frozenset(['disabled', 'hidden']))
|
config.property.setdefault(type='read_write', when='append', properties=frozenset(['disabled', 'hidden']))
|
||||||
|
@ -94,7 +94,7 @@ def test_mod_read_only_write():
|
||||||
with pytest.raises(TypeError):
|
with pytest.raises(TypeError):
|
||||||
config.property.setdefault(type='read_only', when='append', properties=['disabled'])
|
config.property.setdefault(type='read_only', when='append', properties=['disabled'])
|
||||||
|
|
||||||
assert config.property.default() == {'warnings', 'validator', 'cache'}
|
assert config.property.default() == {'cache'}
|
||||||
assert config.property.default('read_only', 'append') == {'disabled'}
|
assert config.property.default('read_only', 'append') == {'disabled'}
|
||||||
assert config.property.default('read_only', 'remove') == {'hidden'}
|
assert config.property.default('read_only', 'remove') == {'hidden'}
|
||||||
assert config.property.default('read_write', 'append') == {'disabled',
|
assert config.property.default('read_write', 'append') == {'disabled',
|
||||||
|
@ -102,11 +102,11 @@ def test_mod_read_only_write():
|
||||||
assert config.property.default('read_write', 'remove') == set([])
|
assert config.property.default('read_write', 'remove') == set([])
|
||||||
#
|
#
|
||||||
config.property.read_only()
|
config.property.read_only()
|
||||||
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled'}
|
assert config.property.get() == {'cache', 'disabled'}
|
||||||
config.property.read_write()
|
config.property.read_write()
|
||||||
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled', 'hidden'}
|
assert config.property.get() == {'cache', 'disabled', 'hidden'}
|
||||||
config.property.read_only()
|
config.property.read_only()
|
||||||
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled'}
|
assert config.property.get() == {'cache', 'disabled'}
|
||||||
#
|
#
|
||||||
assert config2.property.default() == {'cache', 'validator', 'warnings'}
|
assert config2.property.default() == {'cache', 'validator', 'warnings'}
|
||||||
assert config2.property.default('read_only', 'append') == {'frozen',
|
assert config2.property.default('read_only', 'append') == {'frozen',
|
||||||
|
@ -138,19 +138,6 @@ def test_mod_read_only_write():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_setting_tree(config_type):
|
|
||||||
s = StrOption("string", "", default=["string", "sdfsdf"], default_multi="prout", multi=True)
|
|
||||||
od4 = OptionDescription("option4", "", [s])
|
|
||||||
od3 = OptionDescription("option3", "", [od4])
|
|
||||||
od2 = OptionDescription("option2", "", [od3], properties=('hidden',))
|
|
||||||
od1 = OptionDescription("root", "", [od2])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
cfg.property.read_write()
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('option2.option3.option4.string').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_setitem(config_type):
|
def test_setitem(config_type):
|
||||||
s = StrOption("string", "", default=["string", "sdfsdf"], default_multi="prout", multi=True)
|
s = StrOption("string", "", default=["string", "sdfsdf"], default_multi="prout", multi=True)
|
||||||
od1 = OptionDescription("options", "", [s])
|
od1 = OptionDescription("options", "", [s])
|
||||||
|
@ -378,7 +365,8 @@ def test_apply_requires_from_config():
|
||||||
with pytest.raises(PropertiesOptionError):
|
with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('opt.str').value.get()
|
cfg.option('opt.str').value.get()
|
||||||
assert 'hidden' in cfg.forcepermissive.option('opt.str').property.get()
|
assert 'hidden' in cfg.forcepermissive.option('opt.str').property.get()
|
||||||
assert 'hidden' not in cfg.forcepermissive.option('opt.str').property.get(only_raises=True)
|
assert 'hidden' not in cfg.forcepermissive.option('opt.str').properties()
|
||||||
|
assert 'hidden' not in cfg.forcepermissive.option('opt.str').properties(only_raises=True)
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -398,7 +386,8 @@ def test_apply_requires_with_disabled():
|
||||||
cfg.option('int').value.set(1)
|
cfg.option('int').value.set(1)
|
||||||
with pytest.raises(PropertiesOptionError):
|
with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('opt.str').value.get()
|
cfg.option('opt.str').value.get()
|
||||||
assert 'disabled' not in cfg.unrestraint.option('opt.str').property.get(only_raises=True, apply_requires=False)
|
assert 'disabled' not in cfg.unrestraint.option('opt.str').properties()
|
||||||
|
assert 'disabled' not in cfg.unrestraint.option('opt.str').properties(only_raises=True)
|
||||||
assert 'disabled' in cfg.unrestraint.option('opt.str').property.get()
|
assert 'disabled' in cfg.unrestraint.option('opt.str').property.get()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -514,10 +503,10 @@ def test_accepts_multiple_changes_from_option():
|
||||||
od1 = OptionDescription("options", "", [s])
|
od1 = OptionDescription("options", "", [s])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.option('string').value.set("egg")
|
cfg.option('string').value.set("egg")
|
||||||
assert cfg.option('string').value.default() == "string"
|
assert cfg.option('string').default() == "string"
|
||||||
assert cfg.option('string').value.get() == "egg"
|
assert cfg.option('string').value.get() == "egg"
|
||||||
cfg.option('string').value.set('blah')
|
cfg.option('string').value.set('blah')
|
||||||
assert cfg.option('string').value.default() == "string"
|
assert cfg.option('string').default() == "string"
|
||||||
assert cfg.option('string').value.get() == "blah"
|
assert cfg.option('string').value.get() == "blah"
|
||||||
cfg.option('string').value.set('bol')
|
cfg.option('string').value.set('bol')
|
||||||
assert cfg.option('string').value.get() == 'bol'
|
assert cfg.option('string').value.get() == 'bol'
|
||||||
|
@ -618,7 +607,7 @@ def test_properties_get_add_reset():
|
||||||
cfg.property.add('frozen')
|
cfg.property.add('frozen')
|
||||||
assert cfg.property.get() == {'validator', 'warnings', 'cache', 'frozen'}
|
assert cfg.property.get() == {'validator', 'warnings', 'cache', 'frozen'}
|
||||||
cfg.property.reset()
|
cfg.property.reset()
|
||||||
assert cfg.property.get() == frozenset()
|
assert cfg.property.get() == {'validator', 'warnings', 'cache'}
|
||||||
|
|
||||||
|
|
||||||
def test_reset_properties_force_store_value():
|
def test_reset_properties_force_store_value():
|
||||||
|
@ -626,195 +615,28 @@ def test_reset_properties_force_store_value():
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.property.exportation() == {'properties': {None: {None: frozenset({'cache',
|
assert cfg.property.exportation() == {}
|
||||||
'validator',
|
|
||||||
'warnings'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.property.add('frozen')
|
cfg.property.add('frozen')
|
||||||
assert cfg.property.exportation() == \
|
assert cfg.property.exportation() == \
|
||||||
{
|
{None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}}
|
||||||
'properties': {None: {None: frozenset({'cache',
|
|
||||||
'frozen',
|
|
||||||
'validator',
|
|
||||||
'warnings'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
cfg.property.reset()
|
cfg.property.reset()
|
||||||
assert cfg.property.exportation() == {'properties': {None: {}},
|
assert cfg.property.exportation() == {None: {}}
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.option('gc.dummy').property.add('test')
|
cfg.option('gc.dummy').property.add('test')
|
||||||
assert cfg.property.exportation() == {
|
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: set(('test', 'force_store_value'))}}
|
||||||
'properties': {None: {},
|
|
||||||
'gc.dummy': {None: frozenset({'test'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.property.reset()
|
cfg.property.reset()
|
||||||
assert cfg.property.exportation() == {
|
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: set(('test', 'force_store_value'))}}
|
||||||
'properties': {None: {},
|
|
||||||
'gc.dummy': {None: frozenset({'test'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.property.add('frozen')
|
cfg.property.add('frozen')
|
||||||
assert cfg.property.exportation() == \
|
assert cfg.property.exportation() == \
|
||||||
{
|
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
|
||||||
'properties': {None: {None: frozenset({'frozen'})},
|
'gc.dummy': {None: set(('test', 'force_store_value'))}}
|
||||||
'gc.dummy': {None: frozenset({'test'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
cfg.property.add('frozen')
|
cfg.property.add('frozen')
|
||||||
assert cfg.property.exportation() == \
|
assert cfg.property.exportation() == \
|
||||||
{
|
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
|
||||||
'properties': {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}},
|
'gc.dummy': {None: set(('test', 'force_store_value'))}}
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
cfg.option('gc.dummy').property.add('test')
|
cfg.option('gc.dummy').property.add('test')
|
||||||
assert cfg.property.exportation() == \
|
assert cfg.property.exportation() == \
|
||||||
{
|
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
|
||||||
'properties': {None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}},
|
'gc.dummy': {None: set(('test', 'force_store_value'))}}
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -844,79 +666,10 @@ def test_set_modified_value():
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.property.exportation() == {
|
assert cfg.property.exportation() == {}
|
||||||
'properties': {None: {None: frozenset({'cache',
|
cfg.property.importation({None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}})
|
||||||
'validator',
|
|
||||||
'warnings'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg.property.importation({
|
|
||||||
'properties': {None: {None: frozenset({'cache',
|
|
||||||
'frozen',
|
|
||||||
'validator',
|
|
||||||
'warnings'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
})
|
|
||||||
assert cfg.property.exportation() == \
|
assert cfg.property.exportation() == \
|
||||||
{
|
{None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}}
|
||||||
'properties': {None: {None: frozenset({'cache',
|
|
||||||
'frozen',
|
|
||||||
'validator',
|
|
||||||
'warnings'})}},
|
|
||||||
'ro_append': frozenset({'disabled',
|
|
||||||
'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'mandatory',
|
|
||||||
'validator'}),
|
|
||||||
'ro_remove': frozenset({'hidden',
|
|
||||||
'permissive'}),
|
|
||||||
'rw_append': frozenset({'disabled',
|
|
||||||
'force_store_value',
|
|
||||||
'frozen',
|
|
||||||
'hidden',
|
|
||||||
'validator'}),
|
|
||||||
'rw_remove': frozenset({'empty',
|
|
||||||
'everything_frozen',
|
|
||||||
'mandatory',
|
|
||||||
'permissive'}),
|
|
||||||
}
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -933,7 +686,7 @@ def test_set_modified_value():
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
def test_pprint():
|
def test_pprint():
|
||||||
msg_error = _("cannot access to {0} {1} because has {2} {3}")
|
msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}")
|
||||||
msg_is_not = _('the value of "{0}" is not {1}')
|
msg_is_not = _('the value of "{0}" is not {1}')
|
||||||
msg_is = _('the value of "{0}" is {1}')
|
msg_is = _('the value of "{0}" is {1}')
|
||||||
properties = _('properties')
|
properties = _('properties')
|
||||||
|
@ -987,8 +740,8 @@ def test_pprint():
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
list_disabled = '"disabled" (' + display_list([msg_is.format('Test int option', '"1"'), msg_is.format('string2', '"string"')], add_quote=False) + ')'
|
list_disabled = '"disabled" (' + display_list([msg_is.format('Test int option', '"1"'), msg_is.format('string2', '"string"')], add_quote=False) + ')'
|
||||||
list_hidden = '"hidden" (' + msg_is_not.format('Test int option', display_list([2, 3, 4], separator='or', add_quote=True)) + ')'
|
list_hidden = '"hidden" (' + msg_is_not.format('Test int option', display_list([2, 3, 4], 'or', add_quote=True)) + ')'
|
||||||
assert str(err) == _(msg_error.format('option', '"Test string option"', properties, display_list([list_disabled, list_hidden], add_quote=False)))
|
assert str(err) == _(msg_error.format('option', 'Test string option', properties, display_list([list_disabled, list_hidden], add_quote=False)))
|
||||||
del err
|
del err
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
|
@ -997,7 +750,7 @@ def test_pprint():
|
||||||
except PropertiesOptionError as error:
|
except PropertiesOptionError as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('optiondescription', '"options"', prop, '"hidden" (' + msg_is.format('Test int option', '"1"') + ')')
|
assert str(err) == msg_error.format('optiondescription', 'options', prop, '"hidden" (' + msg_is.format('Test int option', '"1"') + ')')
|
||||||
|
|
||||||
#err = None
|
#err = None
|
||||||
#try:
|
#try:
|
||||||
|
@ -1018,7 +771,7 @@ def test_pprint():
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('option', '"string"', properties, display_list(['disabled', 'hidden'], add_quote=True))
|
assert str(err) == msg_error.format('option', 'string', properties, display_list(['disabled', 'hidden'], add_quote=True))
|
||||||
del err
|
del err
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
|
@ -1027,13 +780,13 @@ def test_pprint():
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('option', '"string3"', prop, '"hidden"')
|
assert str(err) == msg_error.format('option', 'string3', prop, '"hidden"')
|
||||||
del err
|
del err
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_pprint_not_todict():
|
def test_pprint_not_todict():
|
||||||
msg_error = _("cannot access to {0} {1} because has {2} {3}")
|
msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}")
|
||||||
msg_is_not = _('the value of "{0}" is not {1}')
|
msg_is_not = _('the value of "{0}" is not {1}')
|
||||||
msg_is = _('the value of "{0}" is {1}')
|
msg_is = _('the value of "{0}" is {1}')
|
||||||
properties = _('properties')
|
properties = _('properties')
|
||||||
|
@ -1088,7 +841,7 @@ def test_pprint_not_todict():
|
||||||
|
|
||||||
list_disabled = '"disabled"'
|
list_disabled = '"disabled"'
|
||||||
list_hidden = '"hidden"'
|
list_hidden = '"hidden"'
|
||||||
assert str(err) == _(msg_error.format('option', '"Test string option"', properties, display_list([list_disabled, list_hidden], add_quote=False)))
|
assert str(err) == _(msg_error.format('option', 'Test string option', properties, display_list([list_disabled, list_hidden], add_quote=False)))
|
||||||
del err
|
del err
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
|
@ -1097,7 +850,7 @@ def test_pprint_not_todict():
|
||||||
except PropertiesOptionError as error:
|
except PropertiesOptionError as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('optiondescription', '"options"', prop, '"hidden"')
|
assert str(err) == msg_error.format('optiondescription', 'options', prop, '"hidden"')
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
try:
|
try:
|
||||||
|
@ -1105,7 +858,7 @@ def test_pprint_not_todict():
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('option', '"string"', properties, display_list(['disabled', 'hidden'], add_quote=True))
|
assert str(err) == msg_error.format('option', 'string', properties, display_list(['disabled', 'hidden'], add_quote=True))
|
||||||
del err
|
del err
|
||||||
|
|
||||||
err = None
|
err = None
|
||||||
|
@ -1114,7 +867,7 @@ def test_pprint_not_todict():
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
err = error
|
err = error
|
||||||
|
|
||||||
assert str(err) == msg_error.format('option', '"string3"', prop, '"hidden"')
|
assert str(err) == msg_error.format('option', 'string3', prop, '"hidden"')
|
||||||
del err
|
del err
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
|
@ -64,10 +64,7 @@ def test_is_hidden(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_group_is_hidden(config_type):
|
def test_group_is_hidden(config_type):
|
||||||
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=(('hidden'),))
|
od1 = make_description()
|
||||||
floatoption = FloatOption('float', 'Test float option', default=2.3)
|
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy, floatoption])
|
|
||||||
od1 = OptionDescription('trs', '', [gcgroup])
|
|
||||||
cfg_ori = Config(od1)
|
cfg_ori = Config(od1)
|
||||||
cfg_ori.property.read_write()
|
cfg_ori.property.read_write()
|
||||||
cfg_ori.option('gc').property.add('hidden')
|
cfg_ori.option('gc').property.add('hidden')
|
||||||
|
@ -76,14 +73,14 @@ def test_group_is_hidden(config_type):
|
||||||
cfg.option('gc.dummy').value.get()
|
cfg.option('gc.dummy').value.get()
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
assert 'hidden' in cfg_ori.option('gc').property.get()
|
assert 'hidden' in cfg_ori.forcepermissive.option('gc').property.get()
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
with pytest.raises(PropertiesOptionError):
|
with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('gc.float').value.get()
|
cfg.option('gc.float').value.get()
|
||||||
# manually set the subconfigs to "show"
|
# manually set the subconfigs to "show"
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.option('gc').property.remove('hidden')
|
cfg_ori.forcepermissive.option('gc').property.remove('hidden')
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
assert not 'hidden' in cfg.option('gc').property.get()
|
assert not 'hidden' in cfg.option('gc').property.get()
|
||||||
assert cfg.option('gc.float').value.get() == 2.3
|
assert cfg.option('gc.float').value.get() == 2.3
|
||||||
|
@ -158,38 +155,13 @@ def test_with_many_subgroups(config_type):
|
||||||
|
|
||||||
def test_password_option(config_type):
|
def test_password_option(config_type):
|
||||||
o = PasswordOption('o', '')
|
o = PasswordOption('o', '')
|
||||||
o1 = PasswordOption('o1', '', min_len=4)
|
od1 = OptionDescription('d', '', [o])
|
||||||
o2 = PasswordOption('o2', '', max_len=4)
|
|
||||||
o3 = PasswordOption('o3', '', forbidden_char=['p'])
|
|
||||||
od1 = OptionDescription('d', '', [o, o1, o2, o3])
|
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
|
||||||
cfg.option('o').value.set('a_valid_password')
|
cfg.option('o').value.set('a_valid_password')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('o').value.set(1)
|
cfg.option('o').value.set(1)
|
||||||
#
|
|
||||||
assert cfg.option('o1').value.get() is None
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('o1').value.set("1")
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('o1').value.set("12")
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('o1').value.set("123")
|
|
||||||
cfg.option('o1').value.set("1234")
|
|
||||||
cfg.option('o1').value.set("12345")
|
|
||||||
#
|
|
||||||
assert cfg.option('o2').value.get() is None
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('o2').value.set("12345")
|
|
||||||
cfg.option('o2').value.set("1")
|
|
||||||
cfg.option('o2').value.set("12")
|
|
||||||
cfg.option('o2').value.set("123")
|
|
||||||
cfg.option('o2').value.set("1234")
|
|
||||||
#
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('o3').value.set("password")
|
|
||||||
cfg.option('o3').value.set("assword")
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -334,7 +334,7 @@ def test_validator_warning(config_type):
|
||||||
assert len(w) == 1
|
assert len(w) == 1
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == opt2
|
assert w[0].message.opt() == opt2
|
||||||
assert str(w[0].message) == msg_err.format('val', _(opt2.get_type()), 'opt2') + ', ' + 'test error return_false'
|
assert str(w[0].message) == msg_err.format('val', opt2.get_type(), 'opt2') + ', ' + 'test error return_false'
|
||||||
#
|
#
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
cfg.nowarnings.option('opt2').value.set('val')
|
cfg.nowarnings.option('opt2').value.set('val')
|
||||||
|
@ -352,7 +352,7 @@ def test_validator_warning(config_type):
|
||||||
assert len(w) == 1
|
assert len(w) == 1
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == opt3
|
assert w[0].message.opt() == opt3
|
||||||
assert str(w[0].message) == msg_err.format('val1', _(opt3.get_type()), 'opt3') + ', ' + 'test error'
|
assert str(w[0].message) == msg_err.format('val1', opt3.get_type(), 'opt3') + ', ' + 'test error'
|
||||||
#
|
#
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
|
@ -365,9 +365,9 @@ def test_validator_warning(config_type):
|
||||||
assert len(w) == 2
|
assert len(w) == 2
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == opt2
|
assert w[0].message.opt() == opt2
|
||||||
assert str(w[0].message) == msg_err.format('val', _(opt2.get_type()), 'opt2') + ', ' + 'test error return_false'
|
assert str(w[0].message) == msg_err.format('val', opt2.get_type(), 'opt2') + ', ' + 'test error return_false'
|
||||||
assert w[1].message.opt() == opt3
|
assert w[1].message.opt() == opt3
|
||||||
assert str(w[1].message) == msg_err.format('val1', _(opt3.get_type()), 'opt3') + ', ' + 'test error'
|
assert str(w[1].message) == msg_err.format('val1', opt3.get_type(), 'opt3') + ', ' + 'test error'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -436,13 +436,13 @@ def test_validator_warning_leadership(config_type):
|
||||||
assert len(w) == 1
|
assert len(w) == 1
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == netmask_admin_eth0
|
assert w[0].message.opt() == netmask_admin_eth0
|
||||||
assert str(w[0].message) == msg_err.format('val1', _(netmask_admin_eth0.get_type()), display_name_netmask) + ', test error'
|
assert str(w[0].message) == msg_err.format('val1', netmask_admin_eth0.get_type(), display_name_netmask) + ', test error'
|
||||||
#
|
#
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w and w[0].message.opt() == ip_admin_eth0
|
assert w and w[0].message.opt() == ip_admin_eth0
|
||||||
assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false'
|
assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
|
||||||
else:
|
else:
|
||||||
assert len(w) == 2
|
assert len(w) == 2
|
||||||
#
|
#
|
||||||
|
@ -450,7 +450,7 @@ def test_validator_warning_leadership(config_type):
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val1', 'val1'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val1', 'val1'])
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == ip_admin_eth0
|
assert w[0].message.opt() == ip_admin_eth0
|
||||||
assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false'
|
assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
|
||||||
else:
|
else:
|
||||||
assert len(w) == 3
|
assert len(w) == 3
|
||||||
#
|
#
|
||||||
|
@ -458,7 +458,7 @@ def test_validator_warning_leadership(config_type):
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val', 'val1'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val', 'val1'])
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == ip_admin_eth0
|
assert w[0].message.opt() == ip_admin_eth0
|
||||||
assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false'
|
assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
|
||||||
else:
|
else:
|
||||||
assert len(w) == 3
|
assert len(w) == 3
|
||||||
#
|
#
|
||||||
|
@ -467,7 +467,7 @@ def test_validator_warning_leadership(config_type):
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val1', 'val'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val1', 'val'])
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
assert w[0].message.opt() == ip_admin_eth0
|
assert w[0].message.opt() == ip_admin_eth0
|
||||||
assert str(w[0].message) == msg_err.format('val', _(ip_admin_eth0.get_type()), display_name_ip) + ', test error return_false'
|
assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
|
||||||
else:
|
else:
|
||||||
assert len(w) == 3
|
assert len(w) == 3
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
@ -1046,12 +1046,12 @@ def test_validator_error_prefix():
|
||||||
try:
|
try:
|
||||||
cfg.option('b').value.set(1)
|
cfg.option('b').value.set(1)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {0}').format('"a"')
|
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {}').format('"a"')
|
||||||
try:
|
try:
|
||||||
cfg.option('b').value.set(1)
|
cfg.option('b').value.set(1)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
err.prefix = ''
|
err.prefix = ''
|
||||||
assert str(err) == _('value is identical to {0}').format('"a"')
|
assert str(err) == _('value is identical to {}').format('"a"')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -1260,24 +1260,18 @@ def test_consistency_not_equal_has_dependency():
|
||||||
def test_validator_information(config_type):
|
def test_validator_information(config_type):
|
||||||
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params((ParamSelfInformation('key'), ParamValue('yes'))))], default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params((ParamSelfInformation('key'), ParamValue('yes'))))], default='val')
|
||||||
opt2 = StrOption('opt2', '', validators=[Calculation(return_true, Params((ParamInformation('key'), ParamValue('yes'))))], default='val')
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_true, Params((ParamInformation('key'), ParamValue('yes'))))], default='val')
|
||||||
opt3 = StrOption('opt3', '', validators=[Calculation(return_true, Params((ParamInformation('key', option=opt1), ParamValue('yes'))))], default='val')
|
od1 = OptionDescription('root', '', [opt1, opt2])
|
||||||
od1 = OptionDescription('root', '', [opt1, opt2, opt3])
|
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
cfg.option('opt1').value.get()
|
cfg.option('opt1').value.get()
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
cfg.option('opt3').value.get()
|
|
||||||
cfg.option('opt1').information.set('key', 'val')
|
cfg.option('opt1').information.set('key', 'val')
|
||||||
assert cfg.option('opt1').value.get() == 'val'
|
assert cfg.option('opt1').value.get() == 'val'
|
||||||
assert cfg.option('opt3').value.get() == 'val'
|
|
||||||
cfg.option('opt1').information.set('key', 'val1')
|
cfg.option('opt1').information.set('key', 'val1')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('opt1').value.get()
|
cfg.option('opt1').value.get()
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('opt3').value.get()
|
|
||||||
#
|
#
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
cfg.option('opt2').value.get()
|
assert cfg.option('opt2').value.get()
|
||||||
cfg.information.set('key', 'val')
|
cfg.information.set('key', 'val')
|
||||||
assert cfg.option('opt2').value.get() == 'val'
|
assert cfg.option('opt2').value.get() == 'val'
|
||||||
cfg.information.set('key', 'val1')
|
cfg.information.set('key', 'val1')
|
||||||
|
|
|
@ -22,7 +22,7 @@ def test_forcepermissive_and_unrestraint(config_type):
|
||||||
cfg_ori.property.read_write()
|
cfg_ori.property.read_write()
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
cfg_ori.forcepermissive.add('disabled')
|
cfg_ori.unrestraint.forcepermissive.add('disabled')
|
||||||
|
|
||||||
|
|
||||||
def test_permissive(config_type):
|
def test_permissive(config_type):
|
||||||
|
@ -39,9 +39,9 @@ def test_permissive(config_type):
|
||||||
assert set(props) == {'disabled'}
|
assert set(props) == {'disabled'}
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.permissive.add('disabled')
|
cfg_ori.unrestraint.permissive.add('disabled')
|
||||||
cfg_ori.permissive.remove('hidden')
|
cfg_ori.unrestraint.permissive.remove('hidden')
|
||||||
assert cfg_ori.permissive.get() == frozenset(['disabled'])
|
assert cfg_ori.unrestraint.permissive.get() == frozenset(['disabled'])
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
props = frozenset()
|
props = frozenset()
|
||||||
try:
|
try:
|
||||||
|
@ -81,8 +81,8 @@ def test_permissive_add(config_type):
|
||||||
assert set(props) == {'disabled'}
|
assert set(props) == {'disabled'}
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.permissive.add('disabled')
|
cfg_ori.unrestraint.permissive.add('disabled')
|
||||||
assert cfg_ori.permissive.get() == frozenset(['hidden', 'disabled'])
|
assert cfg_ori.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
props = frozenset()
|
props = frozenset()
|
||||||
try:
|
try:
|
||||||
|
@ -119,10 +119,10 @@ def test_permissive_pop():
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert set(props) == {'disabled'}
|
assert set(props) == {'disabled'}
|
||||||
cfg.permissive.add('disabled')
|
cfg.unrestraint.permissive.add('disabled')
|
||||||
assert cfg.permissive.get() == frozenset(['hidden', 'disabled'])
|
assert cfg.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
|
||||||
cfg.forcepermissive.option('u1').value.get()
|
cfg.forcepermissive.option('u1').value.get()
|
||||||
cfg.permissive.remove('disabled')
|
cfg.unrestraint.permissive.remove('disabled')
|
||||||
props = frozenset()
|
props = frozenset()
|
||||||
try:
|
try:
|
||||||
cfg.forcepermissive.option('u1').value.get()
|
cfg.forcepermissive.option('u1').value.get()
|
||||||
|
@ -136,14 +136,14 @@ def test_permissive_reset():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert cfg.permissive.get() == frozenset(['hidden'])
|
assert cfg.unrestraint.permissive.get() == frozenset(['hidden'])
|
||||||
#
|
#
|
||||||
cfg.permissive.add('disabled')
|
cfg.unrestraint.permissive.add('disabled')
|
||||||
cfg.permissive.remove('hidden')
|
cfg.unrestraint.permissive.remove('hidden')
|
||||||
assert cfg.permissive.get() == frozenset(['disabled'])
|
assert cfg.unrestraint.permissive.get() == frozenset(['disabled'])
|
||||||
#
|
#
|
||||||
cfg.permissive.reset()
|
cfg.unrestraint.permissive.reset()
|
||||||
assert cfg.permissive.get() == frozenset(['hidden'])
|
assert cfg.unrestraint.permissive.get() == frozenset()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,9 +157,9 @@ def test_permissive_mandatory():
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert frozenset(props) == frozenset(['disabled'])
|
assert frozenset(props) == frozenset(['disabled'])
|
||||||
cfg.permissive.add('mandatory')
|
cfg.unrestraint.permissive.add('mandatory')
|
||||||
cfg.permissive.add('disabled')
|
cfg.unrestraint.permissive.add('disabled')
|
||||||
assert cfg.permissive.get() == frozenset(['hidden', 'mandatory', 'disabled'])
|
assert cfg.unrestraint.permissive.get() == frozenset(['mandatory', 'disabled'])
|
||||||
cfg.property.add('permissive')
|
cfg.property.add('permissive')
|
||||||
cfg.option('u1').value.get()
|
cfg.option('u1').value.get()
|
||||||
cfg.property.remove('permissive')
|
cfg.property.remove('permissive')
|
||||||
|
@ -175,10 +175,10 @@ def test_permissive_frozen():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg.permissive.remove('hidden')
|
cfg.unrestraint.permissive.remove('hidden')
|
||||||
cfg.permissive.add('frozen')
|
cfg.unrestraint.permissive.add('frozen')
|
||||||
cfg.permissive.add('disabled')
|
cfg.unrestraint.permissive.add('disabled')
|
||||||
assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
|
assert cfg.unrestraint.permissive.get() == frozenset(['frozen', 'disabled'])
|
||||||
assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
|
assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
|
||||||
try:
|
try:
|
||||||
cfg.option('u1').value.set(1)
|
cfg.option('u1').value.set(1)
|
||||||
|
@ -229,7 +229,7 @@ def test_permissive_option(config_type):
|
||||||
|
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.option('u1').permissive.add('disabled')
|
cfg_ori.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
props = frozenset()
|
props = frozenset()
|
||||||
try:
|
try:
|
||||||
|
@ -293,7 +293,7 @@ def test_permissive_option_cache():
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert set(props) == {'disabled'}
|
assert set(props) == {'disabled'}
|
||||||
|
|
||||||
cfg.option('u1').permissive.add('disabled')
|
cfg.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
|
||||||
props = frozenset()
|
props = frozenset()
|
||||||
try:
|
try:
|
||||||
cfg.option('u1').value.get()
|
cfg.option('u1').value.get()
|
||||||
|
@ -342,9 +342,8 @@ def test_permissive_option_mandatory():
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert frozenset(props) == frozenset(['disabled'])
|
assert frozenset(props) == frozenset(['disabled'])
|
||||||
cfg.option('u1').permissive.add('mandatory')
|
cfg.unrestraint.option('u1').permissive.set(frozenset(['mandatory', 'disabled']))
|
||||||
cfg.option('u1').permissive.add('disabled')
|
assert cfg.unrestraint.option('u1').permissive.get() == frozenset(['mandatory', 'disabled'])
|
||||||
assert cfg.option('u1').permissive.get() == frozenset(['mandatory', 'disabled'])
|
|
||||||
cfg.property.add('permissive')
|
cfg.property.add('permissive')
|
||||||
cfg.option('u1').value.get()
|
cfg.option('u1').value.get()
|
||||||
cfg.property.remove('permissive')
|
cfg.property.remove('permissive')
|
||||||
|
@ -360,8 +359,7 @@ def test_permissive_option_frozen():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg.option('u1').permissive.add('disabled')
|
cfg.unrestraint.option('u1').permissive.set(frozenset(['frozen', 'disabled']))
|
||||||
cfg.option('u1').permissive.add('frozen')
|
|
||||||
cfg.option('u1').value.set(1)
|
cfg.option('u1').value.set(1)
|
||||||
assert cfg.option('u1').value.get() == 1
|
assert cfg.option('u1').value.get() == 1
|
||||||
cfg.property.add('permissive')
|
cfg.property.add('permissive')
|
||||||
|
@ -371,6 +369,15 @@ def test_permissive_option_frozen():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_option_permissive():
|
||||||
|
od1 = make_description()
|
||||||
|
cfg = Config(od1)
|
||||||
|
cfg.property.read_write()
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
cfg.unrestraint.option('u1').permissive.set(['frozen', 'disabled'])
|
||||||
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_remove_option_permissive(config_type):
|
def test_remove_option_permissive(config_type):
|
||||||
var1 = StrOption('var1', '', u'value', properties=('hidden',))
|
var1 = StrOption('var1', '', u'value', properties=('hidden',))
|
||||||
od1 = OptionDescription('od1', '', [var1])
|
od1 = OptionDescription('od1', '', [var1])
|
||||||
|
@ -382,13 +389,13 @@ def test_remove_option_permissive(config_type):
|
||||||
cfg.option('od1.var1').value.get()
|
cfg.option('od1.var1').value.get()
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.forcepermissive.option('od1.var1').permissive.add('hidden')
|
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
|
||||||
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
|
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
assert cfg.option('od1.var1').value.get() == 'value'
|
assert cfg.option('od1.var1').value.get() == 'value'
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.forcepermissive.option('od1.var1').permissive.reset()
|
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset())
|
||||||
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset()
|
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset()
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
with pytest.raises(PropertiesOptionError):
|
with pytest.raises(PropertiesOptionError):
|
||||||
|
@ -407,7 +414,7 @@ def test_reset_option_permissive(config_type):
|
||||||
cfg.option('od1.var1').value.get()
|
cfg.option('od1.var1').value.get()
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.forcepermissive.option('od1.var1').permissive.add('hidden')
|
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
|
||||||
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
|
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
assert cfg.option('od1.var1').value.get() == 'value'
|
assert cfg.option('od1.var1').value.get() == 'value'
|
||||||
|
|
|
@ -31,12 +31,12 @@ def test_properties(config_type):
|
||||||
assert frozenset(props) == frozenset(['disabled'])
|
assert frozenset(props) == frozenset(['disabled'])
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.unrestraint.option('ip_address_service').permissive.add('disabled')
|
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
cfg.option('ip_address_service').value.get()
|
cfg.option('ip_address_service').value.get()
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.unrestraint.option('ip_address_service').permissive.remove('disabled')
|
cfg_ori.unrestraint.option('ip_address_service').property.add('disabled')
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
props = []
|
props = []
|
||||||
try:
|
try:
|
||||||
|
@ -47,8 +47,8 @@ def test_properties(config_type):
|
||||||
# pop twice
|
# pop twice
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
cfg_ori.unrestraint.option('ip_address_service').permissive.add('disabled')
|
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
|
||||||
cfg_ori.unrestraint.option('ip_address_service').permissive.remove('disabled')
|
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,10 +196,10 @@ def test_requires_same_action(config_type):
|
||||||
submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
||||||
if config_type == 'tiramisu':
|
if config_type == 'tiramisu':
|
||||||
submsg = '"new" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
submsg = '"new" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
||||||
submsg = '"disabled" (' + str(_('cannot access to {0} {1} because has {2} {3}').format('option', '"activate_service_web"', _('property'), submsg)) + ')'
|
submsg = '"disabled" (' + str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'activate_service_web', _('property'), submsg)) + ')'
|
||||||
assert str(err) == str(_('cannot access to {0} {1} because has {2} {3}').format('option', '"ip_address_service_web"', _('property'), submsg))
|
assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg))
|
||||||
#access to cache
|
#access to cache
|
||||||
assert str(err) == str(_('cannot access to {0} {1} because has {2} {3}').format('option', '"ip_address_service_web"', _('property'), submsg))
|
assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg))
|
||||||
else:
|
else:
|
||||||
# FIXME
|
# FIXME
|
||||||
assert str(err) == 'error'
|
assert str(err) == 'error'
|
||||||
|
@ -426,9 +426,8 @@ def test_requires_transitive_unrestraint(config_type):
|
||||||
#
|
#
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
assert cfg_ori.option('activate_service_web').property.get() == {'disabled'}
|
assert cfg_ori.unrestraint.option('activate_service_web').property.get() == {'disabled'}
|
||||||
# FIXME assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
||||||
assert cfg_ori.option('ip_address_service_web').property.get() == {'disabled'}
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -592,7 +591,7 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
|
||||||
cfg.option('activate_service').value.set(False)
|
cfg.option('activate_service').value.set(False)
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
req = err
|
req = err
|
||||||
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option {0} because required option {1} has {2} {3}').format('ip_address_service_web', '"activate_service_web"', _('property'), '"disabled"')))
|
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option "{0}" because required option "{1}" has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('property'), '"disabled"')))
|
||||||
else:
|
else:
|
||||||
cfg.option('activate_service').value.set(False)
|
cfg.option('activate_service').value.set(False)
|
||||||
#
|
#
|
||||||
|
@ -608,26 +607,25 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
|
||||||
cfg.option('ip_address_service_web').value.get()
|
cfg.option('ip_address_service_web').value.get()
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
req = err
|
req = err
|
||||||
error_msg = str(_('unable to carry out a calculation for {}, {}').format('"ip_address_service_web"', _('cannot access to {0} {1} because has {2} {3}').format('option', '"activate_service_web"', _('property'), display_list(['disabled'], add_quote=True))))
|
error_msg = str(_('unable to carry out a calculation for "{}", {}').format('ip_address_service_web', _('cannot access to {0} "{1}" because has {2} {3}').format('option', 'activate_service_web', _('property'), display_list(['disabled'], add_quote=True))))
|
||||||
assert req, "ip_address_service_web should raise ConfigError"
|
assert req, "ip_address_service_web should raise ConfigError"
|
||||||
assert str(req) == error_msg
|
assert str(req) == error_msg
|
||||||
del req
|
del req
|
||||||
#
|
#
|
||||||
cfg_ori.permissive.reset()
|
cfg_ori.permissive.reset()
|
||||||
cfg_ori.permissive.remove('hidden')
|
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
try:
|
try:
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
req = err
|
req = err
|
||||||
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option "{0}" because required option {1} has {2} {3}').format('ip_address_service_web', '"activate_service_web"', _('properties'), '"disabled" {} "hidden"'.format(_('and')))))
|
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option "{0}" because required option "{1}" has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('properties'), '"disabled" {} "hidden"'.format(_('and')))))
|
||||||
else:
|
else:
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
try:
|
try:
|
||||||
cfg.option('ip_address_service_web').value.get()
|
cfg.option('ip_address_service_web').value.get()
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
req = err
|
req = err
|
||||||
error_msg = str(_('unable to carry out a calculation for {}, {}').format('"ip_address_service_web"', _('cannot access to {0} {1} because has {2} {3}').format('option', '"activate_service_web"', _('properties'), display_list(['hidden', 'disabled'], add_quote=True))))
|
error_msg = str(_('unable to carry out a calculation for "{}", {}').format('ip_address_service_web', _('cannot access to {0} "{1}" because has {2} {3}').format('option', 'activate_service_web', _('properties'), display_list(['hidden', 'disabled'], add_quote=True))))
|
||||||
assert req, "ip_address_service_web should raise ConfigError"
|
assert req, "ip_address_service_web should raise ConfigError"
|
||||||
assert str(req) == error_msg
|
assert str(req) == error_msg
|
||||||
del req
|
del req
|
||||||
|
|
|
@ -115,18 +115,18 @@ def test_append_submulti():
|
||||||
#
|
#
|
||||||
assert cfg.option('multi2').value.get() == []
|
assert cfg.option('multi2').value.get() == []
|
||||||
assert cfg.option('multi2').owner.get() == owners.default
|
assert cfg.option('multi2').owner.get() == owners.default
|
||||||
cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti()])
|
cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti()])
|
||||||
assert cfg.option('multi2').owner.get() == owner
|
assert cfg.option('multi2').owner.get() == owner
|
||||||
assert cfg.option('multi2').value.get() == [['yes']]
|
assert cfg.option('multi2').value.get() == [['yes']]
|
||||||
cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti(), ['no']])
|
cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti(), ['no']])
|
||||||
assert cfg.option('multi2').value.get() == [['yes'], ['no']]
|
assert cfg.option('multi2').value.get() == [['yes'], ['no']]
|
||||||
#
|
#
|
||||||
assert cfg.option('multi3').value.get() == [['yes']]
|
assert cfg.option('multi3').value.get() == [['yes']]
|
||||||
assert cfg.option('multi3').owner.get() == owners.default
|
assert cfg.option('multi3').owner.get() == owners.default
|
||||||
cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), []])
|
cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), []])
|
||||||
assert cfg.option('multi3').owner.get() == owner
|
assert cfg.option('multi3').owner.get() == owner
|
||||||
assert cfg.option('multi3').value.get() == [['yes'], []]
|
assert cfg.option('multi3').value.get() == [['yes'], []]
|
||||||
cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), [], ['no']])
|
cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), [], ['no']])
|
||||||
assert cfg.option('multi3').value.get() == [['yes'], [], ['no']]
|
assert cfg.option('multi3').value.get() == [['yes'], [], ['no']]
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ def test_callback_submulti_str():
|
||||||
owner = cfg.owner.get()
|
owner = cfg.owner.get()
|
||||||
assert cfg.option('multi').owner.get() == owners.default
|
assert cfg.option('multi').owner.get() == owners.default
|
||||||
assert cfg.option('multi').value.get() == [['val']]
|
assert cfg.option('multi').value.get() == [['val']]
|
||||||
cfg.option('multi').value.set([['val'], cfg.option('multi').value.defaultmulti()])
|
cfg.option('multi').value.set([['val'], cfg.option('multi').defaultmulti()])
|
||||||
assert cfg.option('multi').owner.get() == owner
|
assert cfg.option('multi').owner.get() == owner
|
||||||
assert cfg.option('multi').value.get() == [['val'], ['val']]
|
assert cfg.option('multi').value.get() == [['val'], ['val']]
|
||||||
cfg.option('multi').value.reset()
|
cfg.option('multi').value.reset()
|
||||||
|
@ -209,10 +209,10 @@ def test_callback_submulti_list():
|
||||||
owner = cfg.owner.get()
|
owner = cfg.owner.get()
|
||||||
assert cfg.option('multi').value.get() == [['val', 'val']]
|
assert cfg.option('multi').value.get() == [['val', 'val']]
|
||||||
assert cfg.option('multi').owner.get() == owners.default
|
assert cfg.option('multi').owner.get() == owners.default
|
||||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()])
|
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()])
|
||||||
assert cfg.option('multi').owner.get() == owner
|
assert cfg.option('multi').owner.get() == owner
|
||||||
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']]
|
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']]
|
||||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti(), cfg.option('multi').value.defaultmulti()])
|
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti(), cfg.option('multi').defaultmulti()])
|
||||||
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']]
|
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']]
|
||||||
cfg.option('multi').value.reset()
|
cfg.option('multi').value.reset()
|
||||||
assert cfg.option('multi').owner.get() == owners.default
|
assert cfg.option('multi').owner.get() == owners.default
|
||||||
|
@ -227,7 +227,7 @@ def test_callback_submulti_list_list():
|
||||||
owner = cfg.owner.get()
|
owner = cfg.owner.get()
|
||||||
assert cfg.option('multi').value.get() == [['val', 'val']]
|
assert cfg.option('multi').value.get() == [['val', 'val']]
|
||||||
assert cfg.option('multi').owner.get() == owners.default
|
assert cfg.option('multi').owner.get() == owners.default
|
||||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()])
|
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()])
|
||||||
assert cfg.option('multi').owner.get() == owner
|
assert cfg.option('multi').owner.get() == owner
|
||||||
assert cfg.option('multi').value.get() == [['val', 'val'], []]
|
assert cfg.option('multi').value.get() == [['val', 'val'], []]
|
||||||
cfg.option('multi').value.reset()
|
cfg.option('multi').value.reset()
|
||||||
|
|
|
@ -26,8 +26,8 @@ def test_symlink_option(config_type):
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert not cfg.option('s1.b').issymlinkoption()
|
assert not cfg.option('s1.b').issymlinkoption()
|
||||||
assert cfg.option('c').issymlinkoption()
|
assert cfg.option('c').issymlinkoption()
|
||||||
assert cfg.option('s1.b').type() == 'boolean'
|
assert cfg.option('s1.b').type() == _('boolean')
|
||||||
assert cfg.option('c').type() == 'boolean'
|
assert cfg.option('c').type() == _('boolean')
|
||||||
assert cfg.option('s1.b').value.get() is False
|
assert cfg.option('s1.b').value.get() is False
|
||||||
cfg.option("s1.b").value.set(True)
|
cfg.option("s1.b").value.set(True)
|
||||||
cfg.option("s1.b").value.set(False)
|
cfg.option("s1.b").value.set(False)
|
||||||
|
@ -54,13 +54,17 @@ def test_symlink_default(config_type):
|
||||||
assert not cfg.option('c').ismulti()
|
assert not cfg.option('c').ismulti()
|
||||||
assert not cfg.option('s1.b').issubmulti()
|
assert not cfg.option('s1.b').issubmulti()
|
||||||
assert not cfg.option('c').issubmulti()
|
assert not cfg.option('c').issubmulti()
|
||||||
|
assert not cfg.option('s1.b').default()
|
||||||
|
assert not cfg.option('c').default()
|
||||||
assert not cfg.option('s1.b').value.default()
|
assert not cfg.option('s1.b').value.default()
|
||||||
assert not cfg.option('c').value.default()
|
assert not cfg.option('c').value.default()
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
assert not cfg.option('s1.b').value.defaultmulti()
|
assert not cfg.option('s1.b').defaultmulti()
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
assert not cfg.option('c').value.defaultmulti()
|
assert not cfg.option('c').defaultmulti()
|
||||||
cfg.option("s1.b").value.set(True)
|
cfg.option("s1.b").value.set(True)
|
||||||
|
assert not cfg.option('s1.b').default()
|
||||||
|
assert not cfg.option('c').default()
|
||||||
assert not cfg.option('s1.b').value.default()
|
assert not cfg.option('s1.b').value.default()
|
||||||
assert not cfg.option('c').value.default()
|
assert not cfg.option('c').value.default()
|
||||||
## assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
@ -78,15 +82,19 @@ def test_symlink_default_multi(config_type):
|
||||||
assert cfg.option('c').ismulti()
|
assert cfg.option('c').ismulti()
|
||||||
assert not cfg.option('s1.b').issubmulti()
|
assert not cfg.option('s1.b').issubmulti()
|
||||||
assert not cfg.option('c').issubmulti()
|
assert not cfg.option('c').issubmulti()
|
||||||
|
assert cfg.option('s1.b').default() == [False]
|
||||||
|
assert cfg.option('c').default() == [False]
|
||||||
assert cfg.option('s1.b').value.default() == [False]
|
assert cfg.option('s1.b').value.default() == [False]
|
||||||
assert cfg.option('c').value.default() == [False]
|
assert cfg.option('c').value.default() == [False]
|
||||||
assert cfg.option('s1.b').value.defaultmulti()
|
assert cfg.option('s1.b').defaultmulti()
|
||||||
assert cfg.option('c').value.defaultmulti()
|
assert cfg.option('c').defaultmulti()
|
||||||
cfg.option("s1.b").value.set([True])
|
cfg.option("s1.b").value.set([True])
|
||||||
|
assert cfg.option('s1.b').default() == [False]
|
||||||
|
assert cfg.option('c').default() == [False]
|
||||||
assert cfg.option('s1.b').value.default() == [False]
|
assert cfg.option('s1.b').value.default() == [False]
|
||||||
assert cfg.option('c').value.default() == [False]
|
assert cfg.option('c').value.default() == [False]
|
||||||
assert cfg.option('s1.b').value.defaultmulti()
|
assert cfg.option('s1.b').defaultmulti()
|
||||||
assert cfg.option('c').value.defaultmulti()
|
assert cfg.option('c').defaultmulti()
|
||||||
## assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,7 +141,7 @@ def test_symlink_getpermissive():
|
||||||
od1 = OptionDescription('opt', '', [boolopt, linkopt])
|
od1 = OptionDescription('opt', '', [boolopt, linkopt])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg.option('b').permissive.add('perm')
|
cfg.option('b').permissive.set(frozenset(['perm']))
|
||||||
cfg.option('c').permissive.get() == frozenset(['perm'])
|
cfg.option('c').permissive.get() == frozenset(['perm'])
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
@ -258,26 +266,14 @@ def test_symlink_owner(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_get_information():
|
def test_symlink_get_information():
|
||||||
boolopt = BoolOption("b", "", default=False, informations={'test': 'test'})
|
|
||||||
linkopt = SymLinkOption("c", boolopt)
|
|
||||||
od1 = OptionDescription('opt', '', [linkopt, boolopt])
|
|
||||||
cfg = Config(od1)
|
|
||||||
assert cfg.option('b').information.get('test') == 'test'
|
|
||||||
assert cfg.option('c').information.get('test') == 'test'
|
|
||||||
cfg.option('b').information.set('test', 'test2')
|
|
||||||
assert cfg.option('b').information.get('test') == 'test2'
|
|
||||||
assert cfg.option('c').information.get('test') == 'test2'
|
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_informations():
|
|
||||||
boolopt = BoolOption("b", "", default=False)
|
boolopt = BoolOption("b", "", default=False)
|
||||||
with pytest.raises(TypeError):
|
|
||||||
linkopt = SymLinkOption("c", boolopt, informations={'test': 'test'})
|
|
||||||
linkopt = SymLinkOption("c", boolopt)
|
linkopt = SymLinkOption("c", boolopt)
|
||||||
od1 = OptionDescription('opt', '', [linkopt, boolopt])
|
boolopt.impl_set_information('test', 'test')
|
||||||
cfg = Config(od1)
|
assert boolopt.impl_get_information('test') == 'test'
|
||||||
with pytest.raises(ConfigError):
|
assert linkopt.impl_get_information('test') == 'test'
|
||||||
cfg.option('c').information.set('test', 'test2')
|
boolopt.impl_set_information('test', 'test2')
|
||||||
|
assert boolopt.impl_get_information('test') == 'test2'
|
||||||
|
assert linkopt.impl_get_information('test') == 'test2'
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_leader():
|
def test_symlink_leader():
|
||||||
|
@ -289,59 +285,11 @@ def test_symlink_leader():
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_followers():
|
def test_symlink_followers():
|
||||||
|
a = StrOption('a', "", multi=True)
|
||||||
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 = SymLinkOption('netmask_admin_eth0', ip_admin_eth0)
|
netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', a)
|
||||||
leader = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
with pytest.raises(ValueError):
|
||||||
od1 = OptionDescription('opt', '', [leader])
|
Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
cfg = Config(od1)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': []}
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
|
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val2'
|
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'user'
|
|
||||||
assert parse_od_get(cfg.value.get()) == {
|
|
||||||
'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1',
|
|
||||||
'ip_admin_eth0.netmask_admin_eth0': 'val1'},
|
|
||||||
{'ip_admin_eth0.ip_admin_eth0': 'val2',
|
|
||||||
'ip_admin_eth0.netmask_admin_eth0': 'val2'}],
|
|
||||||
}
|
|
||||||
|
|
||||||
def test_symlink_leader_default():
|
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", ['val1', 'val2'], multi=True)
|
|
||||||
netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', ip_admin_eth0)
|
|
||||||
leader = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od1 = OptionDescription('opt', '', [leader])
|
|
||||||
cfg = Config(od1)
|
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val2'
|
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.isdefault()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {
|
|
||||||
'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1',
|
|
||||||
'ip_admin_eth0.netmask_admin_eth0': 'val1'},
|
|
||||||
{'ip_admin_eth0.ip_admin_eth0': 'val2',
|
|
||||||
'ip_admin_eth0.netmask_admin_eth0': 'val2'}],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_followers_2():
|
|
||||||
variable1 = StrOption('variable1', "", multi=True)
|
|
||||||
variable2 = StrOption('variable2', "", multi=True)
|
|
||||||
variable3 = SymLinkOption('variable3', variable2)
|
|
||||||
leader = Leadership('variable1', '', [variable1, variable2, variable3])
|
|
||||||
od1 = OptionDescription('opt', '', [leader])
|
|
||||||
cfg = Config(od1)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'variable1.variable1': []}
|
|
||||||
cfg.option('variable1.variable1').value.set(['val1', 'val2'])
|
|
||||||
cfg.option('variable1.variable2', 0).value.set('ival1')
|
|
||||||
cfg.option('variable1.variable2', 1).value.set('ival2')
|
|
||||||
assert cfg.option('variable1.variable3', 1).owner.get() == 'user'
|
|
||||||
assert cfg.option('variable1.variable3', 1).value.get() == 'ival2'
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'variable1.variable1': [{'variable1.variable1': 'val1',
|
|
||||||
'variable1.variable2': 'ival1',
|
|
||||||
'variable1.variable3': 'ival1'},
|
|
||||||
{'variable1.variable1': 'val2',
|
|
||||||
'variable1.variable2': 'ival2',
|
|
||||||
'variable1.variable3': 'ival2'}],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_with_leader(config_type):
|
def test_symlink_with_leader(config_type):
|
||||||
|
@ -411,9 +359,9 @@ def test_symlink_dependency():
|
||||||
[linkopt, OptionDescription("s1", "", [boolopt])])
|
[linkopt, OptionDescription("s1", "", [boolopt])])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.option('s1.b').has_dependency() is False
|
assert cfg.option('s1.b').has_dependency() is False
|
||||||
assert cfg.option('c').has_dependency() is False
|
assert cfg.option('c').has_dependency() is True
|
||||||
assert cfg.option('s1.b').has_dependency(False) is True
|
assert cfg.option('s1.b').has_dependency(False) is True
|
||||||
assert cfg.option('c').has_dependency(False) is True
|
assert cfg.option('c').has_dependency(False) is False
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
@ -437,13 +385,13 @@ def test_symlink_list(config_type):
|
||||||
[linkopt, OptionDescription("s1", "", [boolopt])])
|
[linkopt, OptionDescription("s1", "", [boolopt])])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert [opt.path() for opt in cfg.list()] == ['c', 's1']
|
assert [opt.path() for opt in cfg.option.list()] == ['c', 's1']
|
||||||
#
|
#
|
||||||
assert [opt.path() for opt in cfg.option('s1').list()] == ['s1.b']
|
assert [opt.path() for opt in cfg.option('s1').list()] == ['s1.b']
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_submulti():
|
def test_submulti():
|
||||||
multi = StrOption('multi', '', multi=submulti)
|
multi = StrOption('multi', '', multi=submulti)
|
||||||
multi2 = SymLinkOption('multi2', multi)
|
multi2 = SymLinkOption('multi2', multi)
|
||||||
od1 = OptionDescription('od', '', [multi, multi2])
|
od1 = OptionDescription('od', '', [multi, multi2])
|
||||||
|
@ -452,13 +400,3 @@ def test_symlink_submulti():
|
||||||
assert cfg.option('multi').issubmulti()
|
assert cfg.option('multi').issubmulti()
|
||||||
assert cfg.option('multi2').ismulti()
|
assert cfg.option('multi2').ismulti()
|
||||||
assert cfg.option('multi2').issubmulti()
|
assert cfg.option('multi2').issubmulti()
|
||||||
|
|
||||||
|
|
||||||
def test_symlink_get_option():
|
|
||||||
multi = StrOption('multi', '', multi=submulti)
|
|
||||||
multi2 = SymLinkOption('multi2', multi)
|
|
||||||
od1 = OptionDescription('od', '', [multi, multi2])
|
|
||||||
cfg = Config(od1)
|
|
||||||
option = cfg.option('multi2').option()
|
|
||||||
assert option.name() == 'multi'
|
|
||||||
assert option.path() == 'multi'
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -14,29 +14,11 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""Configuration management library written in python
|
"""Configuration management library written in python
|
||||||
"""
|
"""
|
||||||
from .function import (
|
from .function import calc_value, calc_value_property_help, valid_ip_netmask, \
|
||||||
calc_value,
|
valid_network_netmask, valid_in_network, valid_broadcast, \
|
||||||
calc_value_property_help,
|
valid_not_equal, function_waiting_for_dict
|
||||||
valid_ip_netmask,
|
from .autolib import Calculation, Params, ParamOption, ParamDynOption, ParamSelfOption, \
|
||||||
valid_network_netmask,
|
ParamValue, ParamIndex, ParamSuffix, ParamInformation, ParamSelfInformation
|
||||||
valid_in_network,
|
|
||||||
valid_broadcast,
|
|
||||||
valid_not_equal,
|
|
||||||
function_waiting_for_dict,
|
|
||||||
function_waiting_for_error,
|
|
||||||
)
|
|
||||||
from .autolib import (
|
|
||||||
Calculation,
|
|
||||||
Params,
|
|
||||||
ParamOption,
|
|
||||||
ParamDynOption,
|
|
||||||
ParamSelfOption,
|
|
||||||
ParamValue,
|
|
||||||
ParamIndex,
|
|
||||||
ParamIdentifier,
|
|
||||||
ParamInformation,
|
|
||||||
ParamSelfInformation,
|
|
||||||
)
|
|
||||||
from .option import *
|
from .option import *
|
||||||
from .error import ConfigError
|
from .error import ConfigError
|
||||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||||
|
@ -44,36 +26,34 @@ from .option import __all__ as all_options
|
||||||
from .setting import owners, groups, undefined
|
from .setting import owners, groups, undefined
|
||||||
|
|
||||||
|
|
||||||
allfuncs = [
|
allfuncs = ['Calculation',
|
||||||
"Calculation",
|
'Params',
|
||||||
"Params",
|
'ParamOption',
|
||||||
"ParamOption",
|
'ParamDynOption',
|
||||||
"ParamDynOption",
|
'ParamSelfOption',
|
||||||
"ParamSelfOption",
|
'ParamValue',
|
||||||
"ParamValue",
|
'ParamIndex',
|
||||||
"ParamIndex",
|
'ParamSuffix',
|
||||||
"ParamIdentifier",
|
'ParamInformation',
|
||||||
"ParamInformation",
|
'ParamSelfInformation',
|
||||||
"ParamSelfInformation",
|
'MetaConfig',
|
||||||
"MetaConfig",
|
'MixConfig',
|
||||||
"MixConfig",
|
'GroupConfig',
|
||||||
"GroupConfig",
|
'Config',
|
||||||
"Config",
|
'ConfigError',
|
||||||
"ConfigError",
|
'undefined',
|
||||||
"undefined",
|
'owners',
|
||||||
"owners",
|
'groups',
|
||||||
"groups",
|
'calc_value',
|
||||||
"calc_value",
|
'calc_value_property_help',
|
||||||
"calc_value_property_help",
|
'valid_ip_netmask',
|
||||||
"valid_ip_netmask",
|
'valid_network_netmask',
|
||||||
"valid_network_netmask",
|
'valid_in_network',
|
||||||
"valid_in_network",
|
'valid_broadcast',
|
||||||
"valid_broadcast",
|
'function_waiting_for_dict',
|
||||||
"function_waiting_for_dict",
|
]
|
||||||
"function_waiting_for_error",
|
|
||||||
]
|
|
||||||
allfuncs.extend(all_options)
|
allfuncs.extend(all_options)
|
||||||
del all_options
|
del(all_options)
|
||||||
__all__ = tuple(allfuncs)
|
__all__ = tuple(allfuncs)
|
||||||
del allfuncs
|
del(allfuncs)
|
||||||
__version__ = "4.1.0"
|
__version__ = "4.1.0"
|
||||||
|
|
1675
tiramisu/api.py
1675
tiramisu/api.py
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"cache used by storage"
|
"cache used by storage"
|
||||||
# Copyright (C) 2013-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2013-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -19,9 +19,9 @@ from time import time
|
||||||
|
|
||||||
|
|
||||||
class Cache:
|
class Cache:
|
||||||
"""cache object"""
|
"""cache object
|
||||||
|
"""
|
||||||
__slots__ = ("_cache",)
|
__slots__ = ('_cache',)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._cache = {}
|
self._cache = {}
|
||||||
|
@ -35,30 +35,34 @@ class Cache:
|
||||||
index = subconfig.index
|
index = subconfig.index
|
||||||
return path, index
|
return path, index
|
||||||
|
|
||||||
def getcache(
|
def getcache(self,
|
||||||
self,
|
|
||||||
subconfig,
|
subconfig,
|
||||||
type_,
|
type_,
|
||||||
expiration=True,
|
expiration=True,
|
||||||
):
|
):
|
||||||
"""get the cache value fot a specified path"""
|
"""get the cache value fot a specified path
|
||||||
|
"""
|
||||||
no_cache = False, None, False
|
no_cache = False, None, False
|
||||||
path, index = self._get_path_index(subconfig)
|
path, index = self._get_path_index(subconfig)
|
||||||
if path not in self._cache or index not in self._cache[path]:
|
if path not in self._cache or index not in self._cache[path]:
|
||||||
return no_cache
|
return no_cache
|
||||||
value, timestamp, validated = self._cache[path][index]
|
value, timestamp, validated = self._cache[path][index]
|
||||||
|
if type_ == 'context_props':
|
||||||
|
# cached value is settings properties so value is props
|
||||||
|
props = value
|
||||||
|
self_props = {}
|
||||||
|
else:
|
||||||
props = subconfig.config_bag.properties
|
props = subconfig.config_bag.properties
|
||||||
if type_ == "self_props":
|
if type_ == 'self_props':
|
||||||
# cached value is self_props
|
# cached value is self_props
|
||||||
self_props = value
|
self_props = value
|
||||||
else:
|
else:
|
||||||
self_props = subconfig.properties
|
self_props = subconfig.properties
|
||||||
if "cache" in props or "cache" in self_props:
|
if 'cache' in props or \
|
||||||
if (
|
'cache' in self_props:
|
||||||
expiration
|
if expiration and timestamp and \
|
||||||
and timestamp
|
('expire' in props or \
|
||||||
and ("expire" in props or "expire" in self_props)
|
'expire' in self_props):
|
||||||
):
|
|
||||||
ntime = int(time())
|
ntime = int(time())
|
||||||
if timestamp + subconfig.config_bag.expiration_time >= ntime:
|
if timestamp + subconfig.config_bag.expiration_time >= ntime:
|
||||||
return True, value, validated
|
return True, value, validated
|
||||||
|
@ -66,38 +70,37 @@ class Cache:
|
||||||
return True, value, validated
|
return True, value, validated
|
||||||
return no_cache
|
return no_cache
|
||||||
|
|
||||||
def setcache(
|
def setcache(self,
|
||||||
self,
|
|
||||||
subconfig,
|
subconfig,
|
||||||
val,
|
val,
|
||||||
type_="values",
|
type_='values',
|
||||||
validated=True,
|
validated=True,
|
||||||
):
|
):
|
||||||
"""add val in cache for a specified path
|
"""add val in cache for a specified path
|
||||||
if follower, add index
|
if follower, add index
|
||||||
"""
|
"""
|
||||||
if type_ == "values":
|
if type_ == 'values':
|
||||||
if (
|
if 'cache' not in subconfig.config_bag.properties and \
|
||||||
"cache" not in subconfig.config_bag.properties
|
'cache' not in subconfig.properties:
|
||||||
and "cache" not in subconfig.properties
|
|
||||||
):
|
|
||||||
return
|
return
|
||||||
elif (
|
elif (subconfig is None or 'cache' not in subconfig.config_bag.properties) and \
|
||||||
subconfig is None or "cache" not in subconfig.config_bag.properties
|
'cache' not in val:
|
||||||
) and "cache" not in val:
|
|
||||||
return
|
return
|
||||||
path, index = self._get_path_index(subconfig)
|
path, index = self._get_path_index(subconfig)
|
||||||
self._cache.setdefault(path, {})[index] = (val, int(time()), validated)
|
self._cache.setdefault(path, {})[index] = (val, int(time()), validated)
|
||||||
|
|
||||||
def delcache(self, path):
|
def delcache(self, path):
|
||||||
"""reset cache a a specified path"""
|
"""reset cache a a specified path
|
||||||
|
"""
|
||||||
if path in self._cache:
|
if path in self._cache:
|
||||||
del self._cache[path]
|
del self._cache[path]
|
||||||
|
|
||||||
def get_cached(self):
|
def get_cached(self):
|
||||||
"""get cache values"""
|
"""get cache values
|
||||||
|
"""
|
||||||
return self._cache
|
return self._cache
|
||||||
|
|
||||||
def reset_all_cache(self):
|
def reset_all_cache(self):
|
||||||
"""reset all cache values"""
|
"""reset all cache values
|
||||||
|
"""
|
||||||
self._cache.clear()
|
self._cache.clear()
|
||||||
|
|
1121
tiramisu/config.py
1121
tiramisu/config.py
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -19,18 +19,13 @@ import weakref
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
|
||||||
|
|
||||||
def display_list(
|
def display_list(lst, separator='and', add_quote=False):
|
||||||
lst,
|
|
||||||
*,
|
|
||||||
separator="and",
|
|
||||||
add_quote=False,
|
|
||||||
) -> str():
|
|
||||||
if not lst:
|
if not lst:
|
||||||
return '""'
|
return '""'
|
||||||
if separator == "and":
|
if separator == 'and':
|
||||||
separator = _("and")
|
separator = _('and')
|
||||||
elif separator == "or":
|
elif separator == 'or':
|
||||||
separator = _("or")
|
separator = _('or')
|
||||||
if isinstance(lst, tuple) or isinstance(lst, frozenset):
|
if isinstance(lst, tuple) or isinstance(lst, frozenset):
|
||||||
lst = list(lst)
|
lst = list(lst)
|
||||||
if len(lst) == 1:
|
if len(lst) == 1:
|
||||||
|
@ -52,37 +47,31 @@ def display_list(
|
||||||
lst__.append(l)
|
lst__.append(l)
|
||||||
lst__.sort()
|
lst__.sort()
|
||||||
last = lst__[-1]
|
last = lst__[-1]
|
||||||
return ", ".join(lst__[:-1]) + _(" {} ").format(separator) + "{}".format(last)
|
return ', '.join(lst__[:-1]) + _(' {} ').format(separator) + '{}'.format(last)
|
||||||
|
|
||||||
|
|
||||||
# Exceptions for an Option
|
# Exceptions for an Option
|
||||||
class PropertiesOptionError(AttributeError):
|
class PropertiesOptionError(AttributeError):
|
||||||
"attempt to access to an option with a property that is not allowed"
|
"attempt to access to an option with a property that is not allowed"
|
||||||
|
def __init__(self,
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
subconfig,
|
subconfig,
|
||||||
proptype,
|
proptype,
|
||||||
settings,
|
settings,
|
||||||
opt_type=None,
|
opt_type=None,
|
||||||
name=None,
|
name=None,
|
||||||
orig_opt=None,
|
orig_opt=None,
|
||||||
help_properties=None,
|
help_properties=None):
|
||||||
):
|
|
||||||
if opt_type:
|
if opt_type:
|
||||||
self._opt_type = opt_type
|
self._opt_type = opt_type
|
||||||
self._name = name
|
self._name = name
|
||||||
self._orig_opt = orig_opt
|
self._orig_opt = orig_opt
|
||||||
else:
|
else:
|
||||||
if subconfig.option.impl_is_optiondescription():
|
if subconfig.option.impl_is_optiondescription():
|
||||||
self._opt_type = "optiondescription"
|
self._opt_type = 'optiondescription'
|
||||||
else:
|
else:
|
||||||
self._opt_type = "option"
|
self._opt_type = 'option'
|
||||||
self._name = subconfig.option.impl_get_display_name(
|
self._name = subconfig.option.impl_get_display_name()
|
||||||
subconfig, with_quote=True
|
|
||||||
)
|
|
||||||
self._orig_opt = None
|
self._orig_opt = None
|
||||||
self._subconfig = subconfig
|
|
||||||
self.proptype = proptype
|
self.proptype = proptype
|
||||||
self.help_properties = help_properties
|
self.help_properties = help_properties
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
|
@ -97,7 +86,7 @@ class PropertiesOptionError(AttributeError):
|
||||||
if self.msg is not None:
|
if self.msg is not None:
|
||||||
return self.msg
|
return self.msg
|
||||||
if self._settings is None:
|
if self._settings is None:
|
||||||
return "error"
|
return 'error'
|
||||||
if self.help_properties:
|
if self.help_properties:
|
||||||
properties = list(self.help_properties)
|
properties = list(self.help_properties)
|
||||||
else:
|
else:
|
||||||
|
@ -105,44 +94,42 @@ class PropertiesOptionError(AttributeError):
|
||||||
only_one = len(properties) == 1
|
only_one = len(properties) == 1
|
||||||
properties_msg = display_list(properties, add_quote=True)
|
properties_msg = display_list(properties, add_quote=True)
|
||||||
if only_one:
|
if only_one:
|
||||||
prop_msg = _("property")
|
prop_msg = _('property')
|
||||||
else:
|
else:
|
||||||
prop_msg = _("properties")
|
prop_msg = _('properties')
|
||||||
if properties == ["frozen"]:
|
if properties == ['frozen']:
|
||||||
if self._orig_opt:
|
if self._orig_opt:
|
||||||
msg = _('cannot modify the {0} {1} because "{2}" has {3} {4}')
|
msg = 'cannot modify the {0} "{1}" because "{2}" has {3} {4}'
|
||||||
else:
|
else:
|
||||||
msg = _("cannot modify the {0} {1} because has {2} {3}")
|
msg = 'cannot modify the {0} "{1}" because has {2} {3}'
|
||||||
else:
|
else:
|
||||||
if self._orig_opt:
|
if self._orig_opt:
|
||||||
msg = _('cannot access to {0} {1} because "{2}" has {3} {4}')
|
msg = 'cannot access to {0} "{1}" because "{2}" has {3} {4}'
|
||||||
else:
|
else:
|
||||||
msg = _("cannot access to {0} {1} because has {2} {3}")
|
msg = 'cannot access to {0} "{1}" because has {2} {3}'
|
||||||
if self._orig_opt:
|
if self._orig_opt:
|
||||||
# FIXME _orig_opt ?
|
self.msg = _(msg).format(self._opt_type,
|
||||||
self.msg = msg.format(
|
self._orig_opt.impl_get_display_name(),
|
||||||
self._opt_type,
|
|
||||||
self._orig_opt.impl_get_display_name(subconfig, with_quote=True),
|
|
||||||
self._name,
|
self._name,
|
||||||
prop_msg,
|
prop_msg,
|
||||||
properties_msg,
|
properties_msg)
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
self.msg = msg.format(self._opt_type, self._name, prop_msg, properties_msg)
|
self.msg = _(msg).format(self._opt_type,
|
||||||
|
self._name,
|
||||||
|
prop_msg,
|
||||||
|
properties_msg)
|
||||||
del self._opt_type, self._name
|
del self._opt_type, self._name
|
||||||
del self._settings, self._orig_opt
|
del self._settings, self._orig_opt
|
||||||
return self.msg
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
#____________________________________________________________
|
||||||
# Exceptions for a Config
|
# Exceptions for a Config
|
||||||
class ConfigError(Exception):
|
class ConfigError(Exception):
|
||||||
"""attempt to change an option's owner without a value
|
"""attempt to change an option's owner without a value
|
||||||
or in case of `_descr` is None
|
or in case of `_descr` is None
|
||||||
or if a calculation cannot be carried out"""
|
or if a calculation cannot be carried out"""
|
||||||
|
def __init__(self,
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
exp,
|
exp,
|
||||||
ori_err=None,
|
ori_err=None,
|
||||||
):
|
):
|
||||||
|
@ -155,8 +142,8 @@ class ConflictError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
#____________________________________________________________
|
||||||
# miscellaneous exceptions
|
# miscellaneous exceptions
|
||||||
class LeadershipError(Exception):
|
class LeadershipError(Exception):
|
||||||
"problem with a leadership's value length"
|
"problem with a leadership's value length"
|
||||||
pass
|
pass
|
||||||
|
@ -168,11 +155,16 @@ class ConstError(TypeError):
|
||||||
|
|
||||||
|
|
||||||
class _CommonError:
|
class _CommonError:
|
||||||
def __init__(self, subconfig, val, display_type, opt, err_msg, index):
|
def __init__(self,
|
||||||
|
val,
|
||||||
|
display_type,
|
||||||
|
opt,
|
||||||
|
err_msg,
|
||||||
|
index):
|
||||||
self.val = val
|
self.val = val
|
||||||
self.display_type = display_type
|
self.display_type = display_type
|
||||||
self.opt = weakref.ref(opt)
|
self.opt = weakref.ref(opt)
|
||||||
self.name = opt.impl_get_display_name(subconfig)
|
self.name = opt.impl_get_display_name()
|
||||||
self.err_msg = err_msg
|
self.err_msg = err_msg
|
||||||
self.index = index
|
self.index = index
|
||||||
super().__init__(self.err_msg)
|
super().__init__(self.err_msg)
|
||||||
|
@ -181,24 +173,24 @@ class _CommonError:
|
||||||
try:
|
try:
|
||||||
msg = self.prefix
|
msg = self.prefix
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.prefix = self.tmpl.format(self.val, _(self.display_type), self.name)
|
self.prefix = self.tmpl.format(self.val,
|
||||||
|
self.display_type,
|
||||||
|
self.name)
|
||||||
msg = self.prefix
|
msg = self.prefix
|
||||||
if self.err_msg:
|
if self.err_msg:
|
||||||
if msg:
|
if msg:
|
||||||
msg += ", {}".format(self.err_msg)
|
msg += ', {}'.format(self.err_msg)
|
||||||
else:
|
else:
|
||||||
msg = self.err_msg
|
msg = self.err_msg
|
||||||
if not msg:
|
if not msg:
|
||||||
msg = _("invalid value")
|
msg = _('invalid value')
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
class ValueWarning(_CommonError, UserWarning):
|
class ValueWarning(_CommonError, UserWarning):
|
||||||
tmpl = None
|
tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if ValueWarning.tmpl is None:
|
|
||||||
ValueWarning.tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"')
|
|
||||||
if len(args) == 1 and not kwargs:
|
if len(args) == 1 and not kwargs:
|
||||||
self.msg = args[0]
|
self.msg = args[0]
|
||||||
else:
|
else:
|
||||||
|
@ -212,18 +204,8 @@ class ValueWarning(_CommonError, UserWarning):
|
||||||
|
|
||||||
|
|
||||||
class ValueOptionError(_CommonError, ValueError):
|
class ValueOptionError(_CommonError, ValueError):
|
||||||
tmpl = None
|
tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if ValueOptionError.tmpl is None:
|
|
||||||
ValueOptionError.tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ValueErrorWarning(ValueWarning):
|
class ValueErrorWarning(ValueWarning):
|
||||||
tmpl = None
|
tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
if ValueErrorWarning.tmpl is None:
|
|
||||||
ValueErrorWarning.tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (C) 2018-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2018-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -23,7 +23,6 @@ from .error import display_list
|
||||||
|
|
||||||
|
|
||||||
FUNCTION_WAITING_FOR_DICT = []
|
FUNCTION_WAITING_FOR_DICT = []
|
||||||
FUNCTION_WAITING_FOR_ERROR = []
|
|
||||||
|
|
||||||
|
|
||||||
def function_waiting_for_dict(function):
|
def function_waiting_for_dict(function):
|
||||||
|
@ -37,94 +36,74 @@ def function_waiting_for_dict(function):
|
||||||
return function
|
return function
|
||||||
|
|
||||||
|
|
||||||
def function_waiting_for_error(function):
|
|
||||||
"""functions (calculation or validation) receive by default only the value of other options
|
|
||||||
set PropertyError too
|
|
||||||
"""
|
|
||||||
name = function.__name__
|
|
||||||
if name not in FUNCTION_WAITING_FOR_ERROR:
|
|
||||||
FUNCTION_WAITING_FOR_ERROR.append(name)
|
|
||||||
return function
|
|
||||||
|
|
||||||
|
|
||||||
@function_waiting_for_dict
|
@function_waiting_for_dict
|
||||||
def valid_network_netmask(
|
def valid_network_netmask(network: dict,
|
||||||
network: dict,
|
|
||||||
netmask: dict,
|
netmask: dict,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
validates if network and netmask are coherent
|
validates if network and netmask are coherent
|
||||||
this validator must be set to netmask option
|
this validator must be set to netmask option
|
||||||
"""
|
"""
|
||||||
if None in [network["value"], netmask["value"]]:
|
if None in [network['value'], netmask['value']]:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
ip_network(f'{network["value"]}/{netmask["value"]}')
|
ip_network(f'{network["value"]}/{netmask["value"]}')
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError(
|
raise ValueError(_(f'network "{network["value"]}" ({network["name"]}) does not match '
|
||||||
_('network "{0}" ({1}) does not match with this netmask').format(
|
'with this netmask')) from err
|
||||||
network["value"], network["name"]
|
|
||||||
)
|
|
||||||
) from err
|
|
||||||
|
|
||||||
|
|
||||||
@function_waiting_for_dict
|
@function_waiting_for_dict
|
||||||
def valid_ip_netmask(
|
def valid_ip_netmask(ip: dict, # pylint: disable=invalid-name
|
||||||
ip: dict, # pylint: disable=invalid-name
|
|
||||||
netmask: dict,
|
netmask: dict,
|
||||||
):
|
):
|
||||||
"""validates if ip and netmask are coherent
|
"""validates if ip and netmask are coherent
|
||||||
this validator must be set to netmask option
|
this validator must be set to netmask option
|
||||||
"""
|
"""
|
||||||
if None in [ip["value"], netmask["value"]]:
|
if None in [ip['value'], netmask['value']]:
|
||||||
return
|
return
|
||||||
ip_netmask = ip_interface(f'{ip["value"]}/{netmask["value"]}')
|
ip_netmask = ip_interface(f'{ip["value"]}/{netmask["value"]}')
|
||||||
if ip_netmask.ip == ip_netmask.network.network_address:
|
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||||
msg = _('IP "{0}" ({1}) with this netmask is in fact a network address').format(
|
msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is '
|
||||||
ip["value"], ip["name"]
|
'in fact a network address')
|
||||||
)
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||||
msg = _(
|
msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is '
|
||||||
'IP "{0}" ({1}) with this netmask is in fact a broadcast address'
|
'in fact a broacast address')
|
||||||
).format(ip["value"], ip["name"])
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
@function_waiting_for_dict
|
@function_waiting_for_dict
|
||||||
def valid_broadcast(
|
def valid_broadcast(network: dict,
|
||||||
network: dict,
|
|
||||||
netmask: dict,
|
netmask: dict,
|
||||||
broadcast: dict,
|
broadcast: dict,
|
||||||
):
|
):
|
||||||
"""validates if the broadcast is coherent with network and netmask"""
|
"""validates if the broadcast is coherent with network and netmask
|
||||||
if None in [network["value"], netmask["value"], broadcast["value"]]:
|
"""
|
||||||
|
if None in [network['value'], netmask['value'], broadcast['value']]:
|
||||||
return
|
return
|
||||||
if ip_network(
|
if ip_network(f'{network["value"]}/{netmask["value"]}').broadcast_address != \
|
||||||
f'{network["value"]}/{netmask["value"]}'
|
ip_address(broadcast['value']):
|
||||||
).broadcast_address != ip_address(broadcast["value"]):
|
msg = _(f'broadcast invalid with network {network["value"]} ({network["name"]}) '
|
||||||
msg = _(
|
f'and netmask {netmask["value"]} ({netmask["name"]})')
|
||||||
"broadcast invalid with network {0} ({1}) and netmask {2} ({3})"
|
|
||||||
).format(network["value"], network["name"], netmask["value"], netmask["name"])
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
@function_waiting_for_dict
|
@function_waiting_for_dict
|
||||||
def valid_in_network(
|
def valid_in_network(ip: dict, # pylint: disable=invalid-name
|
||||||
ip: dict, # pylint: disable=invalid-name
|
|
||||||
network: dict,
|
network: dict,
|
||||||
netmask=Optional[dict],
|
netmask=Optional[dict],
|
||||||
):
|
):
|
||||||
"""validates if an IP is in a network
|
"""validates if an IP is in a network
|
||||||
this validator must be set to ip option
|
this validator must be set to ip option
|
||||||
"""
|
"""
|
||||||
if None in [ip["value"], network["value"]]:
|
if None in [ip['value'], network['value']]:
|
||||||
return
|
return
|
||||||
if "/" in network["value"]:
|
if '/' in network['value']:
|
||||||
# it's a CIDR network
|
# it's a CIDR network
|
||||||
network_value = network["value"]
|
network_value = network['value']
|
||||||
else:
|
else:
|
||||||
if netmask is None or netmask["value"] is None:
|
if netmask is None or netmask['value'] is None:
|
||||||
return
|
return
|
||||||
network_value = f'{network["value"]}/{netmask["value"]}'
|
network_value = f'{network["value"]}/{netmask["value"]}'
|
||||||
network_obj = ip_network(network_value)
|
network_obj = ip_network(network_value)
|
||||||
|
@ -133,63 +112,56 @@ def valid_in_network(
|
||||||
if netmask is None:
|
if netmask is None:
|
||||||
msg = _('this IP is not in network {network["value"]} ({network["name"]})')
|
msg = _('this IP is not in network {network["value"]} ({network["name"]})')
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _('this IP is not in network {network["value"]} ({network["name"]}) '
|
||||||
'this IP is not in network {network["value"]} ({network["name"]}) '
|
'with netmask {netmask["value"]} ({netmask["name"]})')
|
||||||
'with netmask {netmask["value"]} ({netmask["name"]})'
|
|
||||||
)
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
# test if ip is not network/broadcast IP
|
# test if ip is not network/broadcast IP
|
||||||
if ip_netmask.ip == ip_netmask.network.network_address:
|
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||||
msg = _(
|
msg = _(f'this IP with the network {network["value"]} ({network["value"]} '
|
||||||
"this IP with the network {0} ({1}) is in fact a network address"
|
'is in fact a network address')
|
||||||
).format(network["value"], network["name"])
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||||
msg = _(
|
msg = _(f'this IP with the network {network["value"]} ({network["value"]} '
|
||||||
"this IP with the network {0} ({1}) is in fact a broadcast address"
|
'is in fact a broadcast address')
|
||||||
).format(network["value"], network["value"])
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
@function_waiting_for_dict
|
@function_waiting_for_dict
|
||||||
def valid_not_equal(*values):
|
def valid_not_equal(*values):
|
||||||
"""valid that two options have not same value"""
|
"""valid that two options have not same value
|
||||||
|
"""
|
||||||
equal = set()
|
equal = set()
|
||||||
for val in values[1:]:
|
for val in values[1:]:
|
||||||
if "propertyerror" in val:
|
if 'propertyerror' in val:
|
||||||
continue
|
continue
|
||||||
if values[0]["value"] == val["value"] is not None:
|
if values[0]['value'] == val['value'] is not None:
|
||||||
equal.add(val["name"])
|
equal.add(val['name'])
|
||||||
if not equal:
|
if not equal:
|
||||||
return
|
return
|
||||||
msg = _("value is identical to {0}").format(
|
msg = _(f'value is identical to {display_list(list(equal), add_quote=True)}')
|
||||||
display_list(list(equal), add_quote=True)
|
|
||||||
)
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
class CalcValue:
|
class CalcValue:
|
||||||
"""class to calc_value with different functions"""
|
"""class to calc_value with different functions
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
def __call__(
|
def __call__(self,
|
||||||
self,
|
|
||||||
*args: List[Any],
|
*args: List[Any],
|
||||||
multi: bool = False,
|
multi: bool=False,
|
||||||
default: Any = undefined,
|
default: Any=undefined,
|
||||||
condition: Any = undefined,
|
condition: Any=undefined,
|
||||||
no_condition_is_invalid: bool = False,
|
no_condition_is_invalid: bool=False,
|
||||||
expected: Any = undefined,
|
expected: Any=undefined,
|
||||||
condition_operator: str = "AND",
|
condition_operator: str='AND',
|
||||||
reverse_condition: bool = False,
|
reverse_condition: bool=False,
|
||||||
allow_none: bool = False,
|
allow_none: bool=False,
|
||||||
remove_duplicate_value: bool = False,
|
remove_duplicate_value: bool=False,
|
||||||
join: Optional[str] = None,
|
join: Optional[str]=None,
|
||||||
min_args_len: Optional[int] = None,
|
min_args_len: Optional[int]=None,
|
||||||
operator: Optional[str] = None,
|
operator: Optional[str]=None,
|
||||||
index: Optional[int] = None,
|
index: Optional[int]=None,
|
||||||
**kwargs,
|
**kwargs) -> Any:
|
||||||
) -> Any:
|
|
||||||
# pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals
|
# pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals
|
||||||
"""calculate value
|
"""calculate value
|
||||||
:param args: list of value
|
:param args: list of value
|
||||||
|
@ -353,11 +325,8 @@ class CalcValue:
|
||||||
self.condition_operator = condition_operator
|
self.condition_operator = condition_operator
|
||||||
self.reverse_condition = reverse_condition
|
self.reverse_condition = reverse_condition
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.no_condition_is_invalid = (
|
self.no_condition_is_invalid = no_condition_is_invalid # pylint: disable=attribute-defined-outside-init
|
||||||
no_condition_is_invalid # pylint: disable=attribute-defined-outside-init
|
value = self.get_value(default,
|
||||||
)
|
|
||||||
value = self.get_value(
|
|
||||||
default,
|
|
||||||
min_args_len,
|
min_args_len,
|
||||||
)
|
)
|
||||||
if not multi:
|
if not multi:
|
||||||
|
@ -368,11 +337,10 @@ class CalcValue:
|
||||||
value = None
|
value = None
|
||||||
elif value and operator:
|
elif value and operator:
|
||||||
new_value = value[0]
|
new_value = value[0]
|
||||||
oper = {
|
oper = {'mul': mul,
|
||||||
"mul": mul,
|
'add': add,
|
||||||
"add": add,
|
'div': truediv,
|
||||||
"div": truediv,
|
'sub': sub,
|
||||||
"sub": sub,
|
|
||||||
}[operator]
|
}[operator]
|
||||||
for val in value[1:]:
|
for val in value[1:]:
|
||||||
new_value = oper(new_value, val)
|
new_value = oper(new_value, val)
|
||||||
|
@ -397,9 +365,8 @@ class CalcValue:
|
||||||
break
|
break
|
||||||
lval = len(val)
|
lval = len(val)
|
||||||
if length_val is not None and length_val != lval:
|
if length_val is not None and length_val != lval:
|
||||||
msg = _(
|
msg = _('unexpected value in calc_value with join attribute '
|
||||||
'unexpected value in calc_value with join attribute "{0}" with invalid length "{1}"'
|
f'"{val}" with invalid length "{length_val}"')
|
||||||
).format(val, length_val)
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
length_val = lval
|
length_val = lval
|
||||||
new_value = []
|
new_value = []
|
||||||
|
@ -425,16 +392,19 @@ class CalcValue:
|
||||||
value = new_value
|
value = new_value
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def value_from_kwargs(
|
def value_from_kwargs(self,
|
||||||
self, value: Any, pattern: str, to_dict: bool = False, empty_test=undefined
|
value: Any,
|
||||||
) -> Any:
|
pattern: str,
|
||||||
"""get value from kwargs"""
|
to_dict: bool=False,
|
||||||
|
empty_test=undefined) -> Any:
|
||||||
|
"""get value from kwargs
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
# if value attribute exist return it's value
|
# if value attribute exist return it's value
|
||||||
# otherwise pattern_0, pattern_1, ...
|
# otherwise pattern_0, pattern_1, ...
|
||||||
# otherwise undefined
|
# otherwise undefined
|
||||||
if value is not empty_test:
|
if value is not empty_test:
|
||||||
if to_dict == "all":
|
if to_dict == 'all':
|
||||||
returns = {None: value}
|
returns = {None: value}
|
||||||
else:
|
else:
|
||||||
returns = value
|
returns = value
|
||||||
|
@ -445,7 +415,7 @@ class CalcValue:
|
||||||
if key.startswith(pattern):
|
if key.startswith(pattern):
|
||||||
index = int(key[len_pattern:])
|
index = int(key[len_pattern:])
|
||||||
if isinstance(pattern_value, dict):
|
if isinstance(pattern_value, dict):
|
||||||
pattern_value = pattern_value["value"]
|
pattern_value = pattern_value['value']
|
||||||
kwargs_matches[index] = pattern_value
|
kwargs_matches[index] = pattern_value
|
||||||
if not kwargs_matches:
|
if not kwargs_matches:
|
||||||
returns = undefined
|
returns = undefined
|
||||||
|
@ -462,29 +432,26 @@ class CalcValue:
|
||||||
returns.append(kwargs_matches[key])
|
returns.append(kwargs_matches[key])
|
||||||
return returns
|
return returns
|
||||||
|
|
||||||
def is_condition_matches(
|
def is_condition_matches(self,
|
||||||
self,
|
|
||||||
condition_value,
|
condition_value,
|
||||||
):
|
):
|
||||||
"""verify the condition"""
|
"""verify the condition
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
calculated_conditions = self.value_from_kwargs(
|
calculated_conditions = self.value_from_kwargs(condition_value,
|
||||||
condition_value,
|
'condition_',
|
||||||
"condition_",
|
to_dict='all',
|
||||||
to_dict="all",
|
|
||||||
)
|
)
|
||||||
if calculated_conditions is undefined:
|
if calculated_conditions is undefined:
|
||||||
is_matches = not self.no_condition_is_invalid
|
is_matches = not self.no_condition_is_invalid
|
||||||
else:
|
else:
|
||||||
is_matches = None
|
is_matches = None
|
||||||
calculated_expected = self.value_from_kwargs(
|
calculated_expected = self.value_from_kwargs(self.expected,
|
||||||
self.expected,
|
'expected_',
|
||||||
"expected_",
|
|
||||||
to_dict=True,
|
to_dict=True,
|
||||||
)
|
)
|
||||||
calculated_reverse = self.value_from_kwargs(
|
calculated_reverse = self.value_from_kwargs(self.reverse_condition,
|
||||||
self.reverse_condition,
|
'reverse_condition_',
|
||||||
"reverse_condition_",
|
|
||||||
to_dict=True,
|
to_dict=True,
|
||||||
empty_test=False,
|
empty_test=False,
|
||||||
)
|
)
|
||||||
|
@ -492,17 +459,11 @@ class CalcValue:
|
||||||
if isinstance(calculated_expected, dict):
|
if isinstance(calculated_expected, dict):
|
||||||
if idx is not None:
|
if idx is not None:
|
||||||
if isinstance(calculated_expected[idx], list):
|
if isinstance(calculated_expected[idx], list):
|
||||||
current_matches = (
|
current_matches = calculated_condition in calculated_expected[idx]
|
||||||
calculated_condition in calculated_expected[idx]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
current_matches = (
|
current_matches = calculated_condition == calculated_expected[idx]
|
||||||
calculated_condition == calculated_expected[idx]
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
current_matches = (
|
current_matches = calculated_condition in calculated_expected.values()
|
||||||
calculated_condition in calculated_expected.values()
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
current_matches = calculated_condition == calculated_expected
|
current_matches = calculated_condition == calculated_expected
|
||||||
if isinstance(calculated_reverse, dict) and idx in calculated_reverse:
|
if isinstance(calculated_reverse, dict) and idx in calculated_reverse:
|
||||||
|
@ -511,41 +472,36 @@ class CalcValue:
|
||||||
reverse_condition = False
|
reverse_condition = False
|
||||||
if is_matches is None:
|
if is_matches is None:
|
||||||
is_matches = current_matches
|
is_matches = current_matches
|
||||||
if self.condition_operator == "AND":
|
if self.condition_operator == 'AND':
|
||||||
is_matches = is_matches and current_matches
|
is_matches = is_matches and current_matches
|
||||||
if reverse_condition:
|
if reverse_condition:
|
||||||
is_matches = not is_matches
|
is_matches = not is_matches
|
||||||
if not is_matches:
|
if not is_matches:
|
||||||
break
|
break
|
||||||
elif self.condition_operator == "OR":
|
elif self.condition_operator == 'OR':
|
||||||
is_matches = is_matches or current_matches
|
is_matches = is_matches or current_matches
|
||||||
if reverse_condition:
|
if reverse_condition:
|
||||||
is_matches = not is_matches
|
is_matches = not is_matches
|
||||||
if is_matches:
|
if is_matches:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _(f'unexpected {self.condition_operator} condition_operator '
|
||||||
"unexpected {0} condition_operator " "in calc_value"
|
'in calc_value')
|
||||||
).format(self.condition_operator)
|
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
is_matches = (
|
is_matches = is_matches and not self.reverse_condition \
|
||||||
is_matches
|
or not is_matches and self.reverse_condition
|
||||||
and not self.reverse_condition
|
|
||||||
or not is_matches
|
|
||||||
and self.reverse_condition
|
|
||||||
)
|
|
||||||
return is_matches
|
return is_matches
|
||||||
|
|
||||||
def get_value(
|
def get_value(self,
|
||||||
self,
|
|
||||||
default,
|
default,
|
||||||
min_args_len,
|
min_args_len,
|
||||||
):
|
):
|
||||||
"""get the value from arguments"""
|
"""get the value from arguments
|
||||||
|
"""
|
||||||
# retrieve the condition
|
# retrieve the condition
|
||||||
if isinstance(self.condition, dict):
|
if isinstance(self.condition, dict):
|
||||||
if "value" in self.condition:
|
if 'value' in self.condition:
|
||||||
condition_value = self.condition["value"]
|
condition_value = self.condition['value']
|
||||||
else:
|
else:
|
||||||
condition_value = undefined
|
condition_value = undefined
|
||||||
else:
|
else:
|
||||||
|
@ -560,9 +516,8 @@ class CalcValue:
|
||||||
value = []
|
value = []
|
||||||
if not value:
|
if not value:
|
||||||
# default value
|
# default value
|
||||||
new_default = self.value_from_kwargs(
|
new_default = self.value_from_kwargs(default,
|
||||||
default,
|
'default_',
|
||||||
"default_",
|
|
||||||
)
|
)
|
||||||
if new_default is not undefined:
|
if new_default is not undefined:
|
||||||
if not isinstance(new_default, list):
|
if not isinstance(new_default, list):
|
||||||
|
@ -572,32 +527,34 @@ class CalcValue:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def get_args(self):
|
def get_args(self):
|
||||||
"""get all arguments"""
|
"""get all arguments
|
||||||
|
"""
|
||||||
return list(self.args)
|
return list(self.args)
|
||||||
|
|
||||||
|
|
||||||
class CalcValuePropertyHelp(CalcValue):
|
class CalcValuePropertyHelp(CalcValue):
|
||||||
"""special class to display property error"""
|
"""special class to display property error
|
||||||
|
"""
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
"""get the condition name"""
|
"""get the condition name
|
||||||
return self.condition["name"]
|
"""
|
||||||
|
return self.condition['name']
|
||||||
|
|
||||||
def get_indexed_name(self, index: int) -> str:
|
def get_indexed_name(self, index: int) -> str:
|
||||||
"""get name for a specified index"""
|
"""get name for a specified index
|
||||||
condition_index = self.kwargs.get(f"condition_{index}")
|
"""
|
||||||
|
condition_index = self.kwargs.get(f'condition_{index}')
|
||||||
if condition_index is not None and not isinstance(condition_index, dict):
|
if condition_index is not None and not isinstance(condition_index, dict):
|
||||||
raise ValueError(
|
raise ValueError(_(f'unexpected condition_{index} must have "todict" argument'))
|
||||||
_('unexpected condition_{0} must have "todict" argument').format(index)
|
return condition_index['name']
|
||||||
)
|
|
||||||
return condition_index["name"]
|
|
||||||
|
|
||||||
def build_property_message(
|
|
||||||
self,
|
def build_property_message(self,
|
||||||
name: str,
|
name: str,
|
||||||
value: Any,
|
value: Any,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""prepare message to display error message if needed"""
|
"""prepare message to display error message if needed
|
||||||
|
"""
|
||||||
if not self.reverse_condition:
|
if not self.reverse_condition:
|
||||||
msg = _('the value of "{0}" is {1}').format(name, value)
|
msg = _('the value of "{0}" is {1}').format(name, value)
|
||||||
else:
|
else:
|
||||||
|
@ -607,36 +564,34 @@ class CalcValuePropertyHelp(CalcValue):
|
||||||
def get_args(self):
|
def get_args(self):
|
||||||
args = super().get_args()
|
args = super().get_args()
|
||||||
action = args[0]
|
action = args[0]
|
||||||
calculated_expected = self.value_from_kwargs(
|
calculated_expected = self.value_from_kwargs(self.expected,
|
||||||
self.expected, "expected_", to_dict=True
|
'expected_',
|
||||||
)
|
to_dict=True)
|
||||||
if self.condition is not undefined:
|
if self.condition is not undefined:
|
||||||
if "propertyerror" in self.condition:
|
if 'propertyerror' in self.condition:
|
||||||
msg = self.condition["propertyerror"]
|
msg = self.condition['propertyerror']
|
||||||
else:
|
else:
|
||||||
name = self.get_name()
|
name = self.get_name()
|
||||||
if isinstance(calculated_expected, dict):
|
if isinstance(calculated_expected, dict):
|
||||||
calc_values = calculated_expected.values()
|
calc_values = calculated_expected.values()
|
||||||
else:
|
else:
|
||||||
calc_values = [calculated_expected]
|
calc_values = [calculated_expected]
|
||||||
display_value = display_list(
|
display_value = display_list([str(val) for val in calc_values],
|
||||||
[str(val) for val in calc_values], separator="or", add_quote=True
|
'or',
|
||||||
)
|
add_quote=True)
|
||||||
msg = self.build_property_message(name, display_value)
|
msg = self.build_property_message(name, display_value)
|
||||||
else:
|
else:
|
||||||
msgs = []
|
msgs = []
|
||||||
for key, value in calculated_expected.items():
|
for key, value in calculated_expected.items():
|
||||||
name = self.get_indexed_name(key)
|
name = self.get_indexed_name(key)
|
||||||
msgs.append(self.build_property_message(name, f'"{value}"'))
|
msgs.append(self.build_property_message(name, f'"{value}"'))
|
||||||
msg = display_list(msgs, separator=self.condition_operator.lower())
|
msg = display_list(msgs, self.condition_operator.lower())
|
||||||
return [(action, f'"{action}" ({msg})')]
|
return [(action, f'"{action}" ({msg})')]
|
||||||
|
|
||||||
|
|
||||||
calc_value = CalcValue()
|
calc_value = CalcValue()
|
||||||
calc_value.__name__ = "calc_value" # pylint: disable=attribute-defined-outside-init
|
calc_value.__name__ = 'calc_value' # pylint: disable=attribute-defined-outside-init
|
||||||
# function_waiting_for_dict(calc_value)
|
# function_waiting_for_dict(calc_value)
|
||||||
calc_value_property_help = CalcValuePropertyHelp()
|
calc_value_property_help = CalcValuePropertyHelp()
|
||||||
calc_value_property_help.__name__ = (
|
calc_value_property_help.__name__ = 'calc_value_property_help' # pylint: disable=attribute-defined-outside-init
|
||||||
"calc_value_property_help" # pylint: disable=attribute-defined-outside-init
|
|
||||||
)
|
|
||||||
function_waiting_for_dict(calc_value_property_help)
|
function_waiting_for_dict(calc_value_property_help)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -18,9 +18,55 @@
|
||||||
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
|
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
"internationalisation utilities"
|
"internationalisation utilities"
|
||||||
from gettext import translation
|
from .log import log
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
t = translation("tiramisu", str(Path(__file__).parent / "locale"), fallback=True)
|
from gettext import translation, NullTranslations
|
||||||
|
from platform import system
|
||||||
|
from pkg_resources import resource_filename
|
||||||
|
from os import environ
|
||||||
|
|
||||||
_ = t.gettext
|
|
||||||
|
DEFAULT = 'en'
|
||||||
|
|
||||||
|
|
||||||
|
def get_translation() -> str:
|
||||||
|
"""Sets the user locale as langage
|
||||||
|
The default is set to english
|
||||||
|
"""
|
||||||
|
# Application name (without .i18n)
|
||||||
|
app_name = __name__[:-5]
|
||||||
|
translations_path = resource_filename(app_name, 'locale')
|
||||||
|
|
||||||
|
if 'TIRAMISU_LOCALE' in environ: # pragma: no cover
|
||||||
|
user_locale = environ['TIRAMISU_LOCALE']
|
||||||
|
else:
|
||||||
|
if 'Windows' in system(): # pragma: no cover
|
||||||
|
import ctypes
|
||||||
|
from locale import windows_locale
|
||||||
|
default_locale = windows_locale[ctypes.windll.kernel32.GetUserDefaultUILanguage()]
|
||||||
|
else:
|
||||||
|
from locale import getlocale
|
||||||
|
default_locale = getlocale()
|
||||||
|
if default_locale and isinstance(default_locale, tuple):
|
||||||
|
if default_locale[0] is not None:
|
||||||
|
user_locale = default_locale[0][:2]
|
||||||
|
else:
|
||||||
|
user_locale = DEFAULT
|
||||||
|
elif default_locale: # pragma: no cover
|
||||||
|
user_locale = default_locale[:2]
|
||||||
|
else: # pragma: no cover
|
||||||
|
user_locale = DEFAULT
|
||||||
|
try:
|
||||||
|
trans = translation(domain=app_name,
|
||||||
|
localedir=translations_path,
|
||||||
|
languages=[user_locale],
|
||||||
|
)
|
||||||
|
# codeset='UTF-8')
|
||||||
|
except FileNotFoundError: # pragma: no cover
|
||||||
|
log.debug('cannot found translation file for langage {} in localedir {}'.format(user_locale,
|
||||||
|
translations_path))
|
||||||
|
trans = NullTranslations()
|
||||||
|
return trans.gettext
|
||||||
|
|
||||||
|
|
||||||
|
_ = get_translation()
|
||||||
|
|
Binary file not shown.
1192
tiramisu/locale/fr/LC_MESSAGES/tiramisu.po
Normal file
1192
tiramisu/locale/fr/LC_MESSAGES/tiramisu.po
Normal file
File diff suppressed because it is too large
Load diff
711
tiramisu/locale/tiramisu.pot
Normal file
711
tiramisu/locale/tiramisu.pot
Normal file
|
@ -0,0 +1,711 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR ORGANIZATION
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"POT-Creation-Date: 2023-11-19 21:26+0100\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"Generated-By: pygettext.py 1.5\n"
|
||||||
|
|
||||||
|
|
||||||
|
#: tiramisu/api.py:61
|
||||||
|
msgid "Settings:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:63
|
||||||
|
msgid "Access to option without verifying permissive properties"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:67
|
||||||
|
msgid "Access to option without property restriction"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:70
|
||||||
|
msgid "Do not warnings during validation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:75
|
||||||
|
msgid "Call: {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:77
|
||||||
|
msgid "Commands:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:185
|
||||||
|
msgid "unknown list type {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:187
|
||||||
|
msgid "unknown group_type: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:352
|
||||||
|
msgid "only multi value has defaultmulti"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:371 tiramisu/option/intoption.py:31
|
||||||
|
msgid "integer"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:374 tiramisu/option/domainnameoption.py:43
|
||||||
|
msgid "domain name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:376
|
||||||
|
msgid "ip"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:376
|
||||||
|
msgid "netmask"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:376
|
||||||
|
msgid "network"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:471
|
||||||
|
msgid "cannot add this property: \"{0}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:621
|
||||||
|
msgid "cannot reduce length of the leader \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:1088
|
||||||
|
msgid "properties must be a frozenset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:1094 tiramisu/api.py:1118
|
||||||
|
msgid "unknown when {} (must be in append or remove)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:1106 tiramisu/api.py:1127 tiramisu/config.py:1210
|
||||||
|
msgid "unknown type {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/api.py:1432
|
||||||
|
msgid "do not use unrestraint, nowarnings or forcepermissive together"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:44
|
||||||
|
msgid "args in params must be a tuple"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:47 tiramisu/autolib.py:52
|
||||||
|
msgid "arg in params must be a Param"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:49
|
||||||
|
msgid "kwargs in params must be a dict"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:72
|
||||||
|
msgid "paramoption needs an option not {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:77
|
||||||
|
msgid "param must have a boolean not a {} for notraisepropertyerror"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:78
|
||||||
|
msgid "param must have a boolean not a {} for raisepropertyerror"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:133
|
||||||
|
msgid "option in ParamInformation cannot be a symlinkoption"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:135
|
||||||
|
msgid "option in ParamInformation cannot be a follower"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:137
|
||||||
|
msgid "option in ParamInformation cannot be a dynamic option"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:166
|
||||||
|
msgid "first argument ({0}) must be a function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:168
|
||||||
|
msgid "help_function ({0}) must be a function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:316 tiramisu/autolib.py:362
|
||||||
|
msgid "unable to carry out a calculation for \"{}\", {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:319 tiramisu/autolib.py:365
|
||||||
|
msgid "the option \"{0}\" is used in a calculation but is invalid ({1})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:402
|
||||||
|
msgid "option \"{}\" cannot be calculated: {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:411
|
||||||
|
msgid "option \"{}\" is not in a dynoptiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:562
|
||||||
|
msgid "the \"{}\" function with positional arguments \"{}\" and keyword arguments \"{}\" must not return a list (\"{}\") for the follower option \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:571
|
||||||
|
msgid "the \"{}\" function must not return a list (\"{}\") for the follower option \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:604
|
||||||
|
msgid "unexpected error \"{0}\" in function \"{1}\" with arguments \"{3}\" and \"{4}\" for option \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/autolib.py:611
|
||||||
|
msgid "unexpected error \"{0}\" in function \"{1}\" for option \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:82
|
||||||
|
msgid "there is no option description for this config (may be GroupConfig)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:269
|
||||||
|
msgid "no option found in config with these criteria"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:532 tiramisu/option/optiondescription.py:72
|
||||||
|
msgid "option description seems to be part of an other config"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:790
|
||||||
|
msgid "cannot set leadership object has root optiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:792
|
||||||
|
msgid "cannot set dynoptiondescription object has root optiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:840
|
||||||
|
msgid "config name must be uniq in groupconfig for \"{0}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1024
|
||||||
|
msgid "unknown config \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1047
|
||||||
|
msgid "child must be a Config, MixConfig or MetaConfig"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1079
|
||||||
|
msgid "force_default, force_default_if_same or force_dont_change_value cannot be set with only_config"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1085
|
||||||
|
msgid "force_default and force_dont_change_value cannot be set together"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1208
|
||||||
|
msgid "config name must be uniq in groupconfig for {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1246
|
||||||
|
msgid "config added has no name, the name is mandatory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1248
|
||||||
|
msgid "config name \"{0}\" is not uniq in groupconfig \"{1}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1270
|
||||||
|
msgid "cannot find the config {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1294
|
||||||
|
msgid "MetaConfig with optiondescription must have string has child, not {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1303
|
||||||
|
msgid "child must be a Config or MetaConfig"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1307
|
||||||
|
msgid "all config in metaconfig must have the same optiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/config.py:1319
|
||||||
|
msgid "metaconfig must have the same optiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:26
|
||||||
|
msgid "and"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:28
|
||||||
|
msgid "or"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:50
|
||||||
|
msgid " {} "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:98
|
||||||
|
msgid "property"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:100
|
||||||
|
msgid "properties"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:187
|
||||||
|
msgid "invalid value"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:192
|
||||||
|
msgid "attention, \"{0}\" could be an invalid {1} for \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/error.py:208 tiramisu/error.py:212
|
||||||
|
msgid "\"{0}\" is an invalid {1} for \"{2}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/function.py:113
|
||||||
|
msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/function.py:115
|
||||||
|
msgid "this IP is not in network {network[\"value\"]} ({network[\"name\"]}) with netmask {netmask[\"value\"]} ({netmask[\"name\"]})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/function.py:559
|
||||||
|
msgid "the value of \"{0}\" is {1}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/function.py:561
|
||||||
|
msgid "the value of \"{0}\" is not {1}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/baseoption.py:70 tiramisu/option/symlinkoption.py:40
|
||||||
|
msgid "\"{0}\" is an invalid name for an option"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/baseoption.py:83
|
||||||
|
msgid "invalid properties type {0} for {1}, must be a frozenset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/baseoption.py:89
|
||||||
|
msgid "invalid property type {0} for {1}, must be a string or a Calculation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/baseoption.py:227
|
||||||
|
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/baseoption.py:265
|
||||||
|
msgid "\"{}\" ({}) object attribute \"{}\" is read-only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/booloption.py:32
|
||||||
|
msgid "boolean"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/broadcastoption.py:33
|
||||||
|
msgid "broadcast address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/broadcastoption.py:41
|
||||||
|
msgid "invalid string"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/choiceoption.py:38
|
||||||
|
msgid "choice"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/choiceoption.py:51
|
||||||
|
msgid "values must be a tuple or a calculation for {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/choiceoption.py:67
|
||||||
|
msgid "the calculated values \"{0}\" for \"{1}\" is not a list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/choiceoption.py:97
|
||||||
|
msgid "only \"{0}\" is allowed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/choiceoption.py:99
|
||||||
|
msgid "only {0} are allowed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/dateoption.py:33
|
||||||
|
msgid "date"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:62
|
||||||
|
msgid "unknown type {0} for hostname"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:65
|
||||||
|
msgid "allow_ip must be a boolean"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:67
|
||||||
|
msgid "allow_cidr_network must be a boolean"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:69
|
||||||
|
msgid "allow_without_dot must be a boolean"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:71
|
||||||
|
msgid "allow_startswith_dot must be a boolean"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:81
|
||||||
|
msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are allowed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:82
|
||||||
|
msgid "must start with lowercase characters followed by lowercase characters, number, \"-\" and \".\" characters are recommanded"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:84
|
||||||
|
#: tiramisu/option/domainnameoption.py:85
|
||||||
|
msgid "could be a IP, otherwise {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:125
|
||||||
|
msgid "invalid length (min 1)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:127
|
||||||
|
msgid "invalid length (max {0})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:133
|
||||||
|
msgid "must have dot"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:135
|
||||||
|
msgid "invalid length (max 255)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:154
|
||||||
|
msgid "must not be an IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/domainnameoption.py:180
|
||||||
|
msgid "some characters are uppercase"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/dynoptiondescription.py:65
|
||||||
|
msgid "suffixes in dynoptiondescription has to be a calculation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/dynoptiondescription.py:109
|
||||||
|
msgid "invalid suffix \"{}\" for option \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/emailoption.py:34
|
||||||
|
msgid "email address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/filenameoption.py:31
|
||||||
|
msgid "file name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/filenameoption.py:38
|
||||||
|
msgid "must starts with \"/\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/floatoption.py:32
|
||||||
|
msgid "float"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:33
|
||||||
|
msgid "IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:57
|
||||||
|
msgid "it's in fact a network address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:59
|
||||||
|
msgid "it's in fact a broacast address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:72
|
||||||
|
msgid "CIDR address must have a \"/\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:83
|
||||||
|
msgid "shouldn't be reserved IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:85
|
||||||
|
msgid "mustn't be reserved IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:89
|
||||||
|
msgid "should be private IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/ipoption.py:91
|
||||||
|
msgid "must be private IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/leadership.py:56
|
||||||
|
msgid "a leader and a follower are mandatories in leadership \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/leadership.py:73
|
||||||
|
msgid "leader cannot have \"{}\" property"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/leadership.py:77
|
||||||
|
msgid "leadership \"{0}\" shall not have a symlinkoption"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/leadership.py:80
|
||||||
|
msgid "leadership \"{0}\" shall not have a subgroup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/leadership.py:83
|
||||||
|
msgid "only multi option allowed in leadership \"{0}\" but option \"{1}\" is not a multi"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/macoption.py:34
|
||||||
|
msgid "mac address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/netmaskoption.py:32
|
||||||
|
msgid "netmask address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/networkoption.py:32
|
||||||
|
msgid "network address"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/networkoption.py:51
|
||||||
|
msgid "must use CIDR notation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/networkoption.py:68
|
||||||
|
msgid "shouldn't be reserved network"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/networkoption.py:70
|
||||||
|
msgid "mustn't be reserved network"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:69
|
||||||
|
msgid "default_multi is set whereas multi is False in option: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:86
|
||||||
|
msgid "invalid multi type \"{}\" for \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:102
|
||||||
|
msgid "validators must be a Calculation for \"{}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:127
|
||||||
|
msgid "invalid default_multi value \"{0}\" for option \"{1}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:137
|
||||||
|
msgid "invalid default_multi value \"{0}\" for option \"{1}\", must be a list for a submulti"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:291
|
||||||
|
msgid "the value \"{}\" is not unique"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:331
|
||||||
|
msgid "which must not be a list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:373 tiramisu/option/option.py:399
|
||||||
|
msgid "which must be a list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/option.py:392
|
||||||
|
msgid "which \"{}\" must be a list of list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/optiondescription.py:109
|
||||||
|
msgid "duplicate option: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/optiondescription.py:306
|
||||||
|
msgid "children in optiondescription \"{}\" must be a list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/optiondescription.py:329
|
||||||
|
msgid "duplicate option name: \"{0}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/optiondescription.py:374
|
||||||
|
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/optiondescription.py:378
|
||||||
|
msgid "group_type: {0} not allowed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/passwordoption.py:32
|
||||||
|
msgid "password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:38
|
||||||
|
msgid "unix file permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:52
|
||||||
|
msgid "only 3 or 4 octal digits are allowed"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:65
|
||||||
|
msgid "user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:66
|
||||||
|
#: tiramisu/option/permissionsoption.py:68
|
||||||
|
msgid "group"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:69
|
||||||
|
msgid "other"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/permissionsoption.py:73
|
||||||
|
msgid "too weak"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/portoption.py:41
|
||||||
|
msgid "port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/portoption.py:71
|
||||||
|
msgid "inconsistency in allowed range"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/portoption.py:76
|
||||||
|
msgid "max value is empty"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/portoption.py:91
|
||||||
|
msgid "range must have two values only"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/portoption.py:93
|
||||||
|
msgid "first port in range must be smaller than the second one"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/stroption.py:33
|
||||||
|
msgid "string"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/symlinkoption.py:44
|
||||||
|
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/symlinkoption.py:60
|
||||||
|
msgid "cannot set symlinkoption in a dynoptiondescription"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/urloption.py:39
|
||||||
|
msgid "URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/urloption.py:91
|
||||||
|
msgid "must start with http:// or https://"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/urloption.py:122
|
||||||
|
msgid "must ends with a valid resource name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/usernameoption.py:35
|
||||||
|
msgid "unix username"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/option/usernameoption.py:42
|
||||||
|
msgid "unix groupname"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:302
|
||||||
|
msgid "can't rebind {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:308
|
||||||
|
msgid "can't unbind {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:515
|
||||||
|
msgid "invalid property type {type(new_prop)} for {option_bag.option.impl_getname()} with {prop.function.__name__} function"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:521
|
||||||
|
msgid "leader cannot have \"{new_prop}\" property"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:591
|
||||||
|
msgid "leader cannot have \"{list(not_allowed_properties)}\" property"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:595
|
||||||
|
msgid "a leader ({opt.impl_get_display_name()}) cannot have \"force_default_on_freeze\" or \"force_metaconfig_on_freeze\" property without \"frozen\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:626
|
||||||
|
msgid "permissive must be a frozenset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/setting.py:635
|
||||||
|
msgid "cannot add those permissives: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:352
|
||||||
|
msgid "option {} only works when remotable is not \"none\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:505
|
||||||
|
msgid "unable to transform tiramisu object to dict: {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:816 tiramisu/todict.py:955
|
||||||
|
msgid "unknown form {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:862
|
||||||
|
msgid "not in current area"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:883
|
||||||
|
msgid "only multi option can have action \"add\", but \"{}\" is not a multi"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/todict.py:885
|
||||||
|
msgid "unknown action {}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/value.py:506 tiramisu/value.py:722
|
||||||
|
msgid "set owner \"{0}\" is forbidden"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/value.py:636
|
||||||
|
msgid "index {index} is greater than the length {length} for option \"{option_bag.option.impl_get_display_name()}\""
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: tiramisu/value.py:695
|
||||||
|
msgid "information's item not found: {0}"
|
||||||
|
msgstr ""
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"logger for tiramisu"
|
"logger for tiramisu"
|
||||||
# Copyright (C) 2019-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2019-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -19,12 +19,12 @@ from logging import getLogger, DEBUG, StreamHandler, Formatter
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
log = getLogger("tiramisu")
|
log = getLogger('tiramisu')
|
||||||
if os.environ.get("TIRAMISU_DEBUG") == "True": # pragma: no cover
|
if os.environ.get('TIRAMISU_DEBUG') == 'True': # pragma: no cover
|
||||||
log.setLevel(DEBUG)
|
log.setLevel(DEBUG)
|
||||||
handler = StreamHandler()
|
handler = StreamHandler()
|
||||||
handler.setLevel(DEBUG)
|
handler.setLevel(DEBUG)
|
||||||
formatter = Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
handler.setFormatter(formatter)
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
log.addHandler(handler)
|
log.addHandler(handler)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -25,8 +25,7 @@ from .dynoptiondescription import DynOptionDescription
|
||||||
from .leadership import Leadership
|
from .leadership import Leadership
|
||||||
from .baseoption import submulti
|
from .baseoption import submulti
|
||||||
from .symlinkoption import SymLinkOption
|
from .symlinkoption import SymLinkOption
|
||||||
|
#from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership
|
||||||
# from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership
|
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from .choiceoption import ChoiceOption
|
from .choiceoption import ChoiceOption
|
||||||
from .booloption import BoolOption
|
from .booloption import BoolOption
|
||||||
|
@ -49,33 +48,12 @@ from .macoption import MACOption
|
||||||
from .permissionsoption import PermissionsOption
|
from .permissionsoption import PermissionsOption
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = ('Leadership', 'OptionDescription', 'DynOptionDescription',
|
||||||
"Leadership",
|
# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption',
|
||||||
"OptionDescription",
|
'Option', 'SymLinkOption',
|
||||||
"DynOptionDescription",
|
'ChoiceOption', 'BoolOption', 'DateOption',
|
||||||
# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption',
|
'IntOption', 'FloatOption', 'StrOption',
|
||||||
"Option",
|
'IPOption', 'PortOption', 'NetworkOption', 'NetmaskOption',
|
||||||
"SymLinkOption",
|
'BroadcastOption', 'DomainnameOption', 'EmailOption', 'URLOption',
|
||||||
"ChoiceOption",
|
'UsernameOption', 'GroupnameOption', 'FilenameOption', 'PasswordOption', 'submulti',
|
||||||
"BoolOption",
|
'RegexpOption', 'MACOption', 'PermissionsOption')
|
||||||
"DateOption",
|
|
||||||
"IntOption",
|
|
||||||
"FloatOption",
|
|
||||||
"StrOption",
|
|
||||||
"IPOption",
|
|
||||||
"PortOption",
|
|
||||||
"NetworkOption",
|
|
||||||
"NetmaskOption",
|
|
||||||
"BroadcastOption",
|
|
||||||
"DomainnameOption",
|
|
||||||
"EmailOption",
|
|
||||||
"URLOption",
|
|
||||||
"UsernameOption",
|
|
||||||
"GroupnameOption",
|
|
||||||
"FilenameOption",
|
|
||||||
"PasswordOption",
|
|
||||||
"submulti",
|
|
||||||
"RegexpOption",
|
|
||||||
"MACOption",
|
|
||||||
"PermissionsOption",
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -20,14 +20,14 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"""base option
|
"""base option
|
||||||
"""
|
"""
|
||||||
from typing import FrozenSet, Set, Any, List, Optional, Dict
|
from typing import FrozenSet, Set, Any, List
|
||||||
import weakref
|
import weakref
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
|
from ..autolib import Calculation, ParamOption
|
||||||
|
|
||||||
STATIC_TUPLE = frozenset()
|
STATIC_TUPLE = frozenset()
|
||||||
|
|
||||||
|
@ -36,41 +36,36 @@ submulti = 2
|
||||||
|
|
||||||
|
|
||||||
def valid_name(name):
|
def valid_name(name):
|
||||||
"""valid option name"""
|
"""valid option name
|
||||||
|
"""
|
||||||
if not isinstance(name, str):
|
if not isinstance(name, str):
|
||||||
return False
|
return False
|
||||||
if "." in name:
|
if '.' in name:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
#____________________________________________________________
|
||||||
#
|
#
|
||||||
class Base:
|
class Base:
|
||||||
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)"""
|
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
||||||
|
"""
|
||||||
__slots__ = (
|
__slots__ = ('_name',
|
||||||
"_name",
|
'_path',
|
||||||
"_path",
|
'_informations',
|
||||||
"_informations",
|
'_subdyns',
|
||||||
"_subdyns",
|
'_properties',
|
||||||
"_properties",
|
'_has_dependency',
|
||||||
"_has_dependency",
|
'_dependencies',
|
||||||
"_dependencies",
|
'_suffixes_dependencies',
|
||||||
"_dependencies_information",
|
'__weakref__'
|
||||||
"_identifiers_dependencies",
|
|
||||||
"__weakref__",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
informations: Optional[Dict],
|
|
||||||
*,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
is_multi: bool = False,
|
is_multi: bool=False) -> None:
|
||||||
) -> None:
|
|
||||||
if not valid_name(name):
|
if not valid_name(name):
|
||||||
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||||
if properties is None:
|
if properties is None:
|
||||||
|
@ -81,99 +76,77 @@ class Base:
|
||||||
# if option is a multi, it cannot be 'empty' (None not allowed in the list)
|
# if option is a multi, it cannot be 'empty' (None not allowed in the list)
|
||||||
# and cannot have multiple time the same value
|
# and cannot have multiple time the same value
|
||||||
# 'empty' and 'unique' are removed for follower's option
|
# 'empty' and 'unique' are removed for follower's option
|
||||||
if "notunique" not in properties:
|
if 'notunique' not in properties:
|
||||||
properties = properties | {"unique"}
|
properties = properties | {'unique'}
|
||||||
if "notempty" not in properties:
|
if 'notempty' not in properties:
|
||||||
properties = properties | {"empty"}
|
properties = properties | {'empty'}
|
||||||
assert isinstance(properties, frozenset), _(
|
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
|
||||||
"invalid properties type {0} for {1}," " must be a frozenset"
|
' must be a frozenset').format(type(properties),
|
||||||
).format(type(properties), name)
|
name)
|
||||||
_setattr = object.__setattr__
|
|
||||||
_setattr(self, "_name", name)
|
|
||||||
_setattr(self, "_informations", {"doc": doc})
|
|
||||||
for prop in properties:
|
for prop in properties:
|
||||||
if not isinstance(prop, str):
|
if not isinstance(prop, str):
|
||||||
if not isinstance(prop, Calculation):
|
if not isinstance(prop, Calculation):
|
||||||
raise ValueError(
|
raise ValueError(_('invalid property type {0} for {1}, must be a string or a '
|
||||||
_(
|
'Calculation').format(type(prop), name))
|
||||||
"invalid property type {0} for {1}, must be a string or a "
|
|
||||||
"Calculation"
|
|
||||||
).format(type(prop), name)
|
|
||||||
)
|
|
||||||
for param in chain(prop.params.args, prop.params.kwargs.values()):
|
for param in chain(prop.params.args, prop.params.kwargs.values()):
|
||||||
if isinstance(param, ParamOption):
|
if isinstance(param, ParamOption):
|
||||||
param.option._add_dependency(self)
|
param.option._add_dependency(self)
|
||||||
|
_setattr = object.__setattr__
|
||||||
|
_setattr(self, '_name', name)
|
||||||
|
_setattr(self, '_informations', {'doc': doc})
|
||||||
if properties:
|
if properties:
|
||||||
_setattr(self, "_properties", properties)
|
_setattr(self, '_properties', properties)
|
||||||
self.set_informations(informations)
|
|
||||||
|
|
||||||
def set_informations(
|
def impl_has_dependency(self,
|
||||||
self,
|
self_is_dep: bool=True,
|
||||||
informations: Optional[Dict],
|
|
||||||
) -> None:
|
|
||||||
if not informations:
|
|
||||||
return
|
|
||||||
for key, value in informations.items():
|
|
||||||
self._set_information(
|
|
||||||
key,
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
|
|
||||||
def impl_has_dependency(
|
|
||||||
self,
|
|
||||||
self_is_dep: bool = True,
|
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""this has dependency"""
|
"""this has dependency
|
||||||
|
"""
|
||||||
if self_is_dep is True:
|
if self_is_dep is True:
|
||||||
return getattr(self, "_has_dependency", False)
|
return getattr(self, '_has_dependency', False)
|
||||||
return hasattr(self, "_dependencies")
|
return hasattr(self, '_dependencies')
|
||||||
|
|
||||||
def get_dependencies(
|
def get_dependencies(self,
|
||||||
self,
|
|
||||||
context_od,
|
context_od,
|
||||||
) -> Set[str]:
|
) -> Set[str]:
|
||||||
ret = set(getattr(self, "_dependencies", STATIC_TUPLE))
|
ret = set(getattr(self, '_dependencies', STATIC_TUPLE))
|
||||||
if context_od and hasattr(context_od, "_dependencies"):
|
if context_od and hasattr(context_od, '_dependencies'):
|
||||||
# add options that have context is set in calculation
|
# add options that have context is set in calculation
|
||||||
return (
|
return set(context_od._dependencies) | ret # pylint: disable=protected-access
|
||||||
set(context_od._dependencies) | ret
|
|
||||||
) # pylint: disable=protected-access
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _get_identifiers_dependencies(self) -> Set[str]:
|
def _get_suffixes_dependencies(self) -> Set[str]:
|
||||||
return getattr(self, "_identifiers_dependencies", STATIC_TUPLE)
|
return getattr(self, '_suffixes_dependencies', STATIC_TUPLE)
|
||||||
|
|
||||||
def _add_dependency(
|
def _add_dependency(self,
|
||||||
self,
|
|
||||||
option,
|
option,
|
||||||
is_identifier: bool = False,
|
is_suffix: bool=False,
|
||||||
) -> None:
|
) -> None:
|
||||||
woption = weakref.ref(option)
|
woption = weakref.ref(option)
|
||||||
options = self.get_dependencies(None)
|
options = self.get_dependencies(None)
|
||||||
options.add(woption)
|
options.add(woption)
|
||||||
self._dependencies = tuple(
|
self._dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init
|
||||||
options
|
if is_suffix:
|
||||||
) # pylint: disable=attribute-defined-outside-init
|
options = list(self._get_suffixes_dependencies())
|
||||||
if is_identifier:
|
|
||||||
options = list(self._get_identifiers_dependencies())
|
|
||||||
options.append(woption)
|
options.append(woption)
|
||||||
self._identifiers_dependencies = tuple(
|
self._suffixes_dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init
|
||||||
options
|
|
||||||
) # pylint: disable=attribute-defined-outside-init
|
|
||||||
|
|
||||||
def impl_is_optiondescription(self) -> bool:
|
def impl_is_optiondescription(self) -> bool:
|
||||||
"""option is an option description"""
|
"""option is an option description
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_is_dynoptiondescription(self) -> bool:
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
"""option is not a dyn option description"""
|
"""option is not a dyn option description
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_is_sub_dyn_optiondescription(self):
|
def impl_is_sub_dyn_optiondescription(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_getname(self) -> str:
|
def impl_getname(self) -> str:
|
||||||
"""get name"""
|
"""get name
|
||||||
|
"""
|
||||||
return self._name # pylint: disable=no-member
|
return self._name # pylint: disable=no-member
|
||||||
|
|
||||||
def _set_readonly(self) -> None:
|
def _set_readonly(self) -> None:
|
||||||
|
@ -182,39 +155,40 @@ class Base:
|
||||||
dico = self._informations # pylint: disable=no-member
|
dico = self._informations # pylint: disable=no-member
|
||||||
keys = tuple(dico.keys())
|
keys = tuple(dico.keys())
|
||||||
if len(keys) == 1:
|
if len(keys) == 1:
|
||||||
dico = dico["doc"]
|
dico = dico['doc']
|
||||||
else:
|
else:
|
||||||
dico = tuple([keys, tuple(dico.values())])
|
dico = tuple([keys, tuple(dico.values())])
|
||||||
_setattr(self, "_informations", dico)
|
_setattr(self, '_informations', dico)
|
||||||
extra = getattr(self, "_extra", None)
|
extra = getattr(self, '_extra', None)
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
_setattr(
|
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
|
||||||
self, "_extra", tuple([tuple(extra.keys()), tuple(extra.values())])
|
|
||||||
)
|
|
||||||
|
|
||||||
def impl_is_readonly(self) -> str:
|
def impl_is_readonly(self) -> str:
|
||||||
"""the option is readonly"""
|
"""the option is readonly
|
||||||
return hasattr(self, "_path")
|
"""
|
||||||
|
return hasattr(self, '_path')
|
||||||
|
|
||||||
def impl_getproperties(self) -> FrozenSet[str]:
|
def impl_getproperties(self) -> FrozenSet[str]:
|
||||||
"""get properties"""
|
"""get properties
|
||||||
return getattr(self, "_properties", frozenset())
|
"""
|
||||||
|
return getattr(self, '_properties', frozenset())
|
||||||
|
|
||||||
def _setsubdyn(
|
def _setsubdyn(self,
|
||||||
self,
|
|
||||||
subdyn,
|
subdyn,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=attribute-defined-outside-init
|
# pylint: disable=attribute-defined-outside-init
|
||||||
if getattr(self, "_subdyns", None) is None:
|
if getattr(self, '_subdyns', None) is None:
|
||||||
self._subdyns = []
|
self._subdyns = []
|
||||||
self._subdyns.append(subdyn)
|
self._subdyns.append(subdyn)
|
||||||
|
|
||||||
def issubdyn(self) -> bool:
|
def issubdyn(self) -> bool:
|
||||||
"""is sub dynoption"""
|
"""is sub dynoption
|
||||||
return getattr(self, "_subdyns", None) is not None
|
"""
|
||||||
|
return getattr(self, '_subdyns', None) is not None
|
||||||
|
|
||||||
def getsubdyn(self):
|
def getsubdyn(self):
|
||||||
"""get sub dynoption"""
|
"""get sub dynoption
|
||||||
|
"""
|
||||||
return self._subdyns[0]()
|
return self._subdyns[0]()
|
||||||
|
|
||||||
def get_sub_dyns(self):
|
def get_sub_dyns(self):
|
||||||
|
@ -222,11 +196,9 @@ class Base:
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# information
|
# information
|
||||||
def _get_information(
|
def impl_get_information(self,
|
||||||
self,
|
|
||||||
subconfig: "SubConfig",
|
|
||||||
key: str,
|
key: str,
|
||||||
default: Any = undefined,
|
default: Any=undefined,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""retrieves one information's item
|
"""retrieves one information's item
|
||||||
|
|
||||||
|
@ -237,7 +209,7 @@ class Base:
|
||||||
if key in dico[0]:
|
if key in dico[0]:
|
||||||
return dico[1][dico[0].index(key)]
|
return dico[1][dico[0].index(key)]
|
||||||
elif isinstance(dico, str):
|
elif isinstance(dico, str):
|
||||||
if key == "doc":
|
if key == 'doc':
|
||||||
return dico
|
return dico
|
||||||
elif isinstance(dico, dict):
|
elif isinstance(dico, dict):
|
||||||
if key in dico:
|
if key in dico:
|
||||||
|
@ -245,14 +217,10 @@ class Base:
|
||||||
if default is not undefined:
|
if default is not undefined:
|
||||||
return default
|
return default
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
raise ValueError(
|
raise ValueError(_(f'information\'s item for "{self.impl_get_display_name()}" '
|
||||||
_('information\'s item for {0} not found: "{1}"').format(
|
f'not found: "{key}"'))
|
||||||
self.impl_get_display_name(subconfig, with_quote=True), key
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _set_information(
|
def impl_set_information(self,
|
||||||
self,
|
|
||||||
key: str,
|
key: str,
|
||||||
value: Any,
|
value: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -263,20 +231,20 @@ class Base:
|
||||||
:param value: information's value (ex: "the help string")
|
:param value: information's value (ex: "the help string")
|
||||||
"""
|
"""
|
||||||
if self.impl_is_readonly():
|
if self.impl_is_readonly():
|
||||||
raise AttributeError(
|
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||||
_("'{0}' ({1}) object attribute '{2}' is" " read-only").format(
|
" read-only").format(self.__class__.__name__,
|
||||||
self.__class__.__name__, self, key
|
self,
|
||||||
)
|
key))
|
||||||
)
|
|
||||||
self._informations[key] = value # pylint: disable=no-member
|
self._informations[key] = value # pylint: disable=no-member
|
||||||
|
|
||||||
def _list_information(self) -> Any:
|
def impl_list_information(self) -> Any:
|
||||||
"""get the list of information keys"""
|
"""get the list of information keys
|
||||||
|
"""
|
||||||
dico = self._informations # pylint: disable=no-member
|
dico = self._informations # pylint: disable=no-member
|
||||||
if isinstance(dico, tuple):
|
if isinstance(dico, tuple):
|
||||||
return list(dico[0])
|
return list(dico[0])
|
||||||
if not isinstance(dico, dict):
|
if isinstance(dico, str):
|
||||||
return ["doc"]
|
return ['doc']
|
||||||
# it's a dict
|
# it's a dict
|
||||||
return list(dico.keys())
|
return list(dico.keys())
|
||||||
|
|
||||||
|
@ -286,11 +254,9 @@ class BaseOption(Base):
|
||||||
in options that have to be set only once, it is of course done in the
|
in options that have to be set only once, it is of course done in the
|
||||||
__setattr__ method
|
__setattr__ method
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ('_display_name_function',)
|
||||||
|
|
||||||
__slots__ = ("_display_name_function",)
|
def __setattr__(self,
|
||||||
|
|
||||||
def __setattr__(
|
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
value: Any,
|
value: Any,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
|
@ -304,111 +270,85 @@ class BaseOption(Base):
|
||||||
"""
|
"""
|
||||||
# never change _name in an option or attribute when object is readonly
|
# never change _name in an option or attribute when object is readonly
|
||||||
if self.impl_is_readonly():
|
if self.impl_is_readonly():
|
||||||
raise AttributeError(
|
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
||||||
_('"{}" ({}) object attribute "{}" is' " read-only").format(
|
' read-only').format(self.__class__.__name__,
|
||||||
self.__class__.__name__, self.impl_get_display_name(None), name
|
self.impl_get_display_name(),
|
||||||
)
|
name))
|
||||||
)
|
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
|
|
||||||
def impl_getpath(self) -> str:
|
def impl_getpath(self) -> str:
|
||||||
"""get the path of the option"""
|
"""get the path of the option
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
return self._path
|
return self._path
|
||||||
except AttributeError as err:
|
except AttributeError as err:
|
||||||
raise AttributeError(
|
raise AttributeError(_(f'"{self.impl_get_display_name()}" not part of any Config')) \
|
||||||
_("{0} not part of any Config").format(
|
from err
|
||||||
self.impl_get_display_name(None, with_quote=True)
|
|
||||||
)
|
|
||||||
) from err
|
|
||||||
|
|
||||||
def impl_get_display_name(
|
def impl_get_display_name(self,
|
||||||
self,
|
dynopt=None,
|
||||||
subconfig: "SubConfig",
|
|
||||||
*,
|
|
||||||
with_quote: bool = False,
|
|
||||||
) -> str:
|
) -> str:
|
||||||
"""get display name"""
|
"""get display name
|
||||||
if hasattr(self, "_display_name_function"):
|
"""
|
||||||
return self._display_name_function(
|
if dynopt is None:
|
||||||
self,
|
dynopt = self
|
||||||
subconfig,
|
if hasattr(self, '_display_name_function'):
|
||||||
with_quote=with_quote,
|
return self._display_name_function(dynopt)
|
||||||
)
|
name = self.impl_get_information('doc', None)
|
||||||
name = self._get_information(subconfig, "doc", None)
|
if name is None or name == '':
|
||||||
if name is None or name == "":
|
name = dynopt.impl_getname()
|
||||||
if subconfig and subconfig.path:
|
|
||||||
name = subconfig.path.rsplit(".", 1)[-1]
|
|
||||||
else:
|
|
||||||
name = self._name
|
|
||||||
if with_quote:
|
|
||||||
return f'"{name}"'
|
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def reset_cache(
|
def reset_cache(self,
|
||||||
self,
|
|
||||||
path: str,
|
path: str,
|
||||||
config_bag: "OptionBag",
|
config_bag: 'OptionBag',
|
||||||
resetted_opts: List[Base], # pylint: disable=unused-argument
|
resetted_opts: List[Base], # pylint: disable=unused-argument
|
||||||
) -> None:
|
) -> None:
|
||||||
"""reset cache"""
|
"""reset cache
|
||||||
|
"""
|
||||||
context = config_bag.context
|
context = config_bag.context
|
||||||
context.properties_cache.delcache(path)
|
context.properties_cache.delcache(path)
|
||||||
context._impl_permissives_cache.delcache(
|
context._impl_permissives_cache.delcache(path) # pylint: disable=protected-access
|
||||||
path
|
|
||||||
) # pylint: disable=protected-access
|
|
||||||
if not self.impl_is_optiondescription():
|
if not self.impl_is_optiondescription():
|
||||||
context.get_values_cache().delcache(
|
context.get_values_cache().delcache(path) # pylint: disable=protected-access
|
||||||
path
|
|
||||||
) # pylint: disable=protected-access
|
|
||||||
|
|
||||||
def impl_is_symlinkoption(self) -> bool:
|
def impl_is_symlinkoption(self) -> bool:
|
||||||
"""the option is not a symlinkoption"""
|
"""the option is not a symlinkoption
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dependencies_information(self) -> List[str]:
|
def get_dependencies_information(self) -> List[str]:
|
||||||
"""get dependencies information"""
|
"""get dependencies information
|
||||||
return getattr(self, "_dependencies_information", {})
|
"""
|
||||||
|
return getattr(self, '_dependencies_information', {})
|
||||||
|
|
||||||
def value_dependencies(
|
def to_sub_dyoption(self,
|
||||||
self,
|
suffixes: list[str],
|
||||||
value: Any,
|
):
|
||||||
is_identifier: bool = False,
|
sub_dyn = self
|
||||||
) -> Any:
|
# retrieve all subdyn options
|
||||||
"""parse dependancies to add dependencies"""
|
sub_dyns = []
|
||||||
if isinstance(value, list):
|
while True:
|
||||||
for val in value:
|
sub_dyn = sub_dyn.getsubdyn()
|
||||||
if isinstance(value, list):
|
sub_dyns.append(sub_dyn)
|
||||||
self.value_dependencies(val, is_identifier)
|
if not sub_dyn.issubdyn():
|
||||||
elif isinstance(value, Calculation):
|
break
|
||||||
self.value_dependency(val, is_identifier)
|
paths = []
|
||||||
elif isinstance(value, Calculation):
|
parent_path = self.impl_getpath().rsplit('.', 1)[0]
|
||||||
self.value_dependency(value, is_identifier)
|
suffix_idx = len(sub_dyns) - 1
|
||||||
|
for sub_dyn in sub_dyns:
|
||||||
def value_dependency(
|
dyn_path = sub_dyn.impl_getpath()
|
||||||
self,
|
if dyn_path.count('.') == parent_path.count('.'):
|
||||||
value: Any,
|
*root_paths, dyn_path_ = parent_path.split('.', dyn_path.count('.') + 1)
|
||||||
is_identifier: bool = False,
|
|
||||||
) -> Any:
|
|
||||||
"""parse dependancy to add dependencies"""
|
|
||||||
for param in chain(value.params.args, value.params.kwargs.values()):
|
|
||||||
if isinstance(param, ParamOption):
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
param.option._add_dependency(self, is_identifier=is_identifier)
|
|
||||||
self._has_dependency = True
|
|
||||||
elif isinstance(param, ParamInformation):
|
|
||||||
dest = self
|
|
||||||
if isinstance(param, ParamSelfInformation):
|
|
||||||
opt = weakref.ref(self)
|
|
||||||
elif param.option:
|
|
||||||
dest = param.option
|
|
||||||
opt = weakref.ref(self)
|
|
||||||
else:
|
else:
|
||||||
param.set_self_option(self)
|
*root_paths, dyn_path_, child_path = parent_path.split('.', dyn_path.count('.') + 1)
|
||||||
opt = None
|
paths.insert(0, child_path)
|
||||||
if not getattr(dest, "_dependencies_information", {}):
|
paths.insert(0, sub_dyn.impl_getname(suffixes[suffix_idx]))
|
||||||
dest._dependencies_information = {None: []}
|
suffix_idx -= 1
|
||||||
dest._dependencies_information[None].append(param)
|
parent_path = '.'.join(root_paths)
|
||||||
dest._dependencies_information.setdefault(
|
if parent_path:
|
||||||
param.information_name, []
|
paths.insert(0, parent_path)
|
||||||
).append(opt)
|
full_parent_path = '.'.join(paths)
|
||||||
|
return self.to_dynoption(full_parent_path,
|
||||||
|
suffixes,
|
||||||
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -26,15 +26,15 @@ from .option import Option
|
||||||
|
|
||||||
|
|
||||||
class BoolOption(Option):
|
class BoolOption(Option):
|
||||||
"""represents a choice between ``True`` and ``False``"""
|
"""represents a choice between ``True`` and ``False``
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "boolean"
|
_type = _('boolean')
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: bool,
|
value: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validate value"""
|
"""validate value
|
||||||
|
"""
|
||||||
if not isinstance(value, bool):
|
if not isinstance(value, bool):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,21 +27,21 @@ from .option import Option
|
||||||
|
|
||||||
|
|
||||||
class BroadcastOption(Option):
|
class BroadcastOption(Option):
|
||||||
"""represents the choice of a broadcast"""
|
"""represents the choice of a broadcast
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "broadcast address"
|
_type = _('broadcast address')
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: str,
|
value: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validate"""
|
"""validate
|
||||||
|
"""
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise ValueError(_("invalid string"))
|
raise ValueError(_('invalid string'))
|
||||||
if value.count(".") != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
for val in value.split("."):
|
for val in value.split('.'):
|
||||||
if val.startswith("0") and len(val) > 1:
|
if val.startswith("0") and len(val) > 1:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -25,7 +25,7 @@ from typing import Any
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from ..autolib import Calculation, get_calculated_value
|
from ..autolib import Calculation
|
||||||
from ..error import ConfigError, display_list
|
from ..error import ConfigError, display_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,53 +34,49 @@ class ChoiceOption(Option):
|
||||||
|
|
||||||
The option can also have the value ``None``
|
The option can also have the value ``None``
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "choice"
|
_type = _('choice')
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
name,
|
||||||
|
doc,
|
||||||
|
values,
|
||||||
|
*args,
|
||||||
|
**kwargs):
|
||||||
|
|
||||||
def __init__(self, name, doc, values, *args, **kwargs):
|
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
"""
|
"""
|
||||||
if not isinstance(values, (Calculation, tuple)):
|
if not isinstance(values, (Calculation, tuple)):
|
||||||
raise TypeError(
|
raise TypeError(_('values must be a tuple or a calculation for {0}'
|
||||||
_("values must be a tuple or a calculation for {0}").format(name)
|
).format(name))
|
||||||
)
|
|
||||||
self._choice_values = values
|
self._choice_values = values
|
||||||
super().__init__(name, doc, *args, **kwargs)
|
super().__init__(name,
|
||||||
|
doc,
|
||||||
|
*args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def impl_get_values(
|
def impl_get_values(self,
|
||||||
self,
|
|
||||||
subconfig: "SubConfig",
|
subconfig: "SubConfig",
|
||||||
uncalculated: bool = False,
|
|
||||||
):
|
):
|
||||||
"""get values allowed by option"""
|
"""get values allowed by option
|
||||||
choices = self._choice_values
|
"""
|
||||||
if isinstance(choices, tuple):
|
if isinstance(self._choice_values, Calculation):
|
||||||
choices = list(choices)
|
values = self._choice_values.execute(subconfig)
|
||||||
if uncalculated:
|
if values is not undefined and not isinstance(values, list):
|
||||||
return choices
|
raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list'
|
||||||
values = get_calculated_value(
|
'').format(values, self.impl_getname()))
|
||||||
subconfig,
|
else:
|
||||||
choices,
|
values = self._choice_values
|
||||||
)[0]
|
|
||||||
|
|
||||||
if values != undefined and not isinstance(values, (list, tuple)):
|
|
||||||
raise ConfigError(
|
|
||||||
_('the calculated values "{0}" for "{1}" is not a list' "").format(
|
|
||||||
values, self.impl_getname()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: Any,
|
value: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""nothing to valide"""
|
"""nothing to valide
|
||||||
|
"""
|
||||||
|
|
||||||
def validate_with_option(
|
def validate_with_option(self,
|
||||||
self,
|
|
||||||
value: Any,
|
value: Any,
|
||||||
subconfig: "SubConfig",
|
subconfig: "SubConfig",
|
||||||
loaded: bool,
|
loaded: bool,
|
||||||
|
@ -90,17 +86,15 @@ class ChoiceOption(Option):
|
||||||
values = self.impl_get_values(subconfig)
|
values = self.impl_get_values(subconfig)
|
||||||
self.validate_values(value, values)
|
self.validate_values(value, values)
|
||||||
|
|
||||||
def validate_values(
|
def validate_values(self,
|
||||||
self,
|
|
||||||
value,
|
value,
|
||||||
values,
|
values,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validate values"""
|
"""validate values
|
||||||
|
"""
|
||||||
if values is not undefined and value not in values:
|
if values is not undefined and value not in values:
|
||||||
if len(values) == 1:
|
if len(values) == 1:
|
||||||
raise ValueError(_('only "{0}" is allowed' "").format(values[0]))
|
raise ValueError(_('only "{0}" is allowed'
|
||||||
raise ValueError(
|
'').format(values[0]))
|
||||||
_("only {0} are allowed" "").format(
|
raise ValueError(_('only {0} are allowed'
|
||||||
display_list(values, add_quote=True)
|
'').format(display_list(values, add_quote=True)))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,12 +27,13 @@ from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class DateOption(StrOption):
|
class DateOption(StrOption):
|
||||||
"""represents the choice of a date"""
|
"""represents the choice of a date
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "date"
|
_type = _('date')
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
try:
|
try:
|
||||||
datetime.strptime(value, "%Y-%m-%d")
|
datetime.strptime(value, "%Y-%m-%d")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -39,139 +39,131 @@ class DomainnameOption(StrOption):
|
||||||
domainname:
|
domainname:
|
||||||
fqdn: with tld, not supported yet
|
fqdn: with tld, not supported yet
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "domain name"
|
_type = _('domain name')
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
*args,
|
default: Any=undefined,
|
||||||
allow_ip: bool = False,
|
default_multi: Any=None,
|
||||||
allow_cidr_network: bool = False,
|
multi: bool=False,
|
||||||
type: str = "domainname",
|
validators: Optional[List[Calculation]]=None,
|
||||||
allow_without_dot: bool = False,
|
properties: Optional[List[str]]=None,
|
||||||
allow_startswith_dot: bool = False,
|
warnings_only: bool=False,
|
||||||
**kwargs,
|
allow_ip: bool=False,
|
||||||
|
allow_cidr_network: bool=False,
|
||||||
|
type: str='domainname',
|
||||||
|
allow_without_dot: bool=False,
|
||||||
|
allow_startswith_dot: bool=False,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
||||||
if type not in ["netbios", "hostname", "domainname"]:
|
if type not in ['netbios', 'hostname', 'domainname']:
|
||||||
raise ValueError(_("unknown type {0} for hostname").format(type))
|
raise ValueError(_('unknown type {0} for hostname').format(type))
|
||||||
extra = {"_dom_type": type}
|
extra = {'_dom_type': type}
|
||||||
if not isinstance(allow_ip, bool):
|
if not isinstance(allow_ip, bool):
|
||||||
raise ValueError(_("allow_ip must be a boolean"))
|
raise ValueError(_('allow_ip must be a boolean'))
|
||||||
if not isinstance(allow_cidr_network, bool):
|
if not isinstance(allow_cidr_network, bool):
|
||||||
raise ValueError(_("allow_cidr_network must be a boolean"))
|
raise ValueError(_('allow_cidr_network must be a boolean'))
|
||||||
if not isinstance(allow_without_dot, bool):
|
if not isinstance(allow_without_dot, bool):
|
||||||
raise ValueError(_("allow_without_dot must be a boolean"))
|
raise ValueError(_('allow_without_dot must be a boolean'))
|
||||||
if not isinstance(allow_startswith_dot, bool):
|
if not isinstance(allow_startswith_dot, bool):
|
||||||
raise ValueError(_("allow_startswith_dot must be a boolean"))
|
raise ValueError(_('allow_startswith_dot must be a boolean'))
|
||||||
extra["_allow_without_dot"] = allow_without_dot
|
extra['_allow_without_dot'] = allow_without_dot
|
||||||
if type == "domainname":
|
if type == 'domainname':
|
||||||
if allow_without_dot:
|
if allow_without_dot:
|
||||||
min_time = 0
|
min_time = 0
|
||||||
else:
|
else:
|
||||||
min_time = 1
|
min_time = 1
|
||||||
regexp = r"((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}".format(
|
regexp = r'((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}'.format(self._get_len(type), min_time)
|
||||||
self._get_len(type), min_time
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
regexp = r"((?!-)[a-z0-9-]{{1,{0}}})".format(self._get_len(type))
|
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type))
|
||||||
msg = _(
|
msg = _('must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed')
|
||||||
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed'
|
msg_warning = _('must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded')
|
||||||
)
|
|
||||||
msg_warning = _(
|
|
||||||
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded'
|
|
||||||
)
|
|
||||||
if allow_ip:
|
if allow_ip:
|
||||||
msg = _("could be a IP, otherwise {}").format(msg)
|
msg = _('could be a IP, otherwise {}').format(msg)
|
||||||
msg_warning = _("could be a IP, otherwise {}").format(msg_warning)
|
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
||||||
if not allow_cidr_network:
|
if not allow_cidr_network:
|
||||||
regexp = r"(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))".format(
|
regexp = r'(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))'.format(regexp)
|
||||||
regexp
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
regexp = r"(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[0-9][0-9]))".format(
|
regexp = r'(?:{0}|(?:(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){{3}}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/[0-9][0-9]))'.format(regexp)
|
||||||
regexp
|
regexp = r'^{0}$'.format(regexp)
|
||||||
)
|
extra['_domain_re'] = re.compile(regexp)
|
||||||
regexp = r"^{0}$".format(regexp)
|
extra['_domain_re_message'] = msg
|
||||||
extra["_domain_re"] = re.compile(regexp)
|
extra['_domain_re_message_warning'] = msg_warning
|
||||||
extra["_domain_re_message"] = msg
|
extra['_has_upper'] = re.compile('[A-Z]')
|
||||||
extra["_domain_re_message_warning"] = msg_warning
|
|
||||||
extra["_has_upper"] = re.compile("[A-Z]")
|
|
||||||
if allow_ip:
|
if allow_ip:
|
||||||
extra["_ip"] = IPOption(
|
extra['_ip'] = IPOption(name,
|
||||||
name,
|
doc)
|
||||||
doc,
|
extra['_allow_ip'] = allow_ip
|
||||||
)
|
|
||||||
extra["_allow_ip"] = allow_ip
|
|
||||||
if allow_cidr_network:
|
if allow_cidr_network:
|
||||||
extra["_network"] = NetworkOption(
|
extra['_network'] = NetworkOption(name,
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
cidr=True,
|
cidr=True)
|
||||||
)
|
extra['_allow_cidr_network'] = allow_cidr_network
|
||||||
extra["_allow_cidr_network"] = allow_cidr_network
|
extra['_allow_startswith_dot'] = allow_startswith_dot
|
||||||
extra["_allow_startswith_dot"] = allow_startswith_dot
|
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(name,
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
*args,
|
default=default,
|
||||||
extra=extra,
|
default_multi=default_multi,
|
||||||
**kwargs,
|
multi=multi,
|
||||||
)
|
validators=validators,
|
||||||
|
properties=properties,
|
||||||
|
warnings_only=warnings_only,
|
||||||
|
extra=extra)
|
||||||
|
|
||||||
def _get_len(self, type_):
|
def _get_len(self, type_):
|
||||||
if type_ == "netbios":
|
if type_ == 'netbios':
|
||||||
return 15
|
return 15
|
||||||
return 63
|
return 63
|
||||||
|
|
||||||
def _validate_domain(self, value: str) -> None:
|
def _validate_domain(self,
|
||||||
|
value: str) -> None:
|
||||||
def _valid_length(val):
|
def _valid_length(val):
|
||||||
if len(val) < 1:
|
if len(val) < 1:
|
||||||
raise ValueError(_("invalid length (min 1)"))
|
raise ValueError(_("invalid length (min 1)"))
|
||||||
if len(val) > part_name_length:
|
if len(val) > part_name_length:
|
||||||
raise ValueError(
|
raise ValueError(_("invalid length (max {0})"
|
||||||
_("invalid length (max {0})" "").format(part_name_length)
|
"").format(part_name_length))
|
||||||
)
|
|
||||||
|
|
||||||
part_name_length = self._get_len(self.impl_get_extra("_dom_type"))
|
part_name_length = self._get_len(self.impl_get_extra('_dom_type'))
|
||||||
if self.impl_get_extra("_dom_type") == "domainname":
|
if self.impl_get_extra('_dom_type') == 'domainname':
|
||||||
if not self.impl_get_extra("_allow_without_dot") and not "." in value:
|
if not self.impl_get_extra('_allow_without_dot') and not "." in value:
|
||||||
raise ValueError(_("must have dot"))
|
raise ValueError(_("must have dot"))
|
||||||
if len(value) > 255:
|
if len(value) > 255:
|
||||||
raise ValueError(_("invalid length (max 255)"))
|
raise ValueError(_("invalid length (max 255)"))
|
||||||
if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."):
|
if self.impl_get_extra('_allow_startswith_dot') and value.startswith('.'):
|
||||||
val = value[1:]
|
val = value[1:]
|
||||||
else:
|
else:
|
||||||
val = value
|
val = value
|
||||||
if val.endswith("."):
|
if val.endswith('.'):
|
||||||
nval = val[:-1]
|
nval = val[:-1]
|
||||||
else:
|
else:
|
||||||
nval = val
|
nval = val
|
||||||
for dom in nval.split("."):
|
for dom in nval.split('.'):
|
||||||
_valid_length(dom)
|
_valid_length(dom)
|
||||||
else:
|
else:
|
||||||
_valid_length(value)
|
_valid_length(value)
|
||||||
|
|
||||||
def _validate_ip_network(self, value: str) -> None:
|
def _validate_ip_network(self,
|
||||||
allow_ip = self.impl_get_extra("_allow_ip")
|
value: str) -> None:
|
||||||
allow_cidr_network = self.impl_get_extra("_allow_cidr_network")
|
allow_ip = self.impl_get_extra('_allow_ip')
|
||||||
|
allow_cidr_network = self.impl_get_extra('_allow_cidr_network')
|
||||||
if allow_ip is False and allow_cidr_network is False:
|
if allow_ip is False and allow_cidr_network is False:
|
||||||
raise ValueError(_("must not be an IP"))
|
raise ValueError(_('must not be an IP'))
|
||||||
if allow_ip is True:
|
if allow_ip is True:
|
||||||
try:
|
try:
|
||||||
self.impl_get_extra("_ip").validate(value)
|
self.impl_get_extra('_ip').validate(value)
|
||||||
return
|
return
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if allow_cidr_network is False:
|
if allow_cidr_network is False:
|
||||||
raise err
|
raise err
|
||||||
if allow_cidr_network is True:
|
if allow_cidr_network is True:
|
||||||
self.impl_get_extra("_network").validate(value)
|
self.impl_get_extra('_network').validate(value)
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
try:
|
try:
|
||||||
# check if it's an IP or network
|
# check if it's an IP or network
|
||||||
|
@ -181,40 +173,42 @@ class DomainnameOption(StrOption):
|
||||||
else:
|
else:
|
||||||
self._validate_ip_network(value)
|
self._validate_ip_network(value)
|
||||||
|
|
||||||
def _second_level_validation_domain(self, value: str, warnings_only: bool) -> None:
|
def _second_level_validation_domain(self,
|
||||||
if self.impl_get_extra("_has_upper").search(value):
|
value: str,
|
||||||
raise ValueError(_("some characters are uppercase"))
|
warnings_only: bool) -> None:
|
||||||
if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."):
|
if self.impl_get_extra('_has_upper').search(value):
|
||||||
|
raise ValueError(_('some characters are uppercase'))
|
||||||
|
if self.impl_get_extra('_allow_startswith_dot') and value.startswith('.'):
|
||||||
val = value[1:]
|
val = value[1:]
|
||||||
else:
|
else:
|
||||||
val = value
|
val = value
|
||||||
if val.endswith("."):
|
if val.endswith('.'):
|
||||||
nval = val[:-1]
|
nval = val[:-1]
|
||||||
else:
|
else:
|
||||||
nval = val
|
nval = val
|
||||||
if not self.impl_get_extra("_domain_re").search(nval):
|
if not self.impl_get_extra('_domain_re').search(nval):
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
raise ValueError(self.impl_get_extra("_domain_re_message_warning"))
|
raise ValueError(self.impl_get_extra('_domain_re_message_warning'))
|
||||||
raise ValueError(self.impl_get_extra("_domain_re_message"))
|
raise ValueError(self.impl_get_extra('_domain_re_message'))
|
||||||
|
|
||||||
def _second_level_validation_ip_network(
|
def _second_level_validation_ip_network(self,
|
||||||
self, value: str, warnings_only: bool
|
value: str,
|
||||||
) -> None:
|
warnings_only: bool) -> None:
|
||||||
allow_ip = self.impl_get_extra("_allow_ip")
|
allow_ip = self.impl_get_extra('_allow_ip')
|
||||||
allow_cidr_network = self.impl_get_extra("_allow_cidr_network")
|
allow_cidr_network = self.impl_get_extra('_allow_cidr_network')
|
||||||
# it's an IP so validate with IPOption
|
# it's an IP so validate with IPOption
|
||||||
if allow_ip is True and allow_cidr_network is False:
|
if allow_ip is True and allow_cidr_network is False:
|
||||||
try:
|
try:
|
||||||
self.impl_get_extra("_ip").second_level_validation(value, warnings_only)
|
self.impl_get_extra('_ip').second_level_validation(value, warnings_only)
|
||||||
return
|
return
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise err
|
raise err
|
||||||
if allow_cidr_network is True:
|
if allow_cidr_network is True:
|
||||||
self.impl_get_extra("_network").second_level_validation(
|
self.impl_get_extra('_network').second_level_validation(value, warnings_only)
|
||||||
value, warnings_only
|
|
||||||
)
|
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
try:
|
try:
|
||||||
# check if it's an IP or network
|
# check if it's an IP or network
|
||||||
ip_interface(value)
|
ip_interface(value)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -20,135 +20,81 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"""DynOptionDescription
|
"""DynOptionDescription
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
import weakref
|
import weakref
|
||||||
from typing import List, Any, Optional, Dict
|
from typing import List, Any, Optional
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
from ..autolib import ParamOption
|
from ..autolib import ParamOption
|
||||||
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .optiondescription import OptionDescription
|
from .optiondescription import OptionDescription
|
||||||
|
from .syndynoption import CommonDyn #, SynDynLeadership
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
from ..setting import ConfigBag, undefined
|
from ..setting import ConfigBag, undefined
|
||||||
from ..error import ConfigError
|
from ..error import ConfigError
|
||||||
from ..autolib import Calculation, get_calculated_value
|
from ..autolib import Calculation
|
||||||
|
|
||||||
|
|
||||||
NAME_REGEXP = re.compile(r"^[a-zA-Z\d\-_]*$")
|
class DynOptionDescription(OptionDescription, CommonDyn):
|
||||||
|
"""dyn option description
|
||||||
|
"""
|
||||||
class DynOptionDescription(OptionDescription):
|
__slots__ = ('_suffixes',
|
||||||
"""dyn option description"""
|
'_subdyns',
|
||||||
|
|
||||||
__slots__ = (
|
|
||||||
"_identifiers",
|
|
||||||
"_subdyns",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
identifiers: Calculation,
|
suffixes: Calculation,
|
||||||
**kwargs,
|
properties=None,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=too-many-arguments
|
# pylint: disable=too-many-arguments
|
||||||
super().__init__(
|
super().__init__(name,
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
children,
|
children,
|
||||||
**kwargs,
|
properties,
|
||||||
)
|
)
|
||||||
# check children + set relation to this dynoptiondescription
|
# check children + set relation to this dynoptiondescription
|
||||||
wself = weakref.ref(self)
|
wself = weakref.ref(self)
|
||||||
for child in children:
|
for child in children:
|
||||||
child._setsubdyn(wself)
|
child._setsubdyn(wself)
|
||||||
# add identifiers
|
# add suffixes
|
||||||
self.value_dependencies(identifiers, is_identifier=True)
|
if __debug__ and not isinstance(suffixes, Calculation):
|
||||||
self._identifiers = identifiers
|
raise ConfigError(_('suffixes in dynoptiondescription has to be a calculation'))
|
||||||
|
for param in chain(suffixes.params.args, suffixes.params.kwargs.values()):
|
||||||
|
if isinstance(param, ParamOption):
|
||||||
|
param.option._add_dependency(self,
|
||||||
|
is_suffix=True,
|
||||||
|
)
|
||||||
|
self._suffixes = suffixes
|
||||||
|
|
||||||
def convert_identifier_to_path(
|
def convert_suffix_to_path(self,
|
||||||
self,
|
suffix: Any,
|
||||||
identifier: Any,
|
|
||||||
) -> str:
|
) -> str:
|
||||||
"""convert identifier to use it to a path"""
|
"""convert suffix to use it to a path
|
||||||
if identifier is None:
|
"""
|
||||||
|
if suffix is None:
|
||||||
return None
|
return None
|
||||||
if not isinstance(identifier, str):
|
if not isinstance(suffix, str):
|
||||||
identifier = str(identifier)
|
suffix = str(suffix)
|
||||||
if "." in identifier:
|
if '.' in suffix:
|
||||||
identifier = identifier.replace(".", "_")
|
suffix = suffix.replace('.', '_')
|
||||||
return identifier
|
return suffix
|
||||||
|
|
||||||
def impl_is_dynoptiondescription(self) -> bool:
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def option_is_self(
|
def option_is_self(self,
|
||||||
self,
|
|
||||||
option,
|
option,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
return option == self
|
return option == self
|
||||||
|
|
||||||
def impl_getname(self, identifier=None) -> str:
|
def impl_getname(self, suffix=None) -> str:
|
||||||
"""get name"""
|
"""get name
|
||||||
|
"""
|
||||||
name = super().impl_getname()
|
name = super().impl_getname()
|
||||||
if identifier is None:
|
if suffix is None:
|
||||||
return name
|
return name
|
||||||
path_identifier = self.convert_identifier_to_path(identifier)
|
path_suffix = self.convert_suffix_to_path(suffix)
|
||||||
return name + path_identifier
|
return name + path_suffix
|
||||||
|
|
||||||
def get_identifiers(
|
|
||||||
self,
|
|
||||||
parent: "SubConfig",
|
|
||||||
*,
|
|
||||||
uncalculated: bool = False,
|
|
||||||
) -> List[str]:
|
|
||||||
"""get dynamic identifiers"""
|
|
||||||
subconfig = parent.get_child(
|
|
||||||
self,
|
|
||||||
None,
|
|
||||||
False,
|
|
||||||
properties=None,
|
|
||||||
)
|
|
||||||
identifiers = self._identifiers
|
|
||||||
if isinstance(identifiers, list):
|
|
||||||
identifiers = identifiers.copy()
|
|
||||||
if uncalculated:
|
|
||||||
return identifiers
|
|
||||||
values = get_calculated_value(
|
|
||||||
subconfig,
|
|
||||||
identifiers,
|
|
||||||
validate_properties=False,
|
|
||||||
)[0]
|
|
||||||
if values is None:
|
|
||||||
values = []
|
|
||||||
values_ = []
|
|
||||||
if __debug__:
|
|
||||||
if not isinstance(values, list):
|
|
||||||
raise ValueError(
|
|
||||||
_(
|
|
||||||
"DynOptionDescription identifiers for option {0}, is not a list ({1})"
|
|
||||||
).format(
|
|
||||||
self.impl_get_display_name(subconfig, with_quote=True), values
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for val in values:
|
|
||||||
cval = self.convert_identifier_to_path(val)
|
|
||||||
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
|
|
||||||
if __debug__ and cval is not None:
|
|
||||||
raise ValueError(
|
|
||||||
_('invalid identifier "{}" for option {}' "").format(
|
|
||||||
cval, self.impl_get_display_name(subconfig, with_quote=True)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
values_.append(val)
|
|
||||||
if __debug__ and len(values_) > len(set(values_)):
|
|
||||||
raise ValueError(
|
|
||||||
_(
|
|
||||||
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'
|
|
||||||
).format(self._name, values_)
|
|
||||||
)
|
|
||||||
return values_
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,10 +27,8 @@ from .stroption import RegexpOption
|
||||||
|
|
||||||
|
|
||||||
class EmailOption(RegexpOption):
|
class EmailOption(RegexpOption):
|
||||||
"""represents a choice of an email"""
|
"""represents a choice of an email
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_regexp = re.compile(
|
_regexp = re.compile(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||||
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"
|
_type = _('email address')
|
||||||
)
|
|
||||||
_type = "email address"
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -20,62 +20,19 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"""FilenameOption
|
"""FilenameOption
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..error import display_list
|
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class FilenameOption(StrOption):
|
class FilenameOption(StrOption):
|
||||||
"""validate file or directory name"""
|
"""represents a choice of a file name
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "file name"
|
_type = _('file name')
|
||||||
|
|
||||||
def __init__(
|
def validate(self,
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
*args,
|
|
||||||
allow_relative=False,
|
|
||||||
test_existence=False,
|
|
||||||
types=["file", "directory"],
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
if not isinstance(types, list):
|
|
||||||
raise ValueError(
|
|
||||||
_('types parameter must be a list, not "{0}" for "{1}"').format(
|
|
||||||
types, name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for typ in types:
|
|
||||||
if typ not in ["file", "directory"]:
|
|
||||||
raise ValueError(f'unknown type "{typ}" for "{name}"')
|
|
||||||
extra = {
|
|
||||||
"_allow_relative": allow_relative,
|
|
||||||
"_test_existence": test_existence,
|
|
||||||
"_types": types,
|
|
||||||
}
|
|
||||||
super().__init__(name, *args, extra=extra, **kwargs)
|
|
||||||
|
|
||||||
def validate(
|
|
||||||
self,
|
|
||||||
value: str,
|
value: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if not self.impl_get_extra("_allow_relative") and not value.startswith("/"):
|
if not value.startswith('/'):
|
||||||
raise ValueError(_('must starts with "/"'))
|
raise ValueError(_('must starts with "/"'))
|
||||||
if value is not None and self.impl_get_extra("_test_existence"):
|
|
||||||
types = self.impl_get_extra("_types")
|
|
||||||
file = Path(value)
|
|
||||||
found = False
|
|
||||||
if "file" in types and file.is_file():
|
|
||||||
found = True
|
|
||||||
if not found and "directory" in types and file.is_dir():
|
|
||||||
found = True
|
|
||||||
if not found:
|
|
||||||
raise ValueError(
|
|
||||||
_('cannot find {0} "{1}"').format(
|
|
||||||
display_list(types, separator="or"), value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -26,11 +26,12 @@ from .option import Option
|
||||||
|
|
||||||
|
|
||||||
class FloatOption(Option):
|
class FloatOption(Option):
|
||||||
"""represents a choice of a floating point number"""
|
"""represents a choice of a floating point number
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "float"
|
_type = _('float')
|
||||||
|
|
||||||
def validate(self, value: float) -> None:
|
def validate(self,
|
||||||
|
value: float) -> None:
|
||||||
if not isinstance(value, float):
|
if not isinstance(value, float):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -28,35 +28,40 @@ from .option import Option
|
||||||
class IntOption(Option):
|
class IntOption(Option):
|
||||||
"represents a choice of an integer"
|
"represents a choice of an integer"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "integer"
|
_type = _('integer')
|
||||||
|
|
||||||
def __init__(self, *args, min_number=None, max_number=None, **kwargs):
|
def __init__(self,
|
||||||
|
*args,
|
||||||
|
min_number=None,
|
||||||
|
max_number=None,
|
||||||
|
**kwargs):
|
||||||
extra = {}
|
extra = {}
|
||||||
if min_number is not None:
|
if min_number is not None:
|
||||||
extra["min_number"] = min_number
|
extra['min_number'] = min_number
|
||||||
if max_number is not None:
|
if max_number is not None:
|
||||||
extra["max_number"] = max_number
|
extra['max_number'] = max_number
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: int,
|
value: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def second_level_validation(self, value, warnings_only):
|
def second_level_validation(self,
|
||||||
min_number = self.impl_get_extra("min_number")
|
value,
|
||||||
|
warnings_only):
|
||||||
|
min_number = self.impl_get_extra('min_number')
|
||||||
if min_number is not None and value < min_number:
|
if min_number is not None and value < min_number:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _('value should be equal or greater than "{0}"')
|
msg = 'value should be greater than "{0}"'
|
||||||
else:
|
else:
|
||||||
msg = _('value must be equal or greater than "{0}"')
|
msg = 'value must be greater than "{0}"'
|
||||||
raise ValueError(msg.format(min_number))
|
raise ValueError(_(msg).format(min_number))
|
||||||
max_number = self.impl_get_extra("max_number")
|
max_number = self.impl_get_extra('max_number')
|
||||||
if max_number is not None and value > max_number:
|
if max_number is not None and value > max_number:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _('value should be less than "{0}"')
|
msg = 'value should be less than "{0}"'
|
||||||
else:
|
else:
|
||||||
msg = _('value must be less than "{0}"')
|
msg = 'value must be less than "{0}"'
|
||||||
raise ValueError(msg.format(max_number))
|
raise ValueError(_(msg).format(max_number))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,26 +27,26 @@ from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class IPOption(StrOption):
|
class IPOption(StrOption):
|
||||||
"""represents the choice of an ip"""
|
"""represents the choice of an ip
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "IP"
|
_type = _('IP')
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
*args,
|
*args,
|
||||||
private_only=False,
|
private_only=False,
|
||||||
allow_reserved=False,
|
allow_reserved=False,
|
||||||
cidr=False,
|
cidr=False,
|
||||||
extra=None,
|
extra=None,
|
||||||
**kwargs,
|
**kwargs):
|
||||||
):
|
|
||||||
if extra is None:
|
if extra is None:
|
||||||
extra = {}
|
extra = {}
|
||||||
extra["_private_only"] = private_only
|
extra['_private_only'] = private_only
|
||||||
extra["_allow_reserved"] = allow_reserved
|
extra['_allow_reserved'] = allow_reserved
|
||||||
extra["_cidr"] = cidr
|
extra['_cidr'] = cidr
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
super().__init__(*args,
|
||||||
|
extra=extra,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def _validate_cidr(self, value):
|
def _validate_cidr(self, value):
|
||||||
try:
|
try:
|
||||||
|
@ -64,24 +64,27 @@ class IPOption(StrOption):
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError() from err
|
raise ValueError() from err
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if self.impl_get_extra("_cidr"):
|
if self.impl_get_extra('_cidr'):
|
||||||
if "/" not in value:
|
if '/' not in value:
|
||||||
raise ValueError(_('CIDR address must have a "/"'))
|
raise ValueError(_('CIDR address must have a "/"'))
|
||||||
self._validate_cidr(value)
|
self._validate_cidr(value)
|
||||||
else:
|
else:
|
||||||
self._validate_ip(value)
|
self._validate_ip(value)
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
ip_obj = ip_interface(value)
|
ip_obj = ip_interface(value)
|
||||||
if not self.impl_get_extra("_allow_reserved") and ip_obj.is_reserved:
|
if not self.impl_get_extra('_allow_reserved') and ip_obj.is_reserved:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("shouldn't be reserved IP")
|
msg = _("shouldn't be reserved IP")
|
||||||
else:
|
else:
|
||||||
msg = _("mustn't be reserved IP")
|
msg = _("mustn't be reserved IP")
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if self.impl_get_extra("_private_only") and not ip_obj.is_private:
|
if self.impl_get_extra('_private_only') and not ip_obj.is_private:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("should be private IP")
|
msg = _("should be private IP")
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"Leadership support"
|
"Leadership support"
|
||||||
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -26,7 +26,6 @@ from typing import List, Iterator, Optional
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import groups, undefined, ALLOWED_LEADER_PROPERTIES
|
from ..setting import groups, undefined, ALLOWED_LEADER_PROPERTIES
|
||||||
from .optiondescription import OptionDescription
|
from .optiondescription import OptionDescription
|
||||||
|
|
||||||
# from .syndynoption import SynDynLeadership
|
# from .syndynoption import SynDynLeadership
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
from .option import Option
|
from .option import Option
|
||||||
|
@ -35,95 +34,58 @@ from ..autolib import Calculation
|
||||||
|
|
||||||
|
|
||||||
class Leadership(OptionDescription):
|
class Leadership(OptionDescription):
|
||||||
"""Leadership"""
|
"""Leadership
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-arguments
|
# pylint: disable=too-many-arguments
|
||||||
__slots__ = (
|
__slots__ = ('leader',
|
||||||
"leader",
|
'followers',
|
||||||
"followers",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
**kwargs,
|
properties=None) -> None:
|
||||||
) -> None:
|
super().__init__(name,
|
||||||
if "group_type" in kwargs:
|
|
||||||
raise LeadershipError(
|
|
||||||
_('cannot set "group_type" attribute for a Leadership')
|
|
||||||
)
|
|
||||||
super().__init__(
|
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
children,
|
children,
|
||||||
**kwargs,
|
properties=properties)
|
||||||
)
|
|
||||||
self._group_type = groups.leadership
|
self._group_type = groups.leadership
|
||||||
followers = []
|
followers = []
|
||||||
if len(children) < 2:
|
if len(children) < 2:
|
||||||
raise ValueError(
|
raise ValueError(_('a leader and a follower are mandatories in leadership "{}"'
|
||||||
_(
|
'').format(name))
|
||||||
'a leader and a follower are mandatories in leadership "{}"' ""
|
leader = children[0]
|
||||||
).format(name)
|
|
||||||
)
|
|
||||||
for idx, child in enumerate(children):
|
for idx, child in enumerate(children):
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._check_child_is_valid(child, idx, children)
|
self._check_child_is_valid(child)
|
||||||
if idx != 0:
|
if idx != 0:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._check_default_value(child)
|
self._check_default_value(child)
|
||||||
# remove empty property for follower
|
# remove empty property for follower
|
||||||
child._properties = frozenset(child._properties - {"empty", "unique"})
|
child._properties = frozenset(child._properties - {'empty', 'unique'})
|
||||||
followers.append(child)
|
followers.append(child)
|
||||||
child._add_dependency(self)
|
child._add_dependency(self)
|
||||||
child._leadership = weakref.ref(self)
|
child._leadership = weakref.ref(self)
|
||||||
if __debug__:
|
if __debug__:
|
||||||
leader = children[0]
|
|
||||||
for prop in leader.impl_getproperties():
|
for prop in leader.impl_getproperties():
|
||||||
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(
|
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation):
|
||||||
prop, Calculation
|
raise LeadershipError(_('leader cannot have "{}" property').format(prop))
|
||||||
):
|
|
||||||
raise LeadershipError(
|
|
||||||
_('leader cannot have "{}" property').format(prop)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_child_is_valid(
|
def _check_child_is_valid(self, child: BaseOption):
|
||||||
self,
|
|
||||||
child: BaseOption,
|
|
||||||
index: int,
|
|
||||||
children: [BaseOption],
|
|
||||||
) -> None:
|
|
||||||
if child.impl_is_symlinkoption():
|
if child.impl_is_symlinkoption():
|
||||||
if not index:
|
raise ValueError(_('leadership "{0}" shall not have '
|
||||||
raise ValueError(
|
"a symlinkoption").format(self.impl_get_display_name()))
|
||||||
_("leadership {0} shall not have " "a symlinkoption").format(
|
|
||||||
self.impl_get_display_name(None, with_quote=True)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
if not isinstance(child, Option):
|
if not isinstance(child, Option):
|
||||||
raise ValueError(
|
raise ValueError(_('leadership "{0}" shall not have '
|
||||||
_("leadership {0} shall not have " "a subgroup").format(
|
'a subgroup').format(self.impl_get_display_name()))
|
||||||
self.impl_get_display_name(None, with_quote=True)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if not child.impl_is_multi():
|
if not child.impl_is_multi():
|
||||||
raise ValueError(
|
raise ValueError(_('only multi option allowed in leadership "{0}" but option '
|
||||||
_(
|
'"{1}" is not a multi'
|
||||||
"only multi option allowed in leadership {0} but option "
|
'').format(self.impl_get_display_name(),
|
||||||
"{1} is not a multi"
|
child.impl_get_display_name()))
|
||||||
""
|
|
||||||
).format(
|
|
||||||
self.impl_get_display_name(None, with_quote=True),
|
|
||||||
child.impl_get_display_name(None, with_quote=True),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _check_default_value(self, child: BaseOption):
|
def _check_default_value(self, child: BaseOption):
|
||||||
if child.impl_is_symlinkoption():
|
|
||||||
return
|
|
||||||
default = child.impl_getdefault()
|
default = child.impl_getdefault()
|
||||||
if default != []:
|
if default != []:
|
||||||
if child.impl_is_submulti() and isinstance(default, (list, tuple)):
|
if child.impl_is_submulti() and isinstance(default, (list, tuple)):
|
||||||
|
@ -137,115 +99,111 @@ class Leadership(OptionDescription):
|
||||||
else:
|
else:
|
||||||
calculation = isinstance(default, Calculation)
|
calculation = isinstance(default, Calculation)
|
||||||
if not calculation:
|
if not calculation:
|
||||||
raise ValueError(
|
raise ValueError(_('not allowed default value for follower option '
|
||||||
_(
|
f'"{child.impl_get_display_name()}" in leadership '
|
||||||
"not allowed default value for follower option {0} in leadership {1}"
|
f'"{self.impl_get_display_name()}"'))
|
||||||
).format(
|
|
||||||
child.impl_get_display_name(None, with_quote=True),
|
|
||||||
self.impl_get_display_name(None, with_quote=True),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def _setsubdyn(
|
def _setsubdyn(self,
|
||||||
self,
|
|
||||||
subdyn,
|
subdyn,
|
||||||
) -> None:
|
) -> None:
|
||||||
for chld in self._children[1]:
|
for chld in self._children[1]:
|
||||||
chld._setsubdyn(subdyn)
|
chld._setsubdyn(subdyn)
|
||||||
super()._setsubdyn(subdyn)
|
super()._setsubdyn(subdyn)
|
||||||
|
|
||||||
def is_leader(
|
def is_leader(self,
|
||||||
self,
|
|
||||||
opt: Option,
|
opt: Option,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""the option is the leader"""
|
"""the option is the leader
|
||||||
|
"""
|
||||||
leader = self.get_leader()
|
leader = self.get_leader()
|
||||||
if opt.impl_is_dynsymlinkoption():
|
if opt.impl_is_dynsymlinkoption():
|
||||||
opt = opt.opt
|
opt = opt.opt
|
||||||
return opt == leader
|
return opt == leader
|
||||||
|
|
||||||
def get_leader(self) -> Option:
|
def get_leader(self) -> Option:
|
||||||
"""get leader"""
|
"""get leader
|
||||||
|
"""
|
||||||
return self._children[1][0]
|
return self._children[1][0]
|
||||||
|
|
||||||
def get_followers(self) -> Iterator[Option]:
|
def get_followers(self) -> Iterator[Option]:
|
||||||
"""get all followers"""
|
"""get all followers
|
||||||
|
"""
|
||||||
for follower in self._children[1][1:]:
|
for follower in self._children[1][1:]:
|
||||||
yield follower
|
yield follower
|
||||||
|
|
||||||
def in_same_leadership(
|
def in_same_leadership(self,
|
||||||
self,
|
|
||||||
opt: Option,
|
opt: Option,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""check if followers are in same leadership"""
|
"""check if followers are in same leadership
|
||||||
|
"""
|
||||||
if opt.impl_is_dynsymlinkoption():
|
if opt.impl_is_dynsymlinkoption():
|
||||||
opt = opt.opt
|
opt = opt.opt
|
||||||
return opt in self._children[1]
|
return opt in self._children[1]
|
||||||
|
|
||||||
def reset(self, parent: "SubConfig") -> None:
|
def reset(self, parent: "SubConfig") -> None:
|
||||||
"""reset follower value"""
|
"""reset follower value
|
||||||
|
"""
|
||||||
|
#config_bag = parent.option_bag.config_bag
|
||||||
values = parent.config_bag.context.get_values()
|
values = parent.config_bag.context.get_values()
|
||||||
|
#config_bag = config_bag.copy()
|
||||||
|
#config_bag.remove_validation()
|
||||||
for follower in self.get_followers():
|
for follower in self.get_followers():
|
||||||
subconfig_follower = parent.get_child(
|
subconfig_follower = parent.get_child(follower,
|
||||||
follower,
|
|
||||||
None,
|
None,
|
||||||
False,
|
False,
|
||||||
)
|
)
|
||||||
values.reset(
|
# OptionBag(follower,
|
||||||
subconfig_follower,
|
# None,
|
||||||
validate=False,
|
# config_bag,
|
||||||
)
|
# )
|
||||||
|
values.reset(subconfig_follower)
|
||||||
|
#
|
||||||
|
# def follower_force_store_value(self,
|
||||||
|
# value,
|
||||||
|
# config_bag: 'ConfigBag',
|
||||||
|
# owner,
|
||||||
|
# dyn=None,
|
||||||
|
# ) -> None:
|
||||||
|
# """apply force_store_value to follower
|
||||||
|
# """
|
||||||
|
# if value:
|
||||||
|
# if dyn is None:
|
||||||
|
# dyn = self
|
||||||
|
# values = config_bag.context.get_values()
|
||||||
|
# for idx, follower in enumerate(dyn.get_children(config_bag)):
|
||||||
|
# if not idx:
|
||||||
|
# # it's a master
|
||||||
|
# apply_requires = True
|
||||||
|
# indexes = [None]
|
||||||
|
# else:
|
||||||
|
# apply_requires = False
|
||||||
|
# indexes = range(len(value))
|
||||||
|
# foption_bag = OptionBag(follower,
|
||||||
|
# None,
|
||||||
|
# config_bag,
|
||||||
|
# apply_requires=apply_requires,
|
||||||
|
# )
|
||||||
|
# if 'force_store_value' not in foption_bag.properties:
|
||||||
|
# continue
|
||||||
|
# for index in indexes:
|
||||||
|
# foption_bag_index = OptionBag(follower,
|
||||||
|
# index,
|
||||||
|
# config_bag,
|
||||||
|
# )
|
||||||
|
# values.set_storage_value(foption_bag_index.path,
|
||||||
|
# index,
|
||||||
|
# values.get_value(foption_bag_index)[0],
|
||||||
|
# owner,
|
||||||
|
# )
|
||||||
|
|
||||||
def follower_force_store_value(
|
def pop(self,
|
||||||
self,
|
subconfig: 'SubConfig',
|
||||||
value,
|
|
||||||
subconfig: "SubConfig",
|
|
||||||
owner,
|
|
||||||
) -> None:
|
|
||||||
"""apply force_store_value to follower"""
|
|
||||||
if not value:
|
|
||||||
return
|
|
||||||
config_bag = subconfig.config_bag
|
|
||||||
values = config_bag.context.get_values()
|
|
||||||
for idx, follower in enumerate(self.get_children()):
|
|
||||||
sub_subconfig = subconfig.get_child(
|
|
||||||
follower,
|
|
||||||
None,
|
|
||||||
False,
|
|
||||||
config_bag=config_bag,
|
|
||||||
)
|
|
||||||
if "force_store_value" not in sub_subconfig.properties:
|
|
||||||
continue
|
|
||||||
self_path = sub_subconfig.path
|
|
||||||
if not idx:
|
|
||||||
# it's a master
|
|
||||||
apply_requires = True
|
|
||||||
indexes = [None]
|
|
||||||
else:
|
|
||||||
apply_requires = False
|
|
||||||
indexes = range(len(value))
|
|
||||||
for index in indexes:
|
|
||||||
i_sub_subconfig = subconfig.get_child(
|
|
||||||
follower,
|
|
||||||
index,
|
|
||||||
False,
|
|
||||||
config_bag=config_bag,
|
|
||||||
)
|
|
||||||
values.set_storage_value(
|
|
||||||
self_path,
|
|
||||||
index,
|
|
||||||
values.get_value(i_sub_subconfig)[0],
|
|
||||||
owner,
|
|
||||||
)
|
|
||||||
|
|
||||||
def pop(
|
|
||||||
self,
|
|
||||||
subconfig: "SubConfig",
|
|
||||||
index: int,
|
index: int,
|
||||||
*,
|
*,
|
||||||
followers: Optional[List[Option]] = undefined,
|
followers: Optional[List[Option]]=undefined,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""pop leader value and follower's one"""
|
"""pop leader value and follower's one
|
||||||
|
"""
|
||||||
if followers is undefined:
|
if followers is undefined:
|
||||||
# followers are not undefined only in SynDynLeadership
|
# followers are not undefined only in SynDynLeadership
|
||||||
followers = self.get_followers()
|
followers = self.get_followers()
|
||||||
|
@ -253,8 +211,7 @@ class Leadership(OptionDescription):
|
||||||
config_bag.remove_validation()
|
config_bag.remove_validation()
|
||||||
values = config_bag.context.get_values()
|
values = config_bag.context.get_values()
|
||||||
for follower in followers:
|
for follower in followers:
|
||||||
sub_subconfig = subconfig.parent.get_child(
|
sub_subconfig = subconfig.parent.get_child(follower,
|
||||||
follower,
|
|
||||||
index,
|
index,
|
||||||
True,
|
True,
|
||||||
properties=set(), # do not check force_default_on_freeze
|
properties=set(), # do not check force_default_on_freeze
|
||||||
|
@ -263,48 +220,51 @@ class Leadership(OptionDescription):
|
||||||
)
|
)
|
||||||
values.reduce_index(sub_subconfig)
|
values.reduce_index(sub_subconfig)
|
||||||
|
|
||||||
def reset_cache(
|
def reset_cache(self,
|
||||||
self,
|
|
||||||
path: str,
|
path: str,
|
||||||
config_bag: "ConfigBag",
|
config_bag: 'ConfigBag',
|
||||||
resetted_opts: List[Option],
|
resetted_opts: List[Option],
|
||||||
) -> None:
|
) -> None:
|
||||||
self._reset_cache(
|
self._reset_cache(path,
|
||||||
path,
|
|
||||||
self.get_leader(),
|
self.get_leader(),
|
||||||
self.get_followers(),
|
self.get_followers(),
|
||||||
config_bag,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _reset_cache(
|
def _reset_cache(self,
|
||||||
self,
|
|
||||||
path: str,
|
path: str,
|
||||||
leader: Option,
|
leader: Option,
|
||||||
followers: List[Option],
|
followers: List[Option],
|
||||||
config_bag: "ConfigBag",
|
config_bag: 'ConfigBag',
|
||||||
resetted_opts: List[Option],
|
resetted_opts: List[Option],
|
||||||
) -> None:
|
) -> None:
|
||||||
super().reset_cache(
|
super().reset_cache(path,
|
||||||
path,
|
|
||||||
config_bag,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
)
|
)
|
||||||
leader_path = leader.impl_getpath()
|
leader_path = leader.impl_getpath()
|
||||||
if leader_path not in resetted_opts:
|
if leader_path not in resetted_opts:
|
||||||
leader.reset_cache(
|
leader.reset_cache(leader_path,
|
||||||
leader_path,
|
|
||||||
config_bag,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
)
|
)
|
||||||
for follower in followers:
|
for follower in followers:
|
||||||
follower_path = follower.impl_getpath()
|
follower_path = follower.impl_getpath()
|
||||||
if follower_path not in resetted_opts:
|
if follower_path not in resetted_opts:
|
||||||
follower.reset_cache(
|
follower.reset_cache(follower_path,
|
||||||
follower_path,
|
|
||||||
config_bag,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
def impl_is_leadership(self) -> None:
|
def impl_is_leadership(self) -> None:
|
||||||
return True
|
return True
|
||||||
|
#
|
||||||
|
# def to_dynoption(self,
|
||||||
|
# rootpath: str,
|
||||||
|
# suffixes: Optional[list],
|
||||||
|
# ) -> SynDynLeadership:
|
||||||
|
# return SynDynLeadership(self,
|
||||||
|
# rootpath,
|
||||||
|
# suffixes,
|
||||||
|
# )
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2020-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2020-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,8 +27,8 @@ from .stroption import RegexpOption
|
||||||
|
|
||||||
|
|
||||||
class MACOption(RegexpOption):
|
class MACOption(RegexpOption):
|
||||||
"""represents the choice of a mac address"""
|
"""represents the choice of a mac address
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$")
|
_regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$")
|
||||||
_type = "mac address"
|
_type = _('mac address')
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -26,17 +26,18 @@ from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class NetmaskOption(StrOption):
|
class NetmaskOption(StrOption):
|
||||||
"""represents the choice of a netmask"""
|
"""represents the choice of a netmask
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "netmask address"
|
_type = _('netmask address')
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
for val in value.split("."):
|
for val in value.split('.'):
|
||||||
if val.startswith("0") and len(val) > 1:
|
if val.startswith("0") and len(val) > 1:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
try:
|
try:
|
||||||
ip_network(f"0.0.0.0/{value}")
|
ip_network(f'0.0.0.0/{value}')
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError() from err
|
raise ValueError() from err
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -29,24 +29,30 @@ from .stroption import StrOption
|
||||||
class NetworkOption(StrOption):
|
class NetworkOption(StrOption):
|
||||||
"represents the choice of a network"
|
"represents the choice of a network"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "network address"
|
_type = _('network address')
|
||||||
|
|
||||||
def __init__(self, *args, cidr=False, **kwargs):
|
def __init__(self,
|
||||||
extra = {"_cidr": cidr}
|
*args,
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
cidr=False,
|
||||||
|
**kwargs):
|
||||||
|
extra = {'_cidr': cidr}
|
||||||
|
super().__init__(*args,
|
||||||
|
extra=extra,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if value.count(".") != 3:
|
if value.count('.') != 3:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
cidr = self.impl_get_extra("_cidr")
|
cidr = self.impl_get_extra('_cidr')
|
||||||
if cidr:
|
if cidr:
|
||||||
if "/" not in value:
|
if '/' not in value:
|
||||||
raise ValueError(_("must use CIDR notation"))
|
raise ValueError(_('must use CIDR notation'))
|
||||||
value_ = value.split("/")[0]
|
value_ = value.split('/')[0]
|
||||||
else:
|
else:
|
||||||
value_ = value
|
value_ = value
|
||||||
for val in value_.split("."):
|
for val in value_.split('.'):
|
||||||
if val.startswith("0") and len(val) > 1:
|
if val.startswith("0") and len(val) > 1:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
try:
|
try:
|
||||||
|
@ -54,7 +60,9 @@ class NetworkOption(StrOption):
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError() from err
|
raise ValueError() from err
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
if ip_network(value).network_address.is_reserved:
|
if ip_network(value).network_address.is_reserved:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("shouldn't be reserved network")
|
msg = _("shouldn't be reserved network")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"option types and option description"
|
"option types and option description"
|
||||||
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -26,8 +26,9 @@ from itertools import chain
|
||||||
from .baseoption import BaseOption, submulti
|
from .baseoption import BaseOption, submulti
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..autolib import Calculation
|
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
|
||||||
from ..error import ValueWarning, ValueErrorWarning, ValueOptionError
|
from ..error import ValueWarning, ValueErrorWarning, ValueOptionError
|
||||||
|
from .syndynoption import SynDynOption
|
||||||
|
|
||||||
|
|
||||||
class Option(BaseOption):
|
class Option(BaseOption):
|
||||||
|
@ -37,43 +38,36 @@ class Option(BaseOption):
|
||||||
|
|
||||||
Reminder: an Option object is **not** a container for the value.
|
Reminder: an Option object is **not** a container for the value.
|
||||||
"""
|
"""
|
||||||
__slots__ = (
|
__slots__ = ('_extra',
|
||||||
"_extra",
|
'_warnings_only',
|
||||||
"_warnings_only",
|
|
||||||
# multi
|
# multi
|
||||||
"_multi",
|
'_multi',
|
||||||
# value
|
# value
|
||||||
"_default",
|
'_default',
|
||||||
"_default_multi",
|
'_default_multi',
|
||||||
#
|
#
|
||||||
"_validators",
|
'_validators',
|
||||||
#
|
#
|
||||||
"_leadership",
|
'_dependencies_information',
|
||||||
"_choice_values",
|
'_leadership',
|
||||||
"_choice_values_params",
|
'_choice_values',
|
||||||
|
'_choice_values_params',
|
||||||
)
|
)
|
||||||
_type = None
|
_type = None
|
||||||
|
def __init__(self,
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
default: Any = undefined,
|
default: Any=undefined,
|
||||||
default_multi: Any = None,
|
default_multi: Any=None,
|
||||||
multi: bool = False,
|
multi: bool=False,
|
||||||
validators: Optional[List[Calculation]] = None,
|
validators: Optional[List[Calculation]]=None,
|
||||||
properties: Optional[List[str]] = None,
|
properties: Optional[List[str]]=None,
|
||||||
warnings_only: bool = False,
|
warnings_only: bool=False,
|
||||||
extra: Optional[Dict] = None,
|
extra: Optional[Dict]=None):
|
||||||
informations: Optional[Dict] = None,
|
|
||||||
):
|
|
||||||
_setattr = object.__setattr__
|
_setattr = object.__setattr__
|
||||||
if not multi and default_multi is not None:
|
if not multi and default_multi is not None:
|
||||||
raise ValueError(
|
raise ValueError(_("default_multi is set whereas multi is False"
|
||||||
_(
|
" in option: {0}").format(name))
|
||||||
"default_multi is set whereas multi is False" " in option: {0}"
|
|
||||||
).format(name)
|
|
||||||
)
|
|
||||||
if default is undefined:
|
if default is undefined:
|
||||||
if multi is False:
|
if multi is False:
|
||||||
default = None
|
default = None
|
||||||
|
@ -89,140 +83,152 @@ class Option(BaseOption):
|
||||||
is_multi = True
|
is_multi = True
|
||||||
_multi = submulti
|
_multi = submulti
|
||||||
else:
|
else:
|
||||||
raise ValueError(
|
raise ValueError(_('invalid multi type "{}" for "{}"').format(multi,
|
||||||
_('invalid multi type "{}" for "{}"').format(
|
|
||||||
multi,
|
|
||||||
name,
|
name,
|
||||||
)
|
))
|
||||||
)
|
|
||||||
if _multi != 1:
|
if _multi != 1:
|
||||||
_setattr(self, "_multi", _multi)
|
_setattr(self, '_multi', _multi)
|
||||||
if multi is not False and default is None:
|
if multi is not False and default is None:
|
||||||
default = []
|
default = []
|
||||||
super().__init__(
|
super().__init__(name,
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
informations,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
is_multi=is_multi,
|
is_multi=is_multi)
|
||||||
)
|
|
||||||
if validators is not None:
|
if validators is not None:
|
||||||
if __debug__ and not isinstance(validators, list):
|
if __debug__ and not isinstance(validators, list):
|
||||||
raise ValueError(
|
raise ValueError(_(f'validators must be a list of Calculation for "{name}"'))
|
||||||
_('validators must be a list of Calculation for "{0}"').format(name)
|
|
||||||
)
|
|
||||||
for validator in validators:
|
for validator in validators:
|
||||||
if __debug__ and not isinstance(validator, Calculation):
|
if __debug__ and not isinstance(validator, Calculation):
|
||||||
raise ValueError(
|
raise ValueError(_('validators must be a Calculation for "{}"').format(name))
|
||||||
_('validators must be a Calculation for "{0}"').format(name)
|
|
||||||
)
|
|
||||||
self.value_dependency(validator)
|
self.value_dependency(validator)
|
||||||
self._validators = tuple(validators)
|
self._validators = tuple(validators)
|
||||||
if extra is not None and extra != {}:
|
if extra is not None and extra != {}:
|
||||||
_setattr(self, "_extra", extra)
|
_setattr(self, '_extra', extra)
|
||||||
if warnings_only is True:
|
if warnings_only is True:
|
||||||
_setattr(self, "_warnings_only", warnings_only)
|
_setattr(self, '_warnings_only', warnings_only)
|
||||||
if is_multi and default_multi is not None:
|
if is_multi and default_multi is not None:
|
||||||
|
|
||||||
def test_multi_value(value):
|
def test_multi_value(value):
|
||||||
if isinstance(value, Calculation):
|
if isinstance(value, Calculation):
|
||||||
return
|
return
|
||||||
# option_bag = OptionBag(self,
|
# option_bag = OptionBag(self,
|
||||||
# None,
|
# None,
|
||||||
# undefined,
|
# undefined,
|
||||||
# properties=None,
|
# properties=None,
|
||||||
# )
|
# )
|
||||||
try:
|
try:
|
||||||
self.validate(value)
|
self.validate(value)
|
||||||
self.validate_with_option(
|
self.validate_with_option(value,
|
||||||
value,
|
|
||||||
None,
|
None,
|
||||||
loaded=True,
|
loaded=True,
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
str_err = str(err)
|
str_err = str(err)
|
||||||
if not str_err:
|
if not str_err:
|
||||||
raise ValueError(
|
raise ValueError(_('invalid default_multi value "{0}" '
|
||||||
_(
|
'for option "{1}"').format(str(value),
|
||||||
'invalid default_multi value "{0}" ' "for option {1}"
|
self.impl_get_display_name())
|
||||||
).format(
|
|
||||||
str(value),
|
|
||||||
self.impl_get_display_name(None, with_quote=True),
|
|
||||||
)
|
|
||||||
) from err
|
) from err
|
||||||
raise ValueError(
|
raise ValueError(_(f'invalid default_multi value "{value}" for option '
|
||||||
_(
|
f'"{self.impl_get_display_name()}", {str_err}')
|
||||||
'invalid default_multi value "{0}" for option {1}, {2}'
|
|
||||||
).format(
|
|
||||||
value,
|
|
||||||
self.impl_get_display_name(None, with_quote=True),
|
|
||||||
str_err,
|
|
||||||
)
|
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
if _multi is submulti:
|
if _multi is submulti:
|
||||||
if not isinstance(default_multi, Calculation):
|
if not isinstance(default_multi, Calculation):
|
||||||
if not isinstance(default_multi, list):
|
if not isinstance(default_multi, list):
|
||||||
raise ValueError(
|
raise ValueError(_('invalid default_multi value "{0}" '
|
||||||
_(
|
'for option "{1}", must be a list for a submulti'
|
||||||
'invalid default_multi value "{0}" '
|
'').format(str(default_multi),
|
||||||
"for option {1}, must be a list for a submulti"
|
self.impl_get_display_name()))
|
||||||
""
|
|
||||||
).format(
|
|
||||||
str(default_multi),
|
|
||||||
self.impl_get_display_name(None, with_quote=True),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
for value in default_multi:
|
for value in default_multi:
|
||||||
test_multi_value(value)
|
test_multi_value(value)
|
||||||
else:
|
else:
|
||||||
test_multi_value(default_multi)
|
test_multi_value(default_multi)
|
||||||
_setattr(self, "_default_multi", default_multi)
|
_setattr(self, '_default_multi', default_multi)
|
||||||
# option_bag = OptionBag(self,
|
# option_bag = OptionBag(self,
|
||||||
# None,
|
# None,
|
||||||
# undefined,
|
# undefined,
|
||||||
# properties=None,
|
# properties=None,
|
||||||
# )
|
# )
|
||||||
self.impl_validate(
|
self.impl_validate(None,
|
||||||
None,
|
|
||||||
default,
|
default,
|
||||||
loaded=True,
|
loaded=True,
|
||||||
)
|
)
|
||||||
self.impl_validate(
|
self.impl_validate(None,
|
||||||
None,
|
|
||||||
default,
|
default,
|
||||||
check_error=False,
|
check_error=False,
|
||||||
loaded=True,
|
loaded=True,
|
||||||
)
|
)
|
||||||
self.value_dependencies(default)
|
self.value_dependencies(default)
|
||||||
if (is_multi and default != []) or (not is_multi and default is not None):
|
if (is_multi and default != []) or \
|
||||||
|
(not is_multi and default is not None):
|
||||||
if is_multi and isinstance(default, list):
|
if is_multi and isinstance(default, list):
|
||||||
default = tuple(default)
|
default = tuple(default)
|
||||||
_setattr(self, "_default", default)
|
_setattr(self, '_default', default)
|
||||||
|
|
||||||
# __________________________________________________________________________
|
def value_dependencies(self,
|
||||||
|
value: Any,
|
||||||
|
) -> Any:
|
||||||
|
"""parse dependancies to add dependencies
|
||||||
|
"""
|
||||||
|
if isinstance(value, list):
|
||||||
|
for val in value:
|
||||||
|
if isinstance(value, list):
|
||||||
|
self.value_dependencies(val)
|
||||||
|
elif isinstance(value, Calculation):
|
||||||
|
self.value_dependency(val)
|
||||||
|
elif isinstance(value, Calculation):
|
||||||
|
self.value_dependency(value)
|
||||||
|
|
||||||
|
def value_dependency(self,
|
||||||
|
value: Any,
|
||||||
|
) -> Any:
|
||||||
|
"""parse dependancy to add dependencies
|
||||||
|
"""
|
||||||
|
for param in chain(value.params.args, value.params.kwargs.values()):
|
||||||
|
if isinstance(param, ParamOption):
|
||||||
|
# pylint: disable=protected-access
|
||||||
|
param.option._add_dependency(self)
|
||||||
|
self._has_dependency = True
|
||||||
|
elif isinstance(param, ParamInformation):
|
||||||
|
dest = self
|
||||||
|
if isinstance(param, ParamSelfInformation):
|
||||||
|
opt = self
|
||||||
|
elif param.option:
|
||||||
|
dest = param.option
|
||||||
|
opt = self
|
||||||
|
else:
|
||||||
|
opt = None
|
||||||
|
if not getattr(dest, '_dependencies_information', {}):
|
||||||
|
dest._dependencies_information = {}
|
||||||
|
dest._dependencies_information.setdefault(param.information_name, []).append(opt)
|
||||||
|
|
||||||
|
#__________________________________________________________________________
|
||||||
# option's information
|
# option's information
|
||||||
|
|
||||||
def impl_is_multi(self) -> bool:
|
def impl_is_multi(self) -> bool:
|
||||||
"""is it a multi option"""
|
"""is it a multi option
|
||||||
return getattr(self, "_multi", 1) != 1
|
"""
|
||||||
|
return getattr(self, '_multi', 1) != 1
|
||||||
|
|
||||||
def impl_is_submulti(self) -> bool:
|
def impl_is_submulti(self) -> bool:
|
||||||
"""is it a submulti option"""
|
"""is it a submulti option
|
||||||
return getattr(self, "_multi", 1) == 2
|
"""
|
||||||
|
return getattr(self, '_multi', 1) == 2
|
||||||
|
|
||||||
def impl_is_dynsymlinkoption(self) -> bool:
|
def impl_is_dynsymlinkoption(self) -> bool:
|
||||||
"""is a dynsymlinkoption?"""
|
"""is a dynsymlinkoption?
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_type(self) -> str:
|
def get_type(self) -> str:
|
||||||
"""get the type of option"""
|
"""get the type of option
|
||||||
|
"""
|
||||||
return self._type
|
return self._type
|
||||||
|
|
||||||
def impl_getdefault(self) -> Any:
|
def impl_getdefault(self) -> Any:
|
||||||
"""accessing the default value"""
|
"""accessing the default value
|
||||||
|
"""
|
||||||
is_multi = self.impl_is_multi()
|
is_multi = self.impl_is_multi()
|
||||||
default = getattr(self, "_default", undefined)
|
default = getattr(self, '_default', undefined)
|
||||||
if default is undefined:
|
if default is undefined:
|
||||||
if is_multi:
|
if is_multi:
|
||||||
default = []
|
default = []
|
||||||
|
@ -233,184 +239,160 @@ class Option(BaseOption):
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def impl_getdefault_multi(self) -> Any:
|
def impl_getdefault_multi(self) -> Any:
|
||||||
"""accessing the default value for a multi"""
|
"""accessing the default value for a multi
|
||||||
|
"""
|
||||||
if self.impl_is_submulti():
|
if self.impl_is_submulti():
|
||||||
default_value = []
|
default_value = []
|
||||||
else:
|
else:
|
||||||
default_value = None
|
default_value = None
|
||||||
return getattr(self, "_default_multi", default_value)
|
return getattr(self, '_default_multi', default_value)
|
||||||
|
|
||||||
def impl_get_extra(
|
def impl_get_extra(self,
|
||||||
self,
|
|
||||||
key: str,
|
key: str,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""if extra parameters are store get it"""
|
"""if extra parameters are store get it
|
||||||
extra = getattr(self, "_extra", {})
|
"""
|
||||||
|
extra = getattr(self, '_extra', {})
|
||||||
if isinstance(extra, tuple):
|
if isinstance(extra, tuple):
|
||||||
if key in extra[0]:
|
if key in extra[0]:
|
||||||
return extra[1][extra[0].index(key)]
|
return extra[1][extra[0].index(key)]
|
||||||
return None
|
return None
|
||||||
return extra.get(key)
|
return extra.get(key)
|
||||||
|
|
||||||
# __________________________________________________________________________
|
#__________________________________________________________________________
|
||||||
# validator
|
# validator
|
||||||
def impl_validate(
|
def impl_validate(self,
|
||||||
self,
|
|
||||||
subconfig: Optional["SubConfig"],
|
subconfig: Optional["SubConfig"],
|
||||||
value: Any,
|
value: Any,
|
||||||
*,
|
*,
|
||||||
check_error: bool = True,
|
check_error: bool=True,
|
||||||
loaded: bool = False,
|
loaded: bool=False,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Return True if value is really valid
|
"""Return True if value is really valid
|
||||||
If not validate or invalid return it returns False
|
If not validate or invalid return it returns False
|
||||||
"""
|
"""
|
||||||
if (
|
if check_error and subconfig and \
|
||||||
check_error
|
not 'validator' in subconfig.config_bag.properties:
|
||||||
and subconfig
|
|
||||||
and not "validator" in subconfig.config_bag.properties
|
|
||||||
):
|
|
||||||
return False
|
return False
|
||||||
if subconfig:
|
if subconfig:
|
||||||
force_index = subconfig.index
|
force_index = subconfig.index
|
||||||
else:
|
else:
|
||||||
force_index = None
|
force_index = None
|
||||||
is_warnings_only = getattr(self, "_warnings_only", False)
|
is_warnings_only = getattr(self, '_warnings_only', False)
|
||||||
|
|
||||||
def _is_not_unique(value):
|
def _is_not_unique(value):
|
||||||
# if set(value) has not same length than value
|
# if set(value) has not same length than value
|
||||||
if not subconfig or not check_error or "unique" not in subconfig.properties:
|
if not subconfig or not check_error or \
|
||||||
|
'unique' not in subconfig.properties:
|
||||||
return
|
return
|
||||||
lvalue = [val for val in value if val is not None]
|
lvalue = [val for val in value if val is not None]
|
||||||
if len(set(lvalue)) == len(lvalue):
|
if len(set(lvalue)) == len(lvalue):
|
||||||
return
|
return
|
||||||
for idx, val in enumerate(value):
|
for idx, val in enumerate(value):
|
||||||
if val not in value[idx + 1 :]:
|
if val not in value[idx+1:]:
|
||||||
continue
|
continue
|
||||||
raise ValueError(_('the value "{}" is not unique' "").format(val))
|
raise ValueError(_('the value "{}" is not unique'
|
||||||
|
'').format(val))
|
||||||
|
|
||||||
def calculation_validator(
|
def calculation_validator(val,
|
||||||
val,
|
|
||||||
_index,
|
_index,
|
||||||
):
|
):
|
||||||
for validator in getattr(self, "_validators", []):
|
for validator in getattr(self, '_validators', []):
|
||||||
calc_is_warnings_only = (
|
calc_is_warnings_only = hasattr(validator, 'warnings_only') and \
|
||||||
hasattr(validator, "warnings_only") and validator.warnings_only
|
validator.warnings_only
|
||||||
)
|
if ((check_error and not calc_is_warnings_only) or
|
||||||
if (check_error and not calc_is_warnings_only) or (
|
(not check_error and calc_is_warnings_only)):
|
||||||
not check_error and calc_is_warnings_only
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
kwargs = {
|
kwargs = {'allow_value_error': True,
|
||||||
"allow_value_error": True,
|
'force_value_warning': calc_is_warnings_only,
|
||||||
"force_value_warning": calc_is_warnings_only,
|
|
||||||
}
|
}
|
||||||
if _index is not None and subconfig.index == _index:
|
if _index is not None and subconfig.index == _index:
|
||||||
lsubconfig = subconfig
|
lsubconfig = subconfig
|
||||||
else:
|
else:
|
||||||
identifier = subconfig.identifiers
|
suffix = subconfig.suffixes
|
||||||
if identifier is not None:
|
if suffix is not None:
|
||||||
identifier = identifier[-1]
|
suffix = suffix[-1]
|
||||||
lsubconfig = subconfig.parent.get_child(
|
lsubconfig = subconfig.parent.get_child(subconfig.option,
|
||||||
subconfig.option,
|
|
||||||
_index,
|
_index,
|
||||||
False,
|
False,
|
||||||
properties=subconfig.properties,
|
properties=subconfig.properties,
|
||||||
identifier=identifier,
|
suffix=suffix,
|
||||||
name=subconfig.path.rsplit(".", 1)[-1],
|
name=subconfig.path.rsplit('.', 1)[-1],
|
||||||
check_index=False,
|
check_index=False,
|
||||||
)
|
)
|
||||||
kwargs["orig_value"] = value
|
kwargs['orig_value'] = value
|
||||||
|
|
||||||
validator.execute(
|
validator.execute(lsubconfig,
|
||||||
lsubconfig,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
)
|
)
|
||||||
except ValueWarning as warn:
|
except ValueWarning as warn:
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(ValueWarning(val,
|
||||||
ValueWarning(
|
self.get_type(),
|
||||||
subconfig,
|
|
||||||
val,
|
|
||||||
_(self.get_type()),
|
|
||||||
self,
|
self,
|
||||||
str(warn),
|
str(warn),
|
||||||
_index,
|
_index,
|
||||||
),
|
),
|
||||||
ValueWarning,
|
ValueWarning,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__, 319)
|
||||||
319,
|
|
||||||
)
|
|
||||||
|
|
||||||
def do_validation(
|
def do_validation(_value,
|
||||||
_value,
|
|
||||||
_index,
|
_index,
|
||||||
):
|
):
|
||||||
#
|
#
|
||||||
if _value is None:
|
if _value is None:
|
||||||
return
|
return
|
||||||
if isinstance(_value, list):
|
if isinstance(_value, list):
|
||||||
raise ValueError(_("which must not be a list"))
|
raise ValueError(_('which must not be a list').format(_value,
|
||||||
|
self.impl_get_display_name()),
|
||||||
|
)
|
||||||
if isinstance(_value, Calculation) and not subconfig:
|
if isinstance(_value, Calculation) and not subconfig:
|
||||||
return
|
return
|
||||||
# option validation
|
# option validation
|
||||||
if check_error:
|
if check_error:
|
||||||
self.validate(_value)
|
self.validate(_value)
|
||||||
self.validate_with_option(
|
self.validate_with_option(_value,
|
||||||
_value,
|
|
||||||
subconfig,
|
subconfig,
|
||||||
loaded=loaded,
|
loaded=loaded,
|
||||||
)
|
)
|
||||||
# second level validation
|
# second level validation
|
||||||
if (check_error and not is_warnings_only) or (
|
if (check_error and not is_warnings_only) or (not check_error and is_warnings_only):
|
||||||
not check_error and is_warnings_only
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
self.second_level_validation(_value, is_warnings_only)
|
self.second_level_validation(_value,
|
||||||
|
is_warnings_only)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if is_warnings_only:
|
if is_warnings_only:
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(ValueWarning(_value,
|
||||||
ValueWarning(
|
self.get_type(),
|
||||||
subconfig,
|
|
||||||
_value,
|
|
||||||
_(self.get_type()),
|
|
||||||
self,
|
self,
|
||||||
str(err),
|
str(err),
|
||||||
_index,
|
_index),
|
||||||
),
|
|
||||||
ValueWarning,
|
ValueWarning,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__, 0)
|
||||||
0,
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
raise err from err
|
raise err from err
|
||||||
# ?
|
# ?
|
||||||
if not loaded:
|
if not loaded:
|
||||||
calculation_validator(
|
calculation_validator(_value,
|
||||||
_value,
|
|
||||||
_index,
|
_index,
|
||||||
)
|
)
|
||||||
|
|
||||||
val = value
|
val = value
|
||||||
err_index = force_index
|
err_index = force_index
|
||||||
try:
|
try:
|
||||||
if not self.impl_is_multi():
|
if not self.impl_is_multi():
|
||||||
do_validation(
|
do_validation(val,
|
||||||
val,
|
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
elif force_index is not None:
|
elif force_index is not None:
|
||||||
if self.impl_is_submulti():
|
if self.impl_is_submulti():
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
raise ValueError(_("which must be a list"))
|
raise ValueError(_('which must be a list'))
|
||||||
for val in value:
|
for val in value:
|
||||||
do_validation(
|
do_validation(val,
|
||||||
val,
|
|
||||||
force_index,
|
force_index,
|
||||||
)
|
)
|
||||||
_is_not_unique(value)
|
_is_not_unique(value)
|
||||||
else:
|
else:
|
||||||
do_validation(
|
do_validation(val,
|
||||||
val,
|
|
||||||
force_index,
|
force_index,
|
||||||
)
|
)
|
||||||
elif isinstance(value, Calculation) and not subconfig:
|
elif isinstance(value, Calculation) and not subconfig:
|
||||||
|
@ -420,79 +402,91 @@ class Option(BaseOption):
|
||||||
if isinstance(lval, Calculation):
|
if isinstance(lval, Calculation):
|
||||||
continue
|
continue
|
||||||
if not isinstance(lval, list):
|
if not isinstance(lval, list):
|
||||||
raise ValueError(
|
raise ValueError(_('which "{}" must be a list of list'
|
||||||
_('which "{}" must be a list of list' "").format(lval)
|
'').format(lval))
|
||||||
)
|
|
||||||
for val in lval:
|
for val in lval:
|
||||||
do_validation(val, err_index)
|
do_validation(val,
|
||||||
|
err_index)
|
||||||
_is_not_unique(lval)
|
_is_not_unique(lval)
|
||||||
elif not isinstance(value, list):
|
elif not isinstance(value, list):
|
||||||
raise ValueError(_("which must be a list"))
|
raise ValueError(_('which must be a list'))
|
||||||
else:
|
else:
|
||||||
# FIXME suboptimal, not several time for whole=True!
|
# FIXME suboptimal, not several time for whole=True!
|
||||||
for err_index, val in enumerate(value):
|
for err_index, val in enumerate(value):
|
||||||
do_validation(
|
do_validation(val,
|
||||||
val,
|
|
||||||
err_index,
|
err_index,
|
||||||
)
|
)
|
||||||
_is_not_unique(value)
|
_is_not_unique(value)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if (
|
if not subconfig or \
|
||||||
not subconfig
|
'demoting_error_warning' not in subconfig.config_bag.properties:
|
||||||
or "demoting_error_warning" not in subconfig.config_bag.properties
|
raise ValueOptionError(val,
|
||||||
):
|
self.get_type(),
|
||||||
raise ValueOptionError(
|
self,
|
||||||
subconfig, val, _(self.get_type()), self, str(err), err_index
|
str(err),
|
||||||
) from err
|
err_index) from err
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(ValueErrorWarning(val,
|
||||||
ValueErrorWarning(
|
self.get_type(),
|
||||||
subconfig, val, _(self.get_type()), self, str(err), err_index
|
self,
|
||||||
),
|
str(err),
|
||||||
|
err_index),
|
||||||
ValueErrorWarning,
|
ValueErrorWarning,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__, 0)
|
||||||
0,
|
|
||||||
)
|
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def validate_with_option(
|
def validate_with_option(self,
|
||||||
self,
|
|
||||||
value: Any,
|
value: Any,
|
||||||
subconfig: "SubConfig",
|
subconfig: "SubConfig",
|
||||||
*,
|
*,
|
||||||
loaded: bool,
|
loaded: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validation function with option"""
|
"""validation function with option
|
||||||
|
"""
|
||||||
|
|
||||||
def second_level_validation(
|
def second_level_validation(self,
|
||||||
self,
|
|
||||||
value: Any,
|
value: Any,
|
||||||
warnings_only: bool,
|
warnings_only: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""less import validation function"""
|
"""less import validation function
|
||||||
|
"""
|
||||||
|
|
||||||
def impl_is_leader(self):
|
def impl_is_leader(self):
|
||||||
"""check if option is a leader in a leadership"""
|
"""check if option is a leader in a leadership
|
||||||
|
"""
|
||||||
leadership = self.impl_get_leadership()
|
leadership = self.impl_get_leadership()
|
||||||
if leadership is None:
|
if leadership is None:
|
||||||
return False
|
return False
|
||||||
return leadership.is_leader(self)
|
return leadership.is_leader(self)
|
||||||
|
|
||||||
def impl_is_follower(self):
|
def impl_is_follower(self):
|
||||||
"""check if option is a leader in a follower"""
|
"""check if option is a leader in a follower
|
||||||
|
"""
|
||||||
leadership = self.impl_get_leadership()
|
leadership = self.impl_get_leadership()
|
||||||
if leadership is None:
|
if leadership is None:
|
||||||
return False
|
return False
|
||||||
return not leadership.is_leader(self)
|
return not leadership.is_leader(self)
|
||||||
|
|
||||||
def impl_get_leadership(self):
|
def impl_get_leadership(self):
|
||||||
"""get leadership"""
|
"""get leadership
|
||||||
leadership = getattr(self, "_leadership", None)
|
"""
|
||||||
|
leadership = getattr(self, '_leadership', None)
|
||||||
if leadership is None:
|
if leadership is None:
|
||||||
return leadership
|
return leadership
|
||||||
# pylint: disable=not-callable
|
#pylint: disable=not-callable
|
||||||
return leadership()
|
return leadership()
|
||||||
|
|
||||||
|
def to_dynoption(self,
|
||||||
|
rootpath: str,
|
||||||
|
suffixes: list[str],
|
||||||
|
) -> SynDynOption:
|
||||||
|
"""tranforme a dynoption to a syndynoption
|
||||||
|
"""
|
||||||
|
return SynDynOption(self,
|
||||||
|
rootpath,
|
||||||
|
suffixes,
|
||||||
|
)
|
||||||
def validate(self, value: Any):
|
def validate(self, value: Any):
|
||||||
"""option needs a validate function"""
|
"""option needs a validate function
|
||||||
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -21,40 +21,39 @@
|
||||||
"""OptionDescription
|
"""OptionDescription
|
||||||
"""
|
"""
|
||||||
import weakref
|
import weakref
|
||||||
from typing import Optional, Iterator, Union, List, Dict
|
from typing import Optional, Iterator, Union, List
|
||||||
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import ConfigBag, groups, undefined, owners, Undefined
|
from ..setting import ConfigBag, groups, undefined, owners, Undefined
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
|
|
||||||
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
|
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
|
||||||
from ..error import ConfigError, ConflictError
|
from ..error import ConfigError, ConflictError
|
||||||
|
|
||||||
|
|
||||||
class CacheOptionDescription(BaseOption):
|
class CacheOptionDescription(BaseOption):
|
||||||
"""manage cache for option description"""
|
"""manage cache for option description
|
||||||
|
"""
|
||||||
__slots__ = (
|
__slots__ = ('_cache_force_store_values',
|
||||||
"_cache_force_store_values",
|
'_cache_dependencies_information',
|
||||||
"_cache_dependencies_information",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def impl_already_build_caches(self) -> bool:
|
def impl_already_build_caches(self) -> bool:
|
||||||
"""is a readonly option?"""
|
"""is a readonly option?
|
||||||
|
"""
|
||||||
return self.impl_is_readonly()
|
return self.impl_is_readonly()
|
||||||
|
|
||||||
def _build_cache(
|
def _build_cache(self,
|
||||||
self,
|
|
||||||
display_name,
|
display_name,
|
||||||
_consistencies=None,
|
_consistencies=None,
|
||||||
_consistencies_id=0,
|
_consistencies_id=0,
|
||||||
currpath: List[str] = None,
|
currpath: List[str]=None,
|
||||||
cache_option=None,
|
cache_option=None,
|
||||||
force_store_values=None,
|
force_store_values=None,
|
||||||
dependencies_information=None,
|
dependencies_information=None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validate options and set option has readonly option"""
|
"""validate options and set option has readonly option
|
||||||
|
"""
|
||||||
# pylint: disable=too-many-branches,too-many-arguments
|
# pylint: disable=too-many-branches,too-many-arguments
|
||||||
# _consistencies is None only when we start to build cache
|
# _consistencies is None only when we start to build cache
|
||||||
if _consistencies is None:
|
if _consistencies is None:
|
||||||
|
@ -70,18 +69,16 @@ class CacheOptionDescription(BaseOption):
|
||||||
|
|
||||||
if self.impl_is_readonly():
|
if self.impl_is_readonly():
|
||||||
# cache already set
|
# cache already set
|
||||||
raise ConfigError(
|
raise ConfigError(_('option description seems to be part of an other '
|
||||||
_("option description seems to be part of an other " "config")
|
'config'))
|
||||||
)
|
|
||||||
for option in self.get_children():
|
for option in self.get_children():
|
||||||
if __debug__:
|
if __debug__:
|
||||||
cache_option.append(option)
|
cache_option.append(option)
|
||||||
sub_currpath = currpath + [option.impl_getname()]
|
sub_currpath = currpath + [option.impl_getname()]
|
||||||
subpath = ".".join(sub_currpath)
|
subpath = '.'.join(sub_currpath)
|
||||||
if isinstance(option, OptionDescription):
|
if isinstance(option, OptionDescription):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
option._build_cache(
|
option._build_cache(display_name,
|
||||||
display_name,
|
|
||||||
_consistencies,
|
_consistencies,
|
||||||
_consistencies_id,
|
_consistencies_id,
|
||||||
sub_currpath,
|
sub_currpath,
|
||||||
|
@ -89,177 +86,129 @@ class CacheOptionDescription(BaseOption):
|
||||||
force_store_values,
|
force_store_values,
|
||||||
dependencies_information,
|
dependencies_information,
|
||||||
)
|
)
|
||||||
elif not option.impl_is_symlinkoption():
|
else:
|
||||||
informations = option.get_dependencies_information()
|
for information, options in option.get_dependencies_information().items():
|
||||||
if informations:
|
|
||||||
for param in informations.pop(None):
|
|
||||||
del param.self_option
|
|
||||||
for (
|
|
||||||
information,
|
|
||||||
options,
|
|
||||||
) in option.get_dependencies_information().items():
|
|
||||||
if None in options:
|
if None in options:
|
||||||
dependencies_information.setdefault(information, []).append(
|
dependencies_information.setdefault(information, []).append(option)
|
||||||
option
|
if not option.impl_is_symlinkoption():
|
||||||
)
|
|
||||||
properties = option.impl_getproperties()
|
properties = option.impl_getproperties()
|
||||||
if "force_store_value" in properties:
|
if 'force_store_value' in properties:
|
||||||
force_store_values.append(option)
|
force_store_values.append(option)
|
||||||
if option.impl_is_readonly():
|
if option.impl_is_readonly():
|
||||||
raise ConflictError(_("duplicate option: {0}").format(option))
|
raise ConflictError(_('duplicate option: {0}').format(option))
|
||||||
if not self.impl_is_readonly() and display_name:
|
if not self.impl_is_readonly() and display_name:
|
||||||
option._display_name_function = (
|
option._display_name_function = display_name # pylint: disable=protected-access
|
||||||
display_name # pylint: disable=protected-access
|
|
||||||
)
|
|
||||||
option._path = subpath # pylint: disable=protected-access
|
option._path = subpath # pylint: disable=protected-access
|
||||||
option._set_readonly() # pylint: disable=protected-access
|
option._set_readonly() # pylint: disable=protected-access
|
||||||
if init:
|
if init:
|
||||||
self._cache_force_store_values = (
|
self._cache_force_store_values = force_store_values # pylint: disable=attribute-defined-outside-init
|
||||||
force_store_values # pylint: disable=attribute-defined-outside-init
|
|
||||||
)
|
|
||||||
self._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init
|
self._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init
|
||||||
self._path = (
|
self._path = None # pylint: disable=attribute-defined-outside-init,no-member
|
||||||
None # pylint: disable=attribute-defined-outside-init,no-member
|
|
||||||
)
|
|
||||||
self._set_readonly()
|
self._set_readonly()
|
||||||
|
#
|
||||||
def impl_build_force_store_values(
|
# def impl_build_force_store_values(self,
|
||||||
self,
|
# config_bag: ConfigBag,
|
||||||
config_bag: ConfigBag,
|
# ) -> None:
|
||||||
) -> None:
|
# """set value to force_store_values option
|
||||||
"""set value to force_store_values option"""
|
# """
|
||||||
# pylint: disable=too-many-branches
|
# # pylint: disable=too-many-branches
|
||||||
context = config_bag.context
|
# def do_option_bags(option):
|
||||||
if "force_store_value" not in config_bag.properties:
|
# if option.issubdyn():
|
||||||
return
|
# dynopt = option.getsubdyn()
|
||||||
|
# yield from dynopt.get_sub_children(option,
|
||||||
values = config_bag.context.get_values()
|
# config_bag,
|
||||||
for option in self._cache_force_store_values:
|
# index=None,
|
||||||
if option.issubdyn():
|
# )
|
||||||
paths = option.impl_getpath().split(".")
|
# else:
|
||||||
parents = [config_bag.context.get_root(config_bag)]
|
# yield OptionBag(option,
|
||||||
for name in paths:
|
# None,
|
||||||
new_parents = []
|
# config_bag,
|
||||||
for parent in parents:
|
# properties=None,
|
||||||
doption = parent.option.get_child(
|
# )
|
||||||
name,
|
# if 'force_store_value' not in config_bag.properties:
|
||||||
config_bag,
|
# return
|
||||||
parent,
|
# values = config_bag.context.get_values()
|
||||||
allow_dynoption=True,
|
# for option in self._cache_force_store_values:
|
||||||
)
|
# if option.impl_is_follower():
|
||||||
if doption.impl_is_dynoptiondescription():
|
# leader = option.impl_get_leadership().get_leader()
|
||||||
new_parents.extend(
|
# for leader_option_bag in do_option_bags(leader):
|
||||||
parent.dyn_to_subconfig(
|
# leader_option_bag.properties = frozenset()
|
||||||
doption,
|
# follower_len = len(values.get_value(leader_option_bag)[0])
|
||||||
True,
|
# if option.issubdyn():
|
||||||
)
|
# doption = option.to_dynoption(leader_option_bag.option.rootpath,
|
||||||
)
|
# leader_option_bag.option.get_current_suffixes(),
|
||||||
else:
|
# )
|
||||||
new_parents.append(
|
# else:
|
||||||
parent.get_child(
|
# doption = option
|
||||||
doption,
|
# subpath = doption.impl_getpath()
|
||||||
None,
|
# for index in range(follower_len):
|
||||||
True,
|
# option_bag = OptionBag(doption,
|
||||||
name=name,
|
# index,
|
||||||
)
|
# config_bag,
|
||||||
)
|
# properties=frozenset(),
|
||||||
parents = new_parents
|
# )
|
||||||
subconfigs = new_parents
|
# if values.hasvalue(subpath, index=index):
|
||||||
else:
|
# continue
|
||||||
subconfigs = [
|
# value = values.get_value(option_bag)[0]
|
||||||
context.get_sub_config(
|
# if value is None:
|
||||||
config_bag,
|
# continue
|
||||||
option.impl_getpath(),
|
# values.set_storage_value(subpath,
|
||||||
None,
|
# index,
|
||||||
properties=None,
|
# value,
|
||||||
validate_properties=False,
|
# owners.forced,
|
||||||
)
|
# )
|
||||||
]
|
# else:
|
||||||
|
# for option_bag in do_option_bags(option):
|
||||||
if option.impl_is_follower():
|
# option_bag.properties = frozenset()
|
||||||
for follower_subconfig in subconfigs:
|
# value = values.get_value(option_bag)[0]
|
||||||
parent = follower_subconfig.parent
|
# if value is None:
|
||||||
follower_len = parent.get_length_leadership()
|
# continue
|
||||||
for index in range(follower_len):
|
# if values.hasvalue(option_bag.path):
|
||||||
if values.hasvalue(
|
# continue
|
||||||
follower_subconfig.path,
|
# values.set_storage_value(option_bag.path,
|
||||||
index=index,
|
# None,
|
||||||
):
|
# value,
|
||||||
continue
|
# owners.forced,
|
||||||
idx_follower_subconfig = parent.get_child(
|
# )
|
||||||
follower_subconfig.option,
|
|
||||||
index,
|
|
||||||
validate_properties=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
value = values.get_value(idx_follower_subconfig)[0]
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
values.set_storage_value(
|
|
||||||
follower_subconfig.path,
|
|
||||||
index,
|
|
||||||
value,
|
|
||||||
owners.forced,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
for subconfig in subconfigs:
|
|
||||||
subconfig.properties = frozenset()
|
|
||||||
value = values.get_value(subconfig)[0]
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
if values.hasvalue(subconfig.path):
|
|
||||||
continue
|
|
||||||
values.set_storage_value(
|
|
||||||
subconfig.path,
|
|
||||||
None,
|
|
||||||
value,
|
|
||||||
owners.forced,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class OptionDescriptionWalk(CacheOptionDescription):
|
class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
"""get child of option description"""
|
"""get child of option description
|
||||||
|
"""
|
||||||
|
__slots__ = ('_children',)
|
||||||
|
|
||||||
__slots__ = ("_children",)
|
def get_path(self,
|
||||||
|
|
||||||
def get_path(
|
|
||||||
self,
|
|
||||||
config_bag,
|
config_bag,
|
||||||
):
|
):
|
||||||
if config_bag is undefined or config_bag.context.get_description() == self:
|
if config_bag is undefined or \
|
||||||
return ""
|
config_bag.context.get_description() == self:
|
||||||
|
return ''
|
||||||
return self.impl_getpath()
|
return self.impl_getpath()
|
||||||
|
|
||||||
def get_child_not_dynamic(
|
def get_child_not_dynamic(self,
|
||||||
self,
|
|
||||||
name,
|
name,
|
||||||
allow_dynoption,
|
allow_dynoption,
|
||||||
):
|
):
|
||||||
if name in self._children[0]: # pylint: disable=no-member
|
if name in self._children[0]: # pylint: disable=no-member
|
||||||
option = self._children[1][
|
option = self._children[1][self._children[0].index(name)] # pylint: disable=no-member
|
||||||
self._children[0].index(name)
|
|
||||||
] # pylint: disable=no-member
|
|
||||||
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
||||||
raise AttributeError(
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
_(
|
"in root optiondescription (it's a dynamic option)"
|
||||||
'unknown option "{0}" in root optiondescription (it\'s a dynamic option)'
|
))
|
||||||
).format(name)
|
|
||||||
)
|
|
||||||
return option
|
return option
|
||||||
|
|
||||||
def get_child(
|
def get_child(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
config_bag: ConfigBag,
|
config_bag: ConfigBag,
|
||||||
parent: "SubConfig",
|
parent: 'SubConfig',
|
||||||
*,
|
*,
|
||||||
with_identifier: bool = False,
|
with_suffix: bool=False,
|
||||||
allow_dynoption: bool = False,
|
allow_dynoption: bool=False,
|
||||||
) -> Union[BaseOption]:
|
) -> Union[BaseOption]:
|
||||||
"""get a child"""
|
"""get a child
|
||||||
|
"""
|
||||||
# if not dyn
|
# if not dyn
|
||||||
option = self.get_child_not_dynamic(
|
option = self.get_child_not_dynamic(name,
|
||||||
name,
|
|
||||||
allow_dynoption,
|
allow_dynoption,
|
||||||
)
|
)
|
||||||
if option:
|
if option:
|
||||||
|
@ -268,49 +217,54 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
for child in self._children[1]: # pylint: disable=no-member
|
for child in self._children[1]: # pylint: disable=no-member
|
||||||
if not child.impl_is_dynoptiondescription():
|
if not child.impl_is_dynoptiondescription():
|
||||||
continue
|
continue
|
||||||
for identifier in child.get_identifiers(parent):
|
for suffix in child.get_suffixes(parent):
|
||||||
if name != child.impl_getname(identifier):
|
if name != child.impl_getname(suffix):
|
||||||
continue
|
continue
|
||||||
if not with_identifier:
|
if not with_suffix:
|
||||||
return child
|
return child
|
||||||
return identifier, child
|
return suffix, child
|
||||||
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
|
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
|
||||||
raise AttributeError(
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
_('unknown option "{0}" in root optiondescription').format(name)
|
'in root optiondescription'
|
||||||
)
|
))
|
||||||
raise AttributeError(
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
_('unknown option "{0}" in optiondescription {1}').format(
|
f'in optiondescription "{self.impl_get_display_name()}"'
|
||||||
name, self.impl_get_display_name(parent, with_quote=True)
|
))
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_children(self) -> List[BaseOption]:
|
def get_children(self) -> List[BaseOption]:
|
||||||
"""get children"""
|
"""get children
|
||||||
|
"""
|
||||||
return self._children[1]
|
return self._children[1]
|
||||||
|
# for child in self._children[1]:
|
||||||
|
# if config_bag is not undefined and child.impl_is_dynoptiondescription():
|
||||||
|
# yield from self.get_suffixed_children([],
|
||||||
|
# config_bag,
|
||||||
|
# child,
|
||||||
|
# )
|
||||||
|
# else:
|
||||||
|
# yield child
|
||||||
|
|
||||||
def get_children_recursively(
|
def get_children_recursively(self,
|
||||||
self,
|
|
||||||
bytype: Optional[BaseOption],
|
bytype: Optional[BaseOption],
|
||||||
byname: Optional[str],
|
byname: Optional[str],
|
||||||
config_bag: ConfigBag,
|
config_bag: ConfigBag,
|
||||||
self_opt: BaseOption = None,
|
self_opt: BaseOption=None,
|
||||||
*,
|
*,
|
||||||
option_identifiers: Optional[list] = None,
|
option_suffixes: Optional[list]=None
|
||||||
) -> Iterator[Union[BaseOption]]:
|
) -> Iterator[Union[BaseOption]]:
|
||||||
"""get children recursively"""
|
"""get children recursively
|
||||||
|
"""
|
||||||
if self_opt is None:
|
if self_opt is None:
|
||||||
self_opt = self
|
self_opt = self
|
||||||
for option in self_opt.get_children():
|
for option in self_opt.get_children():
|
||||||
if option.impl_is_optiondescription():
|
if option.impl_is_optiondescription():
|
||||||
for subopt in option.get_children_recursively(
|
for subopt in option.get_children_recursively(bytype,
|
||||||
bytype,
|
|
||||||
byname,
|
byname,
|
||||||
config_bag,
|
config_bag,
|
||||||
):
|
):
|
||||||
yield subopt
|
yield subopt
|
||||||
elif (byname is None or option.impl_getname() == byname) and (
|
elif (byname is None or option.impl_getname() == byname) and \
|
||||||
bytype is None or isinstance(option, bytype)
|
(bytype is None or isinstance(option, bytype)):
|
||||||
):
|
|
||||||
yield option
|
yield option
|
||||||
|
|
||||||
|
|
||||||
|
@ -318,32 +272,22 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
"""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__ = ('_group_type',)
|
||||||
|
|
||||||
__slots__ = ("_group_type",)
|
def __init__(self,
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
*,
|
properties=None) -> None:
|
||||||
properties=None,
|
|
||||||
informations: Optional[Dict] = None,
|
|
||||||
group_type: Optional[groups.GroupType] = groups.default,
|
|
||||||
) -> None:
|
|
||||||
"""
|
"""
|
||||||
:param children: a list of options (including optiondescriptions)
|
:param children: a list of options (including optiondescriptions)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
assert isinstance(children, list), _(
|
assert isinstance(children, list), _('children in optiondescription "{}" '
|
||||||
'children in optiondescription "{}" ' "must be a list"
|
'must be a list').format(name)
|
||||||
).format(name)
|
super().__init__(name,
|
||||||
super().__init__(
|
doc=doc,
|
||||||
name,
|
properties=properties)
|
||||||
doc,
|
|
||||||
informations,
|
|
||||||
properties=properties,
|
|
||||||
)
|
|
||||||
child_names = []
|
child_names = []
|
||||||
if __debug__:
|
if __debug__:
|
||||||
dynopt_names = []
|
dynopt_names = []
|
||||||
|
@ -362,25 +306,19 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
old = None
|
old = None
|
||||||
for child in child_names:
|
for child in child_names:
|
||||||
if child == old:
|
if child == old:
|
||||||
raise ConflictError(
|
raise ConflictError(_('duplicate option name: '
|
||||||
_("duplicate option name: " '"{0}"').format(child)
|
'"{0}"').format(child))
|
||||||
)
|
|
||||||
if dynopt_names:
|
if dynopt_names:
|
||||||
for dynopt in dynopt_names:
|
for dynopt in dynopt_names:
|
||||||
if child != dynopt and child.startswith(dynopt):
|
if child != dynopt and child.startswith(dynopt):
|
||||||
raise ConflictError(
|
raise ConflictError(_(f'the option\'s name "{child}" start as '
|
||||||
_(
|
f'the dynoptiondescription\'s name "{dynopt}"'))
|
||||||
'the option\'s name "{0}" start as the dynoptiondescription\'s name "{1}"'
|
|
||||||
).format(child, dynopt)
|
|
||||||
)
|
|
||||||
old = child
|
old = child
|
||||||
self._children = children_
|
self._children = children_
|
||||||
# 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 = None
|
self._group_type = groups.default
|
||||||
self.impl_set_group_type(group_type)
|
|
||||||
|
|
||||||
def _setsubdyn(
|
def _setsubdyn(self,
|
||||||
self,
|
|
||||||
subdyn,
|
subdyn,
|
||||||
) -> None:
|
) -> None:
|
||||||
for child in self._children[1]:
|
for child in self._children[1]:
|
||||||
|
@ -388,20 +326,22 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
super()._setsubdyn(subdyn)
|
super()._setsubdyn(subdyn)
|
||||||
|
|
||||||
def impl_is_optiondescription(self) -> bool:
|
def impl_is_optiondescription(self) -> bool:
|
||||||
"""the option is an option description"""
|
"""the option is an option description
|
||||||
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def impl_is_dynoptiondescription(self) -> bool:
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
"""the option is not dynamic"""
|
"""the option is not dynamic
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def impl_is_leadership(self) -> bool:
|
def impl_is_leadership(self) -> bool:
|
||||||
"""the option is not a leadership"""
|
"""the option is not a leadership
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
def impl_set_group_type(
|
def impl_set_group_type(self,
|
||||||
self,
|
|
||||||
group_type: groups.GroupType,
|
group_type: groups.GroupType,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""sets a given group object to an OptionDescription
|
"""sets a given group object to an OptionDescription
|
||||||
|
@ -410,24 +350,39 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
that lives in `setting.groups`
|
that lives in `setting.groups`
|
||||||
"""
|
"""
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if self._group_type is not None and self._group_type != groups.default:
|
if self._group_type != groups.default:
|
||||||
raise ValueError(
|
raise ValueError(_('cannot change group_type if already set '
|
||||||
_(
|
'(old {0}, new {1})').format(self._group_type,
|
||||||
"cannot change group_type if already set " "(old {0}, new {1})"
|
group_type))
|
||||||
).format(self._group_type, group_type)
|
|
||||||
)
|
|
||||||
if not isinstance(group_type, groups.GroupType):
|
if not isinstance(group_type, groups.GroupType):
|
||||||
raise ValueError(_("group_type: {0}" " not allowed").format(group_type))
|
raise ValueError(_('group_type: {0}'
|
||||||
|
' not allowed').format(group_type))
|
||||||
if isinstance(group_type, groups.LeadershipGroupType):
|
if isinstance(group_type, groups.LeadershipGroupType):
|
||||||
raise ConfigError(
|
raise ConfigError('please use Leadership object instead of OptionDescription')
|
||||||
"please use Leadership object instead of OptionDescription"
|
|
||||||
)
|
|
||||||
self._group_type = group_type
|
self._group_type = group_type
|
||||||
|
|
||||||
def impl_get_group_type(self) -> groups.GroupType:
|
def impl_get_group_type(self) -> groups.GroupType:
|
||||||
"""get the group type of option description"""
|
"""get the group type of option description
|
||||||
|
"""
|
||||||
return self._group_type
|
return self._group_type
|
||||||
|
#
|
||||||
|
# def to_dynoption(self,
|
||||||
|
# rootpath: str,
|
||||||
|
# suffixes: Optional[list],
|
||||||
|
# #ori_dyn,
|
||||||
|
# ) -> Union[SubDynOptionDescription]:
|
||||||
|
# """get syn dyn option description
|
||||||
|
# """
|
||||||
|
# if self.impl_is_dynoptiondescription():
|
||||||
|
# obj = SynDynOptionDescription
|
||||||
|
# else:
|
||||||
|
# obj = SubDynOptionDescription
|
||||||
|
# return obj(self,
|
||||||
|
# rootpath,
|
||||||
|
# suffixes,
|
||||||
|
# )
|
||||||
|
|
||||||
def impl_is_dynsymlinkoption(self) -> bool:
|
def impl_is_dynsymlinkoption(self) -> bool:
|
||||||
"""option is not a dyn symlink option"""
|
"""option is not a dyn symlink option
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -22,39 +22,11 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..error import display_list
|
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class PasswordOption(StrOption):
|
class PasswordOption(StrOption):
|
||||||
"""represents the choice of a password"""
|
"""represents the choice of a password
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "password"
|
_type = _('password')
|
||||||
|
|
||||||
def __init__(self, *args, min_len=None, max_len=None, forbidden_char=[], **kwargs):
|
|
||||||
extra = {}
|
|
||||||
if min_len is not None:
|
|
||||||
extra["min_len"] = min_len
|
|
||||||
if max_len is not None:
|
|
||||||
extra["max_len"] = max_len
|
|
||||||
if forbidden_char:
|
|
||||||
extra["forbidden_char"] = set(forbidden_char)
|
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
|
||||||
super().validate(value)
|
|
||||||
min_len = self.impl_get_extra("min_len")
|
|
||||||
if min_len and len(value) < min_len:
|
|
||||||
raise ValueError(_("at least {0} characters are required").format(min_len))
|
|
||||||
max_len = self.impl_get_extra("max_len")
|
|
||||||
if max_len and len(value) > max_len:
|
|
||||||
raise ValueError(_("maximum {0} characters required").format(max_len))
|
|
||||||
if self.impl_get_extra("forbidden_char"):
|
|
||||||
forbidden_char = set(value) & self.impl_get_extra("forbidden_char")
|
|
||||||
if forbidden_char:
|
|
||||||
raise ValueError(
|
|
||||||
_("must not have the characters {0}").format(
|
|
||||||
display_list(list(forbidden_char), add_quote=True)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2023-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -33,25 +33,27 @@ class PermissionsOption(IntOption):
|
||||||
If a fourth digit is present to the setuid bit, the setgid bit and the sticky bit attributes.
|
If a fourth digit is present to the setuid bit, the setgid bit and the sticky bit attributes.
|
||||||
This option is an integer value.
|
This option is an integer value.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
perm_re = re.compile(r"^[0-7]{3,4}$")
|
perm_re = re.compile(r"^[0-7]{3,4}$")
|
||||||
_type = "unix file permissions"
|
_type = _('unix file permissions')
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
*args,
|
*args,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
# do not display intoption attributs
|
#do not display intoption attributs
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if not self.perm_re.search(str(value)):
|
if not self.perm_re.search(str(value)):
|
||||||
raise ValueError(_("only 3 or 4 octal digits are allowed"))
|
raise ValueError(_('only 3 or 4 octal digits are allowed'))
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self,
|
||||||
|
value: str,
|
||||||
|
warnings_only: bool) -> None:
|
||||||
old_digit = 7
|
old_digit = 7
|
||||||
str_value = str(value)
|
str_value = str(value)
|
||||||
if len(str_value) == 4:
|
if len(str_value) == 4:
|
||||||
|
@ -60,12 +62,12 @@ class PermissionsOption(IntOption):
|
||||||
new_digit = int(digit)
|
new_digit = int(digit)
|
||||||
if old_digit < new_digit:
|
if old_digit < new_digit:
|
||||||
if idx == 1:
|
if idx == 1:
|
||||||
old = _("user")
|
old = _('user')
|
||||||
new = _("group")
|
new = _('group')
|
||||||
else:
|
else:
|
||||||
old = _("group")
|
old = _('group')
|
||||||
new = _("other")
|
new = _('other')
|
||||||
raise ValueError(_("{0} has more right than {1}").format(new, old))
|
raise ValueError(_(f'{new} has more right than {old}'))
|
||||||
old_digit = new_digit
|
old_digit = new_digit
|
||||||
if str_value == "777":
|
if str_value == '777':
|
||||||
raise ValueError(_("too weak"))
|
raise ValueError(_('too weak'))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -36,64 +36,62 @@ class PortOption(StrOption):
|
||||||
Port number 0 is reserved and can't be used.
|
Port number 0 is reserved and can't be used.
|
||||||
see: http://en.wikipedia.org/wiki/Port_numbers
|
see: http://en.wikipedia.org/wiki/Port_numbers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
port_re = re.compile(r"^[0-9]*$")
|
port_re = re.compile(r"^[0-9]*$")
|
||||||
_type = "port"
|
_port = _('port')
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
*args,
|
*args,
|
||||||
allow_range: bool = False,
|
allow_range: bool=False,
|
||||||
allow_zero: bool = False,
|
allow_zero: bool=False,
|
||||||
allow_wellknown: bool = True,
|
allow_wellknown: bool=True,
|
||||||
allow_registred: bool = True,
|
allow_registred: bool=True,
|
||||||
allow_protocol: bool = False,
|
allow_protocol: bool=False,
|
||||||
allow_private: bool = False,
|
allow_private: bool=False,
|
||||||
**kwargs,
|
**kwargs) -> None:
|
||||||
) -> None:
|
|
||||||
|
|
||||||
extra = {
|
extra = {'_allow_range': allow_range,
|
||||||
"_allow_range": allow_range,
|
'_allow_protocol': allow_protocol,
|
||||||
"_allow_protocol": allow_protocol,
|
'_min_value': None,
|
||||||
"_min_value": None,
|
'_max_value': None,
|
||||||
"_max_value": None,
|
|
||||||
}
|
}
|
||||||
ports_min = [0, 1, 1024, 49152]
|
ports_min = [0, 1, 1024, 49152]
|
||||||
ports_max = [0, 1023, 49151, 65535]
|
ports_max = [0, 1023, 49151, 65535]
|
||||||
is_finally = False
|
is_finally = False
|
||||||
for index, allowed in enumerate(
|
for index, allowed in enumerate([allow_zero,
|
||||||
[allow_zero, allow_wellknown, allow_registred, allow_private]
|
allow_wellknown,
|
||||||
):
|
allow_registred,
|
||||||
if extra["_min_value"] is None:
|
allow_private]):
|
||||||
|
if extra['_min_value'] is None:
|
||||||
if allowed:
|
if allowed:
|
||||||
extra["_min_value"] = ports_min[index]
|
extra['_min_value'] = ports_min[index]
|
||||||
elif not allowed:
|
elif not allowed:
|
||||||
is_finally = True
|
is_finally = True
|
||||||
elif allowed and is_finally:
|
elif allowed and is_finally:
|
||||||
raise ValueError(_("inconsistency in allowed range"))
|
raise ValueError(_('inconsistency in allowed range'))
|
||||||
if allowed:
|
if allowed:
|
||||||
extra["_max_value"] = ports_max[index]
|
extra['_max_value'] = ports_max[index]
|
||||||
|
|
||||||
if extra["_max_value"] is None:
|
if extra['_max_value'] is None:
|
||||||
raise ValueError(_("max value is empty"))
|
raise ValueError(_('max value is empty'))
|
||||||
|
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
super().__init__(*args,
|
||||||
|
extra=extra,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if self.impl_get_extra("_allow_protocol") and (
|
if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or
|
||||||
value.startswith("tcp:") or value.startswith("udp:")
|
value.startswith('udp:')):
|
||||||
):
|
|
||||||
value = [value[4:]]
|
value = [value[4:]]
|
||||||
elif self.impl_get_extra("_allow_range") and ":" in str(value):
|
elif self.impl_get_extra('_allow_range') and ":" in str(value):
|
||||||
value = value.split(":")
|
value = value.split(':')
|
||||||
if len(value) != 2:
|
if len(value) != 2:
|
||||||
raise ValueError(_("range must have two values only"))
|
raise ValueError(_('range must have two values only'))
|
||||||
if not value[0] < value[1]:
|
if not value[0] < value[1]:
|
||||||
raise ValueError(
|
raise ValueError(_('first port in range must be'
|
||||||
_("first port in range must be" " smaller than the second one")
|
' smaller than the second one'))
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
value = [value]
|
value = [value]
|
||||||
|
|
||||||
|
@ -101,29 +99,22 @@ class PortOption(StrOption):
|
||||||
if not self.port_re.search(val):
|
if not self.port_re.search(val):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self,
|
||||||
if self.impl_get_extra("_allow_protocol") and (
|
value: str,
|
||||||
value.startswith("tcp:") or value.startswith("udp:")
|
warnings_only: bool) -> None:
|
||||||
):
|
if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or
|
||||||
|
value.startswith('udp:')):
|
||||||
value = [value[4:]]
|
value = [value[4:]]
|
||||||
elif ":" in value:
|
elif ':' in value:
|
||||||
value = value.split(":")
|
value = value.split(':')
|
||||||
else:
|
else:
|
||||||
value = [value]
|
value = [value]
|
||||||
for val in value:
|
for val in value:
|
||||||
val = int(val)
|
val = int(val)
|
||||||
if (
|
if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'):
|
||||||
not self.impl_get_extra("_min_value")
|
|
||||||
<= val
|
|
||||||
<= self.impl_get_extra("_max_value")
|
|
||||||
):
|
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("should be between {0} and {1}")
|
msg = 'should be between {0} and {1}'
|
||||||
else:
|
else:
|
||||||
msg = _("must be between {0} and {1}")
|
msg = 'must be between {0} and {1}'
|
||||||
raise ValueError(
|
raise ValueError(_(msg).format(self.impl_get_extra('_min_value'),
|
||||||
msg.format(
|
self.impl_get_extra('_max_value')))
|
||||||
self.impl_get_extra("_min_value"),
|
|
||||||
self.impl_get_extra("_max_value"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,31 +27,31 @@ from .option import Option
|
||||||
|
|
||||||
|
|
||||||
class StrOption(Option):
|
class StrOption(Option):
|
||||||
"""represents a string"""
|
"""represents a string
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "string"
|
_type = _('string')
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: str,
|
value: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validation"""
|
"""validation
|
||||||
|
"""
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
|
|
||||||
class RegexpOption(StrOption):
|
class RegexpOption(StrOption):
|
||||||
"""regexp validation, this is base option use to do a custom's one"""
|
"""regexp validation, this is base option use to do a custom's one
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
def validate(
|
def validate(self,
|
||||||
self,
|
|
||||||
value: Any,
|
value: Any,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
"""validation"""
|
"""validation
|
||||||
|
"""
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
match = self._regexp.search(value)
|
match = self._regexp.search(value)
|
||||||
if not match:
|
if not match:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -20,81 +20,78 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"""SymLinkOption link to an other option
|
"""SymLinkOption link to an other option
|
||||||
"""
|
"""
|
||||||
from typing import Any, Optional, Dict
|
from typing import Any
|
||||||
from .baseoption import BaseOption, valid_name
|
from .baseoption import BaseOption, valid_name
|
||||||
from ..error import ConfigError
|
from ..error import ConfigError
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
|
|
||||||
|
|
||||||
class SymLinkOption(BaseOption):
|
class SymLinkOption(BaseOption):
|
||||||
"""SymLinkOption link to an other option"""
|
"""SymLinkOption link to an other option
|
||||||
|
"""
|
||||||
|
__slots__ = ('_opt',)
|
||||||
|
|
||||||
__slots__ = (
|
def __init__(self,
|
||||||
"_opt",
|
|
||||||
"_leadership",
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
opt: BaseOption,
|
opt: BaseOption,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=super-init-not-called
|
# pylint: disable=super-init-not-called
|
||||||
if not valid_name(name):
|
if not valid_name(name):
|
||||||
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||||
if (
|
if not isinstance(opt, BaseOption) or \
|
||||||
not isinstance(opt, BaseOption)
|
opt.impl_is_optiondescription() or \
|
||||||
or opt.impl_is_optiondescription()
|
opt.impl_is_symlinkoption():
|
||||||
or opt.impl_is_symlinkoption()
|
raise ValueError(_('malformed symlinkoption must be an option for symlink {0}'
|
||||||
):
|
'').format(name))
|
||||||
raise ValueError(
|
_setattr = object.__setattr__
|
||||||
_(
|
_setattr(self, '_name', name)
|
||||||
'malformed symlink second parameters must be an option for "{0}", not {1}'
|
_setattr(self, '_opt', opt)
|
||||||
).format(name, opt)
|
|
||||||
)
|
|
||||||
self._name = name
|
|
||||||
self._opt = opt
|
|
||||||
self._leadership = None
|
|
||||||
opt._add_dependency(self)
|
opt._add_dependency(self)
|
||||||
|
|
||||||
def __getattr__(
|
def __getattr__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if name == "_subdyns":
|
if name == '_path':
|
||||||
return None
|
|
||||||
if name == "_path":
|
|
||||||
raise AttributeError()
|
raise AttributeError()
|
||||||
return getattr(self._opt, name)
|
return getattr(self._opt, name)
|
||||||
|
|
||||||
|
def _setsubdyn(self,
|
||||||
|
subdyn,
|
||||||
|
) -> None:
|
||||||
|
raise ConfigError(_('cannot set symlinkoption in a '
|
||||||
|
'dynoptiondescription'))
|
||||||
|
|
||||||
|
def impl_has_dependency(self,
|
||||||
|
self_is_dep: bool=True,
|
||||||
|
) -> bool:
|
||||||
|
"""If self_is_dep is True, it has dependency (self._opt), so return True
|
||||||
|
if self_is_dep is False, cannot has validation or callback, so return False
|
||||||
|
"""
|
||||||
|
return self_is_dep
|
||||||
|
|
||||||
def impl_is_symlinkoption(self) -> bool:
|
def impl_is_symlinkoption(self) -> bool:
|
||||||
"""it's a symlinkoption"""
|
"""it's a symlinkoption
|
||||||
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def impl_is_leader(self) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def impl_is_follower(self):
|
|
||||||
"""check if option is a leader in a follower"""
|
|
||||||
leadership = self._leadership
|
|
||||||
if leadership is None:
|
|
||||||
return False
|
|
||||||
return not leadership().is_leader(self)
|
|
||||||
|
|
||||||
def impl_getopt(self) -> BaseOption:
|
def impl_getopt(self) -> BaseOption:
|
||||||
"""get to linked option"""
|
"""get to linked option
|
||||||
|
"""
|
||||||
return self._opt
|
return self._opt
|
||||||
|
|
||||||
def impl_is_multi(self) -> bool:
|
def issubdyn(self) -> bool:
|
||||||
"""is it a multi?"""
|
"""it's not a sub dyn option
|
||||||
if self._opt.impl_is_multi():
|
"""
|
||||||
return True
|
|
||||||
if self._opt.issubdyn() or self.issubdyn():
|
|
||||||
if self.issubdyn() != self._opt.issubdyn():
|
|
||||||
return self._opt.issubdyn()
|
|
||||||
return self._opt.issubdyn() in self.get_sub_dyns()
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def impl_is_multi(self) -> bool:
|
||||||
|
"""is it a multi?
|
||||||
|
"""
|
||||||
|
if self._opt.issubdyn():
|
||||||
|
return True
|
||||||
|
return self._opt.impl_is_multi()
|
||||||
|
|
||||||
def impl_is_submulti(self) -> bool:
|
def impl_is_submulti(self) -> bool:
|
||||||
"""is it a submulti?"""
|
"""is it a submulti?
|
||||||
|
"""
|
||||||
return self._opt.impl_is_submulti()
|
return self._opt.impl_is_submulti()
|
||||||
|
|
351
tiramisu/option/syndynoption.py
Normal file
351
tiramisu/option/syndynoption.py
Normal file
|
@ -0,0 +1,351 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2017-2024 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 Lesser General Public License as published by the
|
||||||
|
# Free Software Foundation, either version 3 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 Lesser General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# The original `Config` design model is unproudly borrowed from
|
||||||
|
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
|
# the whole pypy projet is under MIT licence
|
||||||
|
# ____________________________________________________________
|
||||||
|
"""SynDynOption internal option, it's an instanciate synoption
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
from typing import Optional, Iterator, Any, List, Tuple
|
||||||
|
|
||||||
|
from .baseoption import BaseOption
|
||||||
|
from ..i18n import _
|
||||||
|
from ..setting import ConfigBag, undefined
|
||||||
|
|
||||||
|
|
||||||
|
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
|
||||||
|
|
||||||
|
|
||||||
|
class CommonDyn:
|
||||||
|
def get_path(self,
|
||||||
|
config_bag,
|
||||||
|
):
|
||||||
|
if config_bag is undefined or \
|
||||||
|
config_bag.context.get_description() == self:
|
||||||
|
return ''
|
||||||
|
return self.impl_getpath()
|
||||||
|
|
||||||
|
def get_suffixes(self,
|
||||||
|
parent: 'SubConfig',
|
||||||
|
) -> List[str]:
|
||||||
|
"""get dynamic suffixes
|
||||||
|
"""
|
||||||
|
subconfig = parent.get_child(self,
|
||||||
|
None,
|
||||||
|
False,
|
||||||
|
properties=None,
|
||||||
|
)
|
||||||
|
values = self._suffixes.execute(subconfig)
|
||||||
|
if values is None:
|
||||||
|
values = []
|
||||||
|
values_ = []
|
||||||
|
if __debug__:
|
||||||
|
if not isinstance(values, list):
|
||||||
|
raise ValueError(_('DynOptionDescription suffixes for '
|
||||||
|
f'option "{self.impl_get_display_name()}", is not '
|
||||||
|
f'a list ({values})'))
|
||||||
|
for val in values:
|
||||||
|
cval = self.convert_suffix_to_path(val)
|
||||||
|
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
|
||||||
|
if __debug__ and cval is not None:
|
||||||
|
raise ValueError(_('invalid suffix "{}" for option "{}"'
|
||||||
|
'').format(cval,
|
||||||
|
self.impl_get_display_name()))
|
||||||
|
else:
|
||||||
|
values_.append(val)
|
||||||
|
if __debug__ and len(values_) > len(set(values_)):
|
||||||
|
raise ValueError(_(f'DynOptionDescription "{self._name}" suffixes return a list with '
|
||||||
|
f'same values "{values_}"'''))
|
||||||
|
return values_
|
||||||
|
|
||||||
|
def split_path(self,
|
||||||
|
option,
|
||||||
|
*,
|
||||||
|
dynoption=None,
|
||||||
|
) -> Tuple[str, str]:
|
||||||
|
"""self.impl_getpath() is something like root.xxx.dynoption_path
|
||||||
|
option.impl_getpath() is something like root.xxx.dynoption_path.sub.path
|
||||||
|
must return ('root.xxx.', '.sub')
|
||||||
|
"""
|
||||||
|
if dynoption is None:
|
||||||
|
self_path = self.impl_getpath()
|
||||||
|
else:
|
||||||
|
self_path = dynoption.impl_getpath()
|
||||||
|
root_path = self_path.rsplit('.', 1)[0] if '.' in self_path else None
|
||||||
|
#
|
||||||
|
if self.option_is_self(option):
|
||||||
|
sub_path = ''
|
||||||
|
else:
|
||||||
|
option_path = option.impl_getpath()
|
||||||
|
if root_path:
|
||||||
|
if isinstance(option, SynDynLeadership):
|
||||||
|
count_root_path = option_path.count('.') - root_path.count('.')
|
||||||
|
root_path = option_path.rsplit('.', count_root_path)[0]
|
||||||
|
root_path += '.'
|
||||||
|
self_number_child = self_path.count('.') + 1
|
||||||
|
option_sub_path = option_path.split('.', self_number_child)[-1]
|
||||||
|
sub_path = '.' + option_sub_path.rsplit('.', 1)[0] if '.' in option_sub_path else ''
|
||||||
|
return root_path, sub_path
|
||||||
|
|
||||||
|
|
||||||
|
class Syn:
|
||||||
|
__slots__ = ('rootpath',
|
||||||
|
'opt',
|
||||||
|
'_current_suffixes',
|
||||||
|
'__weakref__')
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
opt: BaseOption,
|
||||||
|
rootpath: str,
|
||||||
|
suffixes: list,
|
||||||
|
) -> None:
|
||||||
|
self.opt = opt
|
||||||
|
self.rootpath = rootpath
|
||||||
|
self._current_suffixes = suffixes
|
||||||
|
|
||||||
|
def __getattr__(self,
|
||||||
|
name: str,
|
||||||
|
) -> Any:
|
||||||
|
# if not in SynDynOptionDescription, get value in self.opt
|
||||||
|
return getattr(self.opt,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def impl_get_display_name(self) -> str:
|
||||||
|
return self.opt.impl_get_display_name(self)
|
||||||
|
|
||||||
|
def get_current_suffixes(self) -> str:
|
||||||
|
"""get suffixes
|
||||||
|
"""
|
||||||
|
return self.current__suffixes
|
||||||
|
|
||||||
|
def impl_is_dynsymlinkoption(self) -> bool:
|
||||||
|
"""it's a dynsymlinkoption
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
def impl_getpath(self) -> str:
|
||||||
|
"""get path
|
||||||
|
"""
|
||||||
|
path = self.impl_getname()
|
||||||
|
if self.rootpath:
|
||||||
|
path = f'{self.rootpath}.{path}'
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
class SynDescr(Syn):
|
||||||
|
__slots__ = ('opt',
|
||||||
|
'rootpath',
|
||||||
|
'_current_suffixes',
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_child(self,
|
||||||
|
name: str,
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
*,
|
||||||
|
allow_dynoption: bool=False,
|
||||||
|
):
|
||||||
|
"""get children
|
||||||
|
"""
|
||||||
|
# if not dyn
|
||||||
|
option = self.get_child_not_dynamic(name,
|
||||||
|
allow_dynoption,
|
||||||
|
)
|
||||||
|
if option:
|
||||||
|
if allow_dynoption and option.impl_is_dynoptiondescription():
|
||||||
|
return option
|
||||||
|
return option.to_dynoption(self.impl_getpath(),
|
||||||
|
self._current_suffixes,
|
||||||
|
)
|
||||||
|
for child in self.opt._children[1]: # pylint: disable=no-member
|
||||||
|
if not child.impl_is_dynoptiondescription():
|
||||||
|
continue
|
||||||
|
for suffix in child.get_suffixes(config_bag):
|
||||||
|
if name != child.impl_getname(suffix):
|
||||||
|
continue
|
||||||
|
return child.to_dynoption(self.impl_getpath(),
|
||||||
|
self._current_suffixes + [suffix],
|
||||||
|
)
|
||||||
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
|
f'in optiondescription "{self.impl_get_display_name()}"'
|
||||||
|
))
|
||||||
|
|
||||||
|
def get_children(self,
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
):
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
"""get children
|
||||||
|
"""
|
||||||
|
for child in self.opt._children[1]:
|
||||||
|
if child.impl_is_dynoptiondescription():
|
||||||
|
dynchild = self.get_child(child.impl_getname(),
|
||||||
|
config_bag,
|
||||||
|
allow_dynoption=True,
|
||||||
|
)
|
||||||
|
for d in dynchild.get_sub_children(dynchild,
|
||||||
|
config_bag,
|
||||||
|
):
|
||||||
|
yield d.option
|
||||||
|
# yield from dynchild.get_sub_children(dynchild,
|
||||||
|
# config_bag,
|
||||||
|
# )
|
||||||
|
#for suffix in dynchild.get_suffixes(config_bag):
|
||||||
|
# yield child.to_dynoption(self.impl_getpath(),
|
||||||
|
# self._suffixes + [suffix],
|
||||||
|
# )
|
||||||
|
else:
|
||||||
|
yield child.to_dynoption(self.impl_getpath(),
|
||||||
|
self._current_suffixes,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_children_recursively(self,
|
||||||
|
bytype: Optional[BaseOption],
|
||||||
|
byname: Optional[str],
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
self_opt: BaseOption=None,
|
||||||
|
) -> BaseOption:
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
"""get children recursively
|
||||||
|
"""
|
||||||
|
for option in self.opt.get_children_recursively(bytype,
|
||||||
|
byname,
|
||||||
|
config_bag,
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
yield option
|
||||||
|
|
||||||
|
def get_child_not_dynamic(self,
|
||||||
|
name,
|
||||||
|
allow_dynoption,
|
||||||
|
):
|
||||||
|
children = self.opt._children
|
||||||
|
if name in children[0]: # pylint: disable=no-member
|
||||||
|
option = children[1][children[0].index(name)] # pylint: disable=no-member
|
||||||
|
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
||||||
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
|
"in root optiondescription (it's a dynamic option)"
|
||||||
|
))
|
||||||
|
return SubDynOptionDescription(option,
|
||||||
|
self.impl_getpath(),
|
||||||
|
self._current_suffixes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SynDynOption(Syn):
|
||||||
|
"""SynDynOption is an Option include un DynOptionDescription with specified prefix
|
||||||
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
def impl_get_leadership(self): # pylint: disable=inconsistent-return-statements
|
||||||
|
"""is it a leadership?
|
||||||
|
"""
|
||||||
|
leadership = self.opt.impl_get_leadership()
|
||||||
|
if leadership:
|
||||||
|
rootpath = self.rootpath.rsplit('.', 1)[0]
|
||||||
|
return leadership.to_dynoption(rootpath,
|
||||||
|
self._current_suffixes,
|
||||||
|
)
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#class SubDynOptionDescription(SynDescr, CommonDyn):
|
||||||
|
# def option_is_self(self,
|
||||||
|
# option,
|
||||||
|
# ) -> bool:
|
||||||
|
# return self.opt.option_is_self(option.opt)
|
||||||
|
#
|
||||||
|
# def get_sub_children(self,
|
||||||
|
# option,
|
||||||
|
# config_bag,
|
||||||
|
# *,
|
||||||
|
# index=None,
|
||||||
|
# properties=undefined,
|
||||||
|
# ):
|
||||||
|
# root_path, sub_path = self.split_path(option)
|
||||||
|
# for suffix in self.get_suffixes(config_bag):
|
||||||
|
# if self.option_is_self(option):
|
||||||
|
# parent_path = root_path
|
||||||
|
# elif root_path:
|
||||||
|
# parent_path = root_path + self.impl_getname(suffix) + sub_path
|
||||||
|
# else:
|
||||||
|
# parent_path = self.impl_getname(suffix) + sub_path
|
||||||
|
# yield OptionBag(option.to_dynoption(parent_path,
|
||||||
|
# [suffix],
|
||||||
|
# ),
|
||||||
|
# index,
|
||||||
|
# config_bag,
|
||||||
|
# properties=properties,
|
||||||
|
# ori_option=option
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#class SynDynOptionDescription(SynDescr):
|
||||||
|
# """SynDynOptionDescription internal option, it's an instanciate synoptiondescription
|
||||||
|
# """
|
||||||
|
# def impl_getname(self) -> str:
|
||||||
|
# """get name
|
||||||
|
# """
|
||||||
|
# if self.opt.impl_is_dynoptiondescription():
|
||||||
|
# return self.opt.impl_getname(self._current_suffixes[-1])
|
||||||
|
# return self.opt.impl_getname()
|
||||||
|
#
|
||||||
|
# def getsubdyn(self):
|
||||||
|
# return self.opt
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#class SynDynLeadership(SynDynOptionDescription):
|
||||||
|
# """SynDynLeadership internal option, it's an instanciate synoptiondescription
|
||||||
|
# """
|
||||||
|
# def get_leader(self) -> SynDynOption:
|
||||||
|
# """get the leader
|
||||||
|
# """
|
||||||
|
# return self.opt.get_leader().to_dynoption(self.impl_getpath(),
|
||||||
|
# self._current_suffixes,
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# def get_followers(self) -> Iterator[SynDynOption]:
|
||||||
|
# """get followers
|
||||||
|
# """
|
||||||
|
# subpath = self.impl_getpath()
|
||||||
|
# for follower in self.opt.get_followers():
|
||||||
|
# yield follower.to_dynoption(subpath,
|
||||||
|
# self._current_suffixes,
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# def pop(self,
|
||||||
|
# *args,
|
||||||
|
# **kwargs,
|
||||||
|
# ) -> None:
|
||||||
|
# """pop value for a follower
|
||||||
|
# """
|
||||||
|
# self.opt.pop(*args,
|
||||||
|
# followers=self.get_followers(),
|
||||||
|
# **kwargs,
|
||||||
|
# )
|
||||||
|
#
|
||||||
|
# def follower_force_store_value(self,
|
||||||
|
# value,
|
||||||
|
# config_bag,
|
||||||
|
# owner,
|
||||||
|
# ) -> None:
|
||||||
|
# """force store value for a follower
|
||||||
|
# """
|
||||||
|
# self.opt.follower_force_store_value(value,
|
||||||
|
# config_bag,
|
||||||
|
# owner,
|
||||||
|
# dyn=self,
|
||||||
|
# )
|
235
tiramisu/option/syndynoptiondescription.py
Normal file
235
tiramisu/option/syndynoptiondescription.py
Normal file
|
@ -0,0 +1,235 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (C) 2017-2023 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 Lesser General Public License as published by the
|
||||||
|
# Free Software Foundation, either version 3 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 Lesser General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
# The original `Config` design model is unproudly borrowed from
|
||||||
|
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
|
# the whole pypy projet is under MIT licence
|
||||||
|
# ____________________________________________________________
|
||||||
|
"""SynDynOptionDescription and SynDynLeadership internal option
|
||||||
|
it's an instanciate synoptiondescription
|
||||||
|
"""
|
||||||
|
from typing import Optional, Iterator, Any, List
|
||||||
|
|
||||||
|
|
||||||
|
from ..i18n import _
|
||||||
|
from ..setting import ConfigBag, undefined
|
||||||
|
from .baseoption import BaseOption
|
||||||
|
from .syndynoption import SynDynOption
|
||||||
|
|
||||||
|
|
||||||
|
class Syn:
|
||||||
|
__slots__ = ('opt',
|
||||||
|
'rootpath',
|
||||||
|
'_suffixes',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
opt: BaseOption,
|
||||||
|
rootpath: str,
|
||||||
|
suffixes: list,
|
||||||
|
) -> None:
|
||||||
|
self.opt = opt
|
||||||
|
self.rootpath = rootpath
|
||||||
|
self._suffixes = suffixes
|
||||||
|
|
||||||
|
def impl_get_display_name(self) -> str:
|
||||||
|
return self.opt.impl_get_display_name(self)
|
||||||
|
|
||||||
|
def get_child(self,
|
||||||
|
name: str,
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
*,
|
||||||
|
allow_dynoption: bool=False,
|
||||||
|
):
|
||||||
|
"""get children
|
||||||
|
"""
|
||||||
|
# if not dyn
|
||||||
|
option = self.opt.get_child_not_dynamic(name,
|
||||||
|
allow_dynoption,
|
||||||
|
)
|
||||||
|
if option:
|
||||||
|
if allow_dynoption and option.impl_is_dynoptiondescription():
|
||||||
|
return option
|
||||||
|
return option.to_dynoption(self.impl_getpath(),
|
||||||
|
self._suffixes,
|
||||||
|
)
|
||||||
|
for child in self.opt._children[1]: # pylint: disable=no-member
|
||||||
|
if not child.impl_is_dynoptiondescription():
|
||||||
|
continue
|
||||||
|
for suffix in child.get_suffixes(config_bag,
|
||||||
|
dynoption=self,
|
||||||
|
):
|
||||||
|
if name != child.impl_getname(suffix):
|
||||||
|
continue
|
||||||
|
return child.to_dynoption(self.impl_getpath(),
|
||||||
|
self._suffixes + [suffix],
|
||||||
|
)
|
||||||
|
raise AttributeError(_(f'unknown option "{name}" '
|
||||||
|
f'in optiondescription "{self.impl_get_display_name()}"'
|
||||||
|
))
|
||||||
|
|
||||||
|
def get_children(self,
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
):
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
"""get children
|
||||||
|
"""
|
||||||
|
for child in self.opt._children[1]:
|
||||||
|
if child.impl_is_dynoptiondescription():
|
||||||
|
for suffix in child.get_suffixes(config_bag,
|
||||||
|
dynoption=self,
|
||||||
|
):
|
||||||
|
yield child.to_dynoption(self.impl_getpath(),
|
||||||
|
self._suffixes + [suffix],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
yield child.to_dynoption(self.impl_getpath(),
|
||||||
|
self._suffixes,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_children_recursively(self,
|
||||||
|
bytype: Optional[BaseOption],
|
||||||
|
byname: Optional[str],
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
self_opt: BaseOption=None,
|
||||||
|
) -> BaseOption:
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
"""get children recursively
|
||||||
|
"""
|
||||||
|
for option in self.opt.get_children_recursively(bytype,
|
||||||
|
byname,
|
||||||
|
config_bag,
|
||||||
|
self,
|
||||||
|
):
|
||||||
|
yield option
|
||||||
|
|
||||||
|
def get_suffixes(self) -> str:
|
||||||
|
"""get suffixes
|
||||||
|
"""
|
||||||
|
return self._suffixes
|
||||||
|
|
||||||
|
def impl_is_dynsymlinkoption(self) -> bool:
|
||||||
|
"""it's a dynsymlinkoption
|
||||||
|
"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class SubDynOptionDescription(Syn):
|
||||||
|
|
||||||
|
def impl_getpath(self) -> str:
|
||||||
|
"""get path
|
||||||
|
"""
|
||||||
|
path = self.opt.impl_getname()
|
||||||
|
if self.rootpath:
|
||||||
|
path = f'{self.rootpath}.{path}'
|
||||||
|
return path
|
||||||
|
|
||||||
|
def getsubdyn(self):
|
||||||
|
return self.opt.getsubdyn()
|
||||||
|
|
||||||
|
def impl_is_optiondescription(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def impl_is_symlinkoption(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def impl_is_leadership(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def impl_getproperties(self):
|
||||||
|
return self.opt.impl_getproperties()
|
||||||
|
|
||||||
|
|
||||||
|
class SynDynOptionDescription(Syn):
|
||||||
|
"""SynDynOptionDescription internal option, it's an instanciate synoptiondescription
|
||||||
|
"""
|
||||||
|
def __getattr__(self,
|
||||||
|
name: str,
|
||||||
|
) -> Any:
|
||||||
|
# if not in SynDynOptionDescription, get value in self.opt
|
||||||
|
return getattr(self.opt,
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
|
||||||
|
def impl_getname(self) -> str:
|
||||||
|
"""get name
|
||||||
|
"""
|
||||||
|
if self.opt.impl_is_dynoptiondescription():
|
||||||
|
return self.opt.impl_getname(self._suffixes[-1])
|
||||||
|
return self.opt.impl_getname()
|
||||||
|
|
||||||
|
def impl_getpath(self) -> str:
|
||||||
|
"""get path
|
||||||
|
"""
|
||||||
|
path = self.impl_getname()
|
||||||
|
if self.rootpath:
|
||||||
|
path = f'{self.rootpath}.{path}'
|
||||||
|
return path
|
||||||
|
|
||||||
|
def getsubdyn(self):
|
||||||
|
return self.opt
|
||||||
|
|
||||||
|
|
||||||
|
class SynDynLeadership(SynDynOptionDescription):
|
||||||
|
"""SynDynLeadership internal option, it's an instanciate synoptiondescription
|
||||||
|
"""
|
||||||
|
def get_leader(self) -> SynDynOption:
|
||||||
|
"""get the leader
|
||||||
|
"""
|
||||||
|
return self.opt.get_leader().to_dynoption(self.impl_getpath(),
|
||||||
|
self._suffixes,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_followers(self) -> Iterator[SynDynOption]:
|
||||||
|
"""get followers
|
||||||
|
"""
|
||||||
|
subpath = self.impl_getpath()
|
||||||
|
for follower in self.opt.get_followers():
|
||||||
|
yield follower.to_dynoption(subpath,
|
||||||
|
self._suffixes,
|
||||||
|
)
|
||||||
|
|
||||||
|
def pop(self,
|
||||||
|
*args,
|
||||||
|
**kwargs,
|
||||||
|
) -> None:
|
||||||
|
"""pop value for a follower
|
||||||
|
"""
|
||||||
|
self.opt.pop(*args,
|
||||||
|
followers=self.get_followers(),
|
||||||
|
**kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
|
def follower_force_store_value(self,
|
||||||
|
value,
|
||||||
|
config_bag,
|
||||||
|
owner,
|
||||||
|
) -> None:
|
||||||
|
"""force store value for a follower
|
||||||
|
"""
|
||||||
|
self.opt.follower_force_store_value(value,
|
||||||
|
config_bag,
|
||||||
|
owner,
|
||||||
|
dyn=self,
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_suffixes(self) -> str:
|
||||||
|
"""get suffix
|
||||||
|
"""
|
||||||
|
return self._suffixes
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -32,97 +32,100 @@ from .portoption import PortOption
|
||||||
|
|
||||||
|
|
||||||
class URLOption(StrOption):
|
class URLOption(StrOption):
|
||||||
"""URLOption to check url value"""
|
"""URLOption to check url value
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||||
_type = "URL"
|
_type = _('URL')
|
||||||
|
|
||||||
def __init__(
|
def __init__(self,
|
||||||
self,
|
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
*args,
|
default: Any=undefined,
|
||||||
allow_ip: bool = False,
|
default_multi: Any=None,
|
||||||
type: str = "domainname",
|
multi: bool=False,
|
||||||
|
validators: Optional[List[Calculation]]=None,
|
||||||
|
properties: Optional[List[str]]=None,
|
||||||
|
warnings_only: bool=False,
|
||||||
|
extra: Optional[Dict]=None,
|
||||||
|
allow_ip: bool=False,
|
||||||
|
type: str='domainname',
|
||||||
allow_without_dot=False,
|
allow_without_dot=False,
|
||||||
allow_range: bool = False,
|
allow_range: bool=False,
|
||||||
allow_zero: bool = False,
|
allow_zero: bool=False,
|
||||||
allow_wellknown: bool = True,
|
allow_wellknown: bool=True,
|
||||||
allow_registred: bool = True,
|
allow_registred: bool=True,
|
||||||
allow_private: bool = False,
|
allow_private: bool=False) -> None:
|
||||||
**kwargs,
|
|
||||||
) -> None:
|
|
||||||
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
|
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
|
||||||
extra = {
|
extra = {'_domainname': DomainnameOption(name,
|
||||||
"_domainname": DomainnameOption(
|
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
allow_ip=allow_ip,
|
allow_ip=allow_ip,
|
||||||
type=type,
|
type=type,
|
||||||
allow_without_dot=allow_without_dot,
|
allow_without_dot=allow_without_dot),
|
||||||
),
|
'_port': PortOption(name,
|
||||||
"_port": PortOption(
|
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
allow_range=allow_range,
|
allow_range=allow_range,
|
||||||
allow_zero=allow_zero,
|
allow_zero=allow_zero,
|
||||||
allow_wellknown=allow_wellknown,
|
allow_wellknown=allow_wellknown,
|
||||||
allow_registred=allow_registred,
|
allow_registred=allow_registred,
|
||||||
allow_private=allow_private,
|
allow_private=allow_private)}
|
||||||
),
|
super().__init__(name,
|
||||||
}
|
|
||||||
super().__init__(
|
|
||||||
name,
|
|
||||||
doc,
|
doc,
|
||||||
extra=extra,
|
default=default,
|
||||||
*args,
|
default_multi=default_multi,
|
||||||
**kwargs,
|
multi=multi,
|
||||||
)
|
validators=validators,
|
||||||
|
properties=properties,
|
||||||
|
warnings_only=warnings_only,
|
||||||
|
extra=extra)
|
||||||
|
|
||||||
def _get_domain_port_files(self, value: str) -> (str, str):
|
def _get_domain_port_files(self,
|
||||||
if value.startswith("http://"):
|
value: str) -> (str, str):
|
||||||
type_ = "http"
|
if value.startswith('http://'):
|
||||||
|
type_ = 'http'
|
||||||
value = value[7:]
|
value = value[7:]
|
||||||
elif value.startswith("https://"):
|
elif value.startswith('https://'):
|
||||||
type_ = "https"
|
type_ = 'https'
|
||||||
value = value[8:]
|
value = value[8:]
|
||||||
else:
|
else:
|
||||||
raise ValueError(_("must start with http:// or " "https://"))
|
raise ValueError(_('must start with http:// or '
|
||||||
|
'https://'))
|
||||||
# get domain/files
|
# get domain/files
|
||||||
splitted = value.split("/", 1)
|
splitted = value.split('/', 1)
|
||||||
if len(splitted) == 1:
|
if len(splitted) == 1:
|
||||||
domain = value
|
domain = value
|
||||||
files = None
|
files = None
|
||||||
else:
|
else:
|
||||||
domain, files = splitted
|
domain, files = splitted
|
||||||
# if port in domain
|
# if port in domain
|
||||||
splitted = domain.split(":", 1)
|
splitted = domain.split(':', 1)
|
||||||
if len(splitted) == 1:
|
if len(splitted) == 1:
|
||||||
domain = splitted[0]
|
domain = splitted[0]
|
||||||
port = {"http": "80", "https": "443"}[type_]
|
port = {'http': '80',
|
||||||
|
'https': '443'}[type_]
|
||||||
else:
|
else:
|
||||||
domain, port = splitted
|
domain, port = splitted
|
||||||
return domain, port, files
|
return domain, port, files
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self,
|
||||||
|
value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
domain, port, files = self._get_domain_port_files(value)
|
domain, port, files = self._get_domain_port_files(value)
|
||||||
# validate port
|
# validate port
|
||||||
portoption = self.impl_get_extra("_port")
|
portoption = self.impl_get_extra('_port')
|
||||||
portoption.validate(port)
|
portoption.validate(port)
|
||||||
# validate domainname
|
# validate domainname
|
||||||
domainnameoption = self.impl_get_extra("_domainname")
|
domainnameoption = self.impl_get_extra('_domainname')
|
||||||
domainnameoption.validate(domain)
|
domainnameoption.validate(domain)
|
||||||
# validate files
|
# validate files
|
||||||
if files is not None and files != "" and not self.path_re.search(files):
|
if files is not None and files != '' and not self.path_re.search(files):
|
||||||
raise ValueError(_("must ends with a valid resource name"))
|
raise ValueError(_('must ends with a valid resource name'))
|
||||||
|
|
||||||
def second_level_validation(self, value, warnings_only):
|
def second_level_validation(self, value, warnings_only):
|
||||||
domain, port, _ = self._get_domain_port_files(value)
|
domain, port, _ = self._get_domain_port_files(value)
|
||||||
# validate port
|
# validate port
|
||||||
portoption = self.impl_get_extra("_port")
|
portoption = self.impl_get_extra('_port')
|
||||||
portoption.second_level_validation(port, warnings_only)
|
portoption.second_level_validation(port, warnings_only)
|
||||||
# validate domainname
|
# validate domainname
|
||||||
domainnameoption = self.impl_get_extra("_domainname")
|
domainnameoption = self.impl_get_extra('_domainname')
|
||||||
domainnameoption.second_level_validation(domain, warnings_only)
|
domainnameoption.second_level_validation(domain, warnings_only)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
@ -27,16 +27,16 @@ from .stroption import RegexpOption
|
||||||
|
|
||||||
|
|
||||||
class UsernameOption(RegexpOption):
|
class UsernameOption(RegexpOption):
|
||||||
"""UsernameOption to check unix username value"""
|
"""UsernameOption to check unix username value
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
# regexp build with 'man 8 adduser' informations
|
#regexp build with 'man 8 adduser' informations
|
||||||
_regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
|
_regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
|
||||||
_type = "unix username"
|
_type = _('unix username')
|
||||||
|
|
||||||
|
|
||||||
class GroupnameOption(UsernameOption):
|
class GroupnameOption(UsernameOption):
|
||||||
"""GroupnameOption to check unix group value"""
|
"""GroupnameOption to check unix group value
|
||||||
|
"""
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "unix groupname"
|
_type = _('unix groupname')
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue