Compare commits
14 commits
Author | SHA1 | Date | |
---|---|---|---|
1a31ada869 | |||
4aecf2c4bd | |||
a3228fbf30 | |||
c3bb590415 | |||
16a7857d0c | |||
952069a865 | |||
5e66d2074d | |||
b5d477a439 | |||
54ac0c980a | |||
be8b1e7e4f | |||
7ae1b48f4a | |||
7761758096 | |||
bbec439a5e | |||
9c36fb8fb2 |
74 changed files with 9142 additions and 7109 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
*~
|
||||
*#
|
||||
*.pyc
|
||||
*.mo
|
||||
*.swp
|
||||
build/
|
||||
|
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -1,3 +1,31 @@
|
|||
## 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)
|
||||
|
||||
### Fix
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# 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,13 +1,25 @@
|
|||
![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)
|
||||
|
||||
|
||||
# LICENSES
|
||||
|
||||
See COPYING for the licences of the code and the documentation.
|
||||
See [COPYING](COPYING) for the licences of the code and the documentation.
|
||||
|
||||
See AUTHORS for the details about the tiramisu's team.
|
||||
See [AUTHORS](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
|
||||
|
||||
Settings:
|
||||
forcepermissive Access to option without verifying permissive properties
|
||||
unrestraint Access to option without property restriction
|
||||
nowarnings Do not warnings during validation
|
||||
|
||||
Commands:
|
||||
cache Manage config cache
|
||||
config Actions to Config
|
||||
information Manage config informations
|
||||
option Select an option
|
||||
owner Global owner
|
||||
permissive Manage config permissives
|
||||
property Manage config properties
|
||||
value Manage config value
|
||||
description Get option description
|
||||
dict Convert config and option to tiramisu format
|
||||
get Get Tiramisu option
|
||||
has_dependency Test if option has dependency
|
||||
isdynamic Test if option is a dynamic optiondescription
|
||||
isleadership Test if option is a leader or a follower
|
||||
isoptiondescription Test if option is an optiondescription
|
||||
list List options (by default list only option)
|
||||
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.
|
||||
|
||||
|
@ -105,16 +105,35 @@ Then let's print our :class:`Option` details.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
Select an option
|
||||
|
||||
Call: Select an option by path
|
||||
Manage selected option
|
||||
|
||||
Commands:
|
||||
dict Convert config and option to tiramisu format
|
||||
find Find an or a list of options
|
||||
list List options (by default list only option)
|
||||
name get the name
|
||||
updates Updates value with tiramisu format
|
||||
dependencies Get dependencies from this option
|
||||
description Get option description
|
||||
dict Convert config and option to tiramisu format
|
||||
extra Get de option extra
|
||||
followers Get the followers option for a leadership
|
||||
get Get Tiramisu option
|
||||
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
|
||||
|
||||
Finaly, let's print the :class:`Config`.
|
||||
|
||||
|
@ -123,7 +142,7 @@ Finaly, let's print the :class:`Config`.
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
<tiramisu.api.Config object at 0x7f3ee6204278>
|
||||
<Config path=None>
|
||||
|
||||
:download:`download the getting started code <src/getting_started.py>`
|
||||
|
||||
|
|
|
@ -25,26 +25,32 @@ Dynamic option description is an :class:`OptionDescription` which multiplies acc
|
|||
|
||||
Note:: the option can be an :doc:`option` or an other option description
|
||||
|
||||
* - suffixes
|
||||
- Suffixes is a :doc:`calculation` that return the list of suffixes used to create dynamic option description.
|
||||
* - identifiers
|
||||
- Identifiers is a :doc:`calculation` that return the list of identifiers used to create dynamic option description.
|
||||
|
||||
* - properties
|
||||
- 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
|
||||
==============
|
||||
|
||||
Let's try:
|
||||
|
||||
>>> from tiramisu import StrOption, DynOptionDescription, Calculation
|
||||
>>> def return_suffixes():
|
||||
>>> def return_identifiers():
|
||||
... return ['1', '2']
|
||||
>>> child1 = StrOption('first', 'First basic option ')
|
||||
>>> child2 = StrOption('second', 'Second basic option ')
|
||||
>>> DynOptionDescription('basic ',
|
||||
... 'Basic options ',
|
||||
... [child1, child2],
|
||||
... Calculation(return_suffixes))
|
||||
... Calculation(return_identifiers))
|
||||
|
||||
This example will construct:
|
||||
|
||||
|
|
|
@ -35,6 +35,9 @@ The leadership
|
|||
* - properties
|
||||
- A list of :doc:`property` (inside a frozenset().
|
||||
|
||||
* - informations
|
||||
- We can add default informations to this option description.
|
||||
|
||||
Example
|
||||
====================
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ Option
|
|||
* - doc
|
||||
- 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
|
||||
- For each option, we can defined a default value. This value will be the value of this option until user customize it.
|
||||
|
||||
|
@ -35,14 +32,20 @@ Option
|
|||
|
||||
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
|
||||
- A list of :doc:`validator`.
|
||||
|
||||
* - properties
|
||||
- A list of :doc:`property` (inside a frozenset().
|
||||
|
||||
* - warnings_only
|
||||
- Only emit warnings if not type validation is invalid.
|
||||
|
||||
* - properties
|
||||
- A list of :doc:`property` (inside a frozenset().
|
||||
* - informations
|
||||
- We can add default informations to this option.
|
||||
|
||||
|
||||
Examples
|
||||
|
|
|
@ -25,6 +25,12 @@ Option description
|
|||
* - properties
|
||||
- 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
|
||||
==============
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ Network options
|
|||
-
|
||||
|
||||
* - 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
|
||||
|
@ -114,6 +114,10 @@ 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_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_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
|
||||
|
@ -276,18 +280,35 @@ Unix options
|
|||
|
||||
* - Type
|
||||
- Comments
|
||||
- Extra parameters
|
||||
|
||||
* - 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 "_".
|
||||
-
|
||||
|
||||
* - GroupnameOption
|
||||
- Same conditions has username
|
||||
-
|
||||
|
||||
* - PasswordOption
|
||||
- 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
|
||||
- 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
|
||||
>>> UsernameOption('user', 'user', 'my_user')
|
||||
|
|
|
@ -14,6 +14,6 @@ cfg = Config(descr)
|
|||
# the global help about the config
|
||||
cfg.help()
|
||||
# help about an option
|
||||
cfg.option.help()
|
||||
cfg.option("bool").help()
|
||||
# the config's __repr__
|
||||
print(cfg)
|
||||
|
|
1379
locale/fr/LC_MESSAGES/tiramisu.po
Normal file
1379
locale/fr/LC_MESSAGES/tiramisu.po
Normal file
File diff suppressed because it is too large
Load diff
823
locale/tiramisu.pot
Normal file
823
locale/tiramisu.pot
Normal file
|
@ -0,0 +1,823 @@
|
|||
# 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 ""
|
||||
|
37
pyproject.toml
Normal file
37
pyproject.toml
Normal file
|
@ -0,0 +1,37 @@
|
|||
[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
52
setup.py
|
@ -1,52 +0,0 @@
|
|||
#!/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://forge.cloud.silique.fr/stove/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],
|
||||
)
|
|
@ -13,9 +13,8 @@ import pytest
|
|||
# submulti, undefined, owners, Params, ParamOption, Calculation
|
||||
from tiramisu import Config, DynOptionDescription, OptionDescription, Leadership, \
|
||||
StrOption, IntOption, ChoiceOption, SymLinkOption, \
|
||||
Calculation, Params, ParamValue, ParamOption, ParamSelfOption, ParamInformation, ParamSelfInformation, ParamIndex, ParamSuffix, \
|
||||
Calculation, Params, ParamValue, ParamOption, ParamSelfOption, ParamInformation, ParamSelfInformation, ParamIndex, ParamIdentifier, \
|
||||
submulti, calc_value, owners
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.option.baseoption import BaseOption
|
||||
from tiramisu.error import ConfigError, ConstError, PropertiesOptionError, LeadershipError
|
||||
from tiramisu.setting import ALLOWED_LEADER_PROPERTIES
|
||||
|
@ -86,6 +85,7 @@ def build_variables(*,
|
|||
base_name += 'dynamic_'
|
||||
if hidden:
|
||||
base_name += 'hidden_'
|
||||
#str_mandatory_multi_hidden_information_deps
|
||||
str1 = StrOption(base_name + 'information_deps',
|
||||
'',
|
||||
multi=multi,
|
||||
|
@ -211,10 +211,10 @@ def build_variables(*,
|
|||
)
|
||||
)
|
||||
if dynoptiondescription:
|
||||
default = Calculation(calc_value, Params(ParamSuffix()))
|
||||
default = Calculation(calc_value, Params(ParamIdentifier()))
|
||||
if param_multi:
|
||||
default = [default]
|
||||
variables.append(StrOption(base_name + 'calc_default_suffix',
|
||||
variables.append(StrOption(base_name + 'calc_default_identifier',
|
||||
'',
|
||||
default,
|
||||
multi=multi,
|
||||
|
@ -309,40 +309,43 @@ def build_root_variables(*,
|
|||
follower_params['multi'] = submulti
|
||||
else:
|
||||
follower_params['multi'] = True
|
||||
suffix = ''
|
||||
identifier = ''
|
||||
if dynamic:
|
||||
suffix += '_dynamic'
|
||||
lsuffix = suffix
|
||||
identifier += '_dynamic'
|
||||
lidentifier = identifier
|
||||
if hidden:
|
||||
lsuffix += '_hidden'
|
||||
variables.append(Leadership('leadership' + lsuffix, '', [StrOption('leader_multi_deps' + lsuffix,
|
||||
lidentifier += '_hidden'
|
||||
variables.append(Leadership('leadership' + lidentifier, '', [StrOption('leader_multi_deps' + lidentifier,
|
||||
'',
|
||||
default=['l1', 'l2'],
|
||||
multi=True,
|
||||
),
|
||||
] + build_variables(**follower_params, parent_variables=parent_variables, dynamic=dynamic, hidden=hidden),
|
||||
))
|
||||
suffixes = StrOption('suffixes_multi_deps' + lsuffix, '', ['d1', 'd2'], multi=True)
|
||||
variables.append(suffixes)
|
||||
identifiers = StrOption('identifiers_multi_deps' + lidentifier, '', ['d1', 'd2'], multi=True)
|
||||
variables.append(identifiers)
|
||||
dynamic_name = 'dynamic_'
|
||||
if hidden:
|
||||
dynamic_name += 'hidden_'
|
||||
variables.append(DynOptionDescription(dynamic_name, '', build_variables(**kwargs, dynoptiondescription=True, parent_variables=parent_variables, dynamic=dynamic, hidden=hidden), Calculation(return_var, Params(ParamOption(suffixes)))))
|
||||
variables.append(DynOptionDescription(dynamic_name, '', build_variables(**kwargs, dynoptiondescription=True, parent_variables=parent_variables, dynamic=dynamic, hidden=hidden), Calculation(return_var, Params(ParamOption(identifiers)))))
|
||||
tree.reverse()
|
||||
for idx, t in enumerate(tree):
|
||||
lsuffix = suffix
|
||||
lidentifier = identifier
|
||||
variables.extend(parent_variables.pop(-1))
|
||||
if hidden and idx <= hidden_idx:
|
||||
lsuffix = '_hidden' + suffix
|
||||
if t.startswith('h'):
|
||||
lidentifier = '_self_hidden' + identifier
|
||||
else:
|
||||
lidentifier = '_hidden' + identifier
|
||||
if t.startswith('h'):
|
||||
t = t[1:]
|
||||
properties = frozenset(['hidden'])
|
||||
else:
|
||||
properties = frozenset()
|
||||
if t == 'dod':
|
||||
variables = [DynOptionDescription('tree_dynamic' + lsuffix, '', variables, Calculation(return_var, Params(ParamValue(['var1', 'var2']))), properties=properties)]
|
||||
variables = [DynOptionDescription('tree_dynamic' + lidentifier, '', variables, Calculation(return_var, Params(ParamValue(['var1', 'var2']))), properties=properties)]
|
||||
else:
|
||||
variables = [OptionDescription('tree' + lsuffix, '', variables, properties=properties)]
|
||||
variables = [OptionDescription('tree' + lidentifier, '', variables, properties=properties)]
|
||||
od = OptionDescription('root', 'root', variables, informations={'cfg_key': 'cfg_info'})
|
||||
return od
|
||||
|
||||
|
@ -445,17 +448,17 @@ def _test_option(option, without_index=False):
|
|||
option.leadership()
|
||||
assert option.isdynamic() == ('dynamic' in name)
|
||||
if option.isdynamic():
|
||||
suffixes = []
|
||||
identifiers = []
|
||||
for path in option.path().split('.'):
|
||||
if 'dynamicvar1' in path:
|
||||
suffixes.append('var1')
|
||||
identifiers.append('var1')
|
||||
if 'dynamicvar2' in path:
|
||||
suffixes.append('var2')
|
||||
identifiers.append('var2')
|
||||
if 'd1' in path:
|
||||
suffixes.append('d1')
|
||||
identifiers.append('d1')
|
||||
if 'd2' in path:
|
||||
suffixes.append('d2')
|
||||
assert option.suffixes() == suffixes
|
||||
identifiers.append('d2')
|
||||
assert option.identifiers() == identifiers
|
||||
assert isinstance(option.description(), str) and option.description() == name and option.description(uncalculated=True) == ''
|
||||
assert isinstance(option.path(), str) and (option.path() == name or option.path().endswith(f'.{name}'))
|
||||
if '_deps' in name:
|
||||
|
@ -467,11 +470,11 @@ def _test_option(option, without_index=False):
|
|||
if option.isoptiondescription():
|
||||
assert option.type() == 'optiondescription'
|
||||
elif 'index' in name:
|
||||
assert option.type() == _('integer')
|
||||
assert option.type() == 'integer'
|
||||
elif 'choice' in name:
|
||||
assert option.type() == _('choice')
|
||||
assert option.type() == 'choice'
|
||||
else:
|
||||
assert option.type() == _('string')
|
||||
assert option.type() == 'string'
|
||||
# only option
|
||||
if option.isoptiondescription():
|
||||
with pytest.raises(ConfigError):
|
||||
|
@ -485,9 +488,9 @@ def _test_option(option, without_index=False):
|
|||
with pytest.raises(ConfigError):
|
||||
option.issymlinkoption()
|
||||
with pytest.raises(ConfigError):
|
||||
option.default()
|
||||
option.value.default()
|
||||
with pytest.raises(ConfigError):
|
||||
option.defaultmulti()
|
||||
option.value.defaultmulti()
|
||||
with pytest.raises(ConfigError):
|
||||
option.pattern()
|
||||
with pytest.raises(ConfigError):
|
||||
|
@ -514,14 +517,14 @@ def _test_option(option, without_index=False):
|
|||
assert option.index() in [0, 1]
|
||||
else:
|
||||
assert option.index() is None
|
||||
if option.type() == _('integer'):
|
||||
if option.type() == 'integer':
|
||||
assert option.pattern() == '^[0-9]+$'
|
||||
else:
|
||||
assert not option.pattern()
|
||||
default = option.default()
|
||||
default = option.value.default(uncalculated=True)
|
||||
if 'calc_default' in name:
|
||||
assert isinstance(default, Calculation) or (isinstance(default, list) and len(default) == 1 and isinstance(default[0], Calculation))
|
||||
elif 'suffixes_multi' in name:
|
||||
elif 'identifiers_multi' in name:
|
||||
assert default == ['d1', 'd2']
|
||||
elif 'leader_multi' in name:
|
||||
assert default == ['l1', 'l2']
|
||||
|
@ -530,9 +533,9 @@ def _test_option(option, without_index=False):
|
|||
else:
|
||||
assert default is None
|
||||
if option.issubmulti():
|
||||
assert option.defaultmulti() == []
|
||||
assert option.value.defaultmulti() == []
|
||||
elif option.ismulti():
|
||||
assert option.defaultmulti() is None
|
||||
assert option.value.defaultmulti() is None
|
||||
|
||||
|
||||
def _test_information(cfg, option, without_index=False):
|
||||
|
@ -764,8 +767,8 @@ def _get_value(name, option, unrestraint):
|
|||
value = 'value'
|
||||
if 'multi' in name:
|
||||
value = [value]
|
||||
elif 'calc_default_suffix' in name:
|
||||
value = option.suffixes()[-1]
|
||||
elif 'calc_default_identifier' in name:
|
||||
value = option.identifiers()[-1]
|
||||
if 'multi' in name:
|
||||
value = [value]
|
||||
elif 'calc_default_index' in name:
|
||||
|
@ -776,7 +779,7 @@ def _get_value(name, option, unrestraint):
|
|||
value = 'val'
|
||||
if 'multi' in name:
|
||||
value = [value]
|
||||
elif 'suffixes_multi' in name:
|
||||
elif 'identifiers_multi' in name:
|
||||
value = ['d1', 'd2']
|
||||
elif 'leader_multi_deps' in name:
|
||||
value = ['l1', 'l2']
|
||||
|
@ -816,11 +819,11 @@ def _test_value_normal(name, cfg, option, unrestraint, without_index):
|
|||
with pytest.raises(ConfigError):
|
||||
option.value.list()
|
||||
else:
|
||||
if option.type() == _('string'):
|
||||
if option.type() == 'string':
|
||||
new_value = 'new_value'
|
||||
new_value2 = 'new_value1'
|
||||
new_value3 = 'new_value2'
|
||||
elif option.type() == _('integer'):
|
||||
elif option.type() == 'integer':
|
||||
new_value = 10
|
||||
new_value2 = 11
|
||||
new_value3 = 12
|
||||
|
@ -904,7 +907,8 @@ def _test_property(cfg, option, unrestraint=False, without_index=False):
|
|||
if not unrestraint:
|
||||
properties_only_raises.append('hidden')
|
||||
properties_apply_requires.append('hidden')
|
||||
properties_uncalculated.append('hidden')
|
||||
if 'self_hidden' in option.name():
|
||||
properties_uncalculated.append('hidden')
|
||||
if name and 'mandatory' in name:
|
||||
properties.append('mandatory')
|
||||
properties_apply_requires.append('mandatory')
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"options.unicode": null
|
||||
}
|
|
@ -32,6 +32,9 @@ def list_data(ext='.py'):
|
|||
for filename in filenames:
|
||||
# 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 'leadership' in filename:
|
||||
# print('FIXME')
|
||||
# continue
|
||||
ret.append(filename)
|
||||
return ret
|
||||
|
||||
|
@ -58,7 +61,7 @@ def load_config(filename,
|
|||
form.extend(mod.get_form(add_extra_od))
|
||||
config.property.read_write()
|
||||
if root is None:
|
||||
values = loads(dumps(config.option.dict(remotable=remote, clearable=clearable, form=form)))
|
||||
values = loads(dumps(config.dict(remotable=remote, clearable=clearable, form=form)))
|
||||
else:
|
||||
values = loads(dumps(config.option(root).dict(remotable=remote, clearable=clearable, form=form)))
|
||||
return values
|
||||
|
@ -380,11 +383,12 @@ def test_updates(filename_mod):
|
|||
if dico_ori is None:
|
||||
if clearable == 'minimum' and remote == 'minimum':
|
||||
with open(join(datadir, modulepath + '.dict'), 'w') as fh:
|
||||
dump(config.value.dict(), fh, indent=2)
|
||||
pouet
|
||||
dump(config.value.get(), fh, indent=2)
|
||||
else:
|
||||
assert config.value.dict() == dico_ori, "clearable {}, remote: {}, filename: {}".format(clearable, remote, filename_mod)
|
||||
assert config.value.get() == dico_ori, "clearable {}, remote: {}, filename: {}".format(clearable, remote, filename_mod)
|
||||
if root is None:
|
||||
suboption = config.option
|
||||
suboption = config
|
||||
else:
|
||||
suboption = config.option(root)
|
||||
if with_model:
|
||||
|
|
|
@ -446,7 +446,7 @@ def test_config_od_name(config_type):
|
|||
cfg = get_config(cfg, config_type)
|
||||
assert cfg.option('val.i').name() == 'i'
|
||||
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 not list_sessions()
|
||||
|
||||
|
@ -458,7 +458,7 @@ def test_config_od_type(config_type):
|
|||
cfg = Config(o2)
|
||||
cfg = get_config(cfg, config_type)
|
||||
assert cfg.option('val').type() == 'optiondescription'
|
||||
assert cfg.option('val.i').type() == _('integer')
|
||||
assert cfg.option('val.i').type() == 'integer'
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
|
@ -201,7 +201,7 @@ def test_deref_symlink():
|
|||
def test_deref_dyn():
|
||||
a = StrOption('a', '', ['val1', 'val2'], multi=True)
|
||||
b = StrOption('b', '')
|
||||
dod = DynOptionDescription('dod', '', [b], suffixes=Calculation(funcname, Params((ParamOption(a),))))
|
||||
dod = DynOptionDescription('dod', '', [b], identifiers=Calculation(funcname, Params((ParamOption(a),))))
|
||||
o = OptionDescription('od', '', [dod, a])
|
||||
cfg = Config(o)
|
||||
w = weakref.ref(a)
|
||||
|
|
|
@ -11,45 +11,47 @@ from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \
|
|||
EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \
|
||||
OptionDescription, DynOptionDescription, submulti, Leadership, \
|
||||
Config, \
|
||||
Params, ParamOption, ParamValue, ParamSuffix, ParamSelfOption, ParamDynOption, ParamIndex, ParamSelfInformation, ParamInformation, \
|
||||
Params, ParamOption, ParamValue, ParamIdentifier, ParamSelfOption, ParamDynOption, ParamIndex, ParamSelfInformation, ParamInformation, \
|
||||
Calculation, calc_value
|
||||
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError, ValueOptionError
|
||||
|
||||
|
||||
def display_name(kls, subconfig) -> str:
|
||||
def display_name(kls, subconfig, with_quote=False) -> str:
|
||||
"""Replace the Tiramisu display_name function to display path + description"""
|
||||
doc = kls._get_information(subconfig, "doc", None)
|
||||
comment = f" ({doc})" if doc and doc != subconfig.path.rsplit('.', 1)[-1] else ""
|
||||
if with_quote:
|
||||
return f'"{subconfig.path}"{comment}'
|
||||
return f"{subconfig.path}{comment}"
|
||||
|
||||
|
||||
class ConvertDynOptionDescription(DynOptionDescription):
|
||||
def convert_suffix_to_path(self, suffix):
|
||||
def convert_identifier_to_path(self, identifier):
|
||||
# remove dot with is illegal
|
||||
return suffix.replace('.', '')
|
||||
return identifier.replace('.', '')
|
||||
|
||||
|
||||
def return_true(value, param=None, suffix=None):
|
||||
def return_true(value, param=None, identifier=None):
|
||||
if value == 'val' and param in [None, 'yes']:
|
||||
return
|
||||
raise ValueError('no value')
|
||||
|
||||
|
||||
def return_dynval(value='val', suffix=None):
|
||||
def return_dynval(value='val', identifier=None):
|
||||
return value
|
||||
|
||||
|
||||
def return_list2(suffix):
|
||||
return [str(suffix), 'val2']
|
||||
def return_list2(identifier):
|
||||
return [str(identifier), 'val2']
|
||||
|
||||
|
||||
def return_list(val=None, suffix=None):
|
||||
def return_list(val=None, identifier=None):
|
||||
if val:
|
||||
return val
|
||||
return ['val1', 'val2']
|
||||
|
||||
|
||||
def return_list_dot(val=None, suffix=None):
|
||||
def return_list_dot(val=None, identifier=None):
|
||||
return ['val.1', 'val.2']
|
||||
|
||||
|
||||
|
@ -71,7 +73,7 @@ def return_str(*args, **kwargs):
|
|||
|
||||
def test_build_dyndescription():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st': None, 'dodval2.st': None}
|
||||
|
@ -82,23 +84,39 @@ def test_build_dyndescription():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyndescription_suffixes():
|
||||
def test_dyndescription_identifiers():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st': None, 'dodval2.st': None}
|
||||
assert cfg.option('dodval1').suffixes() == ['val1']
|
||||
assert cfg.option('dodval1.st').suffixes() == ['val1']
|
||||
assert cfg.option('dodval1').suffixes(only_self=True) == ['val1', 'val2']
|
||||
assert cfg.option('dodval1').identifiers() == ['val1']
|
||||
assert cfg.option('dodval1.st').identifiers() == ['val1']
|
||||
assert cfg.option('dodval1').identifiers(only_self=True) == ['val1', 'val2']
|
||||
with pytest.raises(ConfigError):
|
||||
cfg.option('dodval1.st').suffixes(only_self=True)
|
||||
cfg.option('dodval1.st').identifiers(only_self=True)
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyndescription_identifiers_2():
|
||||
st1 = StrOption('st', '')
|
||||
od = OptionDescription('od', '', [st1])
|
||||
dod = DynOptionDescription('dod', '', [od], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.od.st': None, 'dodval2.od.st': None}
|
||||
assert cfg.option('dodval1').identifiers() == ['val1']
|
||||
assert cfg.option('dodval1.od').identifiers() == ['val1']
|
||||
assert cfg.option('dodval1.od.st').identifiers() == ['val1']
|
||||
assert cfg.option('dodval1').identifiers(only_self=True) == ['val1', 'val2']
|
||||
with pytest.raises(ConfigError):
|
||||
cfg.option('dodval1.od').identifiers(only_self=True)
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_build_dyndescription_with_int():
|
||||
int1 = IntOption('int', '', default=Calculation(calc_value, Params(ParamSuffix())))
|
||||
dod = DynOptionDescription('dod', '', [int1], suffixes=Calculation(return_list, Params(ParamValue([1, 2]))))
|
||||
int1 = IntOption('int', '', default=Calculation(calc_value, Params(ParamIdentifier())))
|
||||
dod = DynOptionDescription('dod', '', [int1], identifiers=Calculation(return_list, Params(ParamValue([1, 2]))))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dod1.int': 1, 'dod2.int': 2}
|
||||
|
@ -106,8 +124,8 @@ def test_build_dyndescription_with_int():
|
|||
|
||||
|
||||
def test_build_dyndescription_with_dot():
|
||||
st1 = StrOption('st', '', default=Calculation(calc_value, Params(ParamSuffix())))
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list_dot))
|
||||
st1 = StrOption('st', '', default=Calculation(calc_value, Params(ParamIdentifier())))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list_dot))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval_1.st': 'val.1', 'dodval_2.st': 'val.2'}
|
||||
|
@ -116,7 +134,7 @@ def test_build_dyndescription_with_dot():
|
|||
|
||||
def test_build_dyndescription_raise():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_raise))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_raise))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
with pytest.raises(ConfigError):
|
||||
|
@ -126,7 +144,7 @@ def test_build_dyndescription_raise():
|
|||
|
||||
def test_build_dyndescription_not_list():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_str))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_str))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -136,7 +154,7 @@ def test_build_dyndescription_not_list():
|
|||
|
||||
def test_subpath_dyndescription():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -146,7 +164,7 @@ def test_subpath_dyndescription():
|
|||
|
||||
def test_list_dyndescription():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -157,7 +175,7 @@ def test_list_dyndescription():
|
|||
|
||||
def test_unknown_dyndescription():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -174,7 +192,7 @@ def test_unknown_dyndescription():
|
|||
|
||||
def test_getdoc_dyndescription():
|
||||
st1 = StrOption('st', 'doc1')
|
||||
dod = DynOptionDescription('dod', 'doc2', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', 'doc2', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -193,7 +211,7 @@ def test_getdoc_dyndescription():
|
|||
|
||||
def test_dyndescription_path():
|
||||
st1 = StrOption('st', 'doc1')
|
||||
dod = DynOptionDescription('dod', 'doc2', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', 'doc2', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -207,7 +225,7 @@ def test_dyndescription_path():
|
|||
|
||||
def test_mod_dyndescription():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -234,7 +252,7 @@ def test_mod_dyndescription():
|
|||
|
||||
def test_del_dyndescription():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -250,7 +268,7 @@ def test_del_dyndescription():
|
|||
|
||||
def test_multi_dyndescription():
|
||||
st = StrOption('st', '', multi=True)
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -278,7 +296,7 @@ def test_multi_dyndescription():
|
|||
|
||||
def test_prop_dyndescription():
|
||||
st = StrOption('st', '', properties=('test',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -301,7 +319,7 @@ def test_prop_dyndescription():
|
|||
|
||||
def test_prop_dyndescription_force_store_value():
|
||||
st = StrOption('st', '', properties=('force_store_value',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -312,8 +330,8 @@ def test_prop_dyndescription_force_store_value():
|
|||
|
||||
def test_prop_dyndescription_force_store_value_calculation_prefix():
|
||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', Calculation(return_list, Params(ParamSuffix())) , properties=('force_store_value',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(lst))))
|
||||
st = StrOption('st', '', Calculation(return_list, Params(ParamIdentifier())) , properties=('force_store_value',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
od = OptionDescription('od', '', [dod, lst])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -333,7 +351,7 @@ def test_prop_dyndescription_force_store_value_calculation_prefix():
|
|||
|
||||
def test_callback_dyndescription():
|
||||
st = StrOption('st', '', Calculation(return_dynval))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -358,7 +376,7 @@ def test_callback_dyndescription():
|
|||
def test_callback_dyndescription_outside_wrong_param():
|
||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', Calculation(return_dynval))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(lst))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamOption(st))))
|
||||
od = OptionDescription('od', '', [dod, out])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
|
@ -371,7 +389,7 @@ def test_callback_dyndescription_outside_wrong_param():
|
|||
def test_callback_dyndescription_outside1():
|
||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', Calculation(return_dynval))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(lst))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamDynOption(st, ['val1']))))
|
||||
od = OptionDescription('od', '', [dod, out])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
|
@ -392,7 +410,7 @@ def test_callback_dyndescription_outside2():
|
|||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
out = StrOption('out', '')
|
||||
st = StrOption('st', '', Calculation(return_dynval, Params(ParamOption(out))))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(lst))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
od = OptionDescription('od', '', [dod, out])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
cfg = Config(od2)
|
||||
|
@ -402,9 +420,34 @@ def test_callback_dyndescription_outside2():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_callback_dyndescription_outside3():
|
||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', 'val1')
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))), properties=('hidden',))
|
||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamDynOption(st, ['val1']))))
|
||||
od = OptionDescription('od', '', [dod, out])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_write()
|
||||
assert parse_od_get(cfg.value.get()) == {'od.out': 'val1', 'lst': ['val1', 'val2']}
|
||||
|
||||
|
||||
def test_callback_dyndescription_subdyn():
|
||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', 'val1')
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamDynOption(st, ['val1', None]))), multi=True, properties=('notunique',))
|
||||
dod2 = DynOptionDescription('dod2', '', [dod, out], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
||||
od = OptionDescription('od', '', [dod2])
|
||||
od2 = OptionDescription('od', '', [od, lst])
|
||||
cfg = Config(od2)
|
||||
cfg.property.read_write()
|
||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval2.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val2.dodval1.st': 'val1', 'od.dod2val2.dodval2.st': 'val1', 'od.dod2val2.out': ['val1', 'val1'], 'lst': ['val1', 'val2']}
|
||||
|
||||
|
||||
def test_callback_list_dyndescription():
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamSuffix())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamIdentifier())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -423,7 +466,7 @@ def test_callback_list_dyndescription():
|
|||
|
||||
def test_mandatory_dyndescription():
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -449,7 +492,7 @@ def test_mandatory_dyndescription():
|
|||
def test_build_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od1 = OptionDescription('od', '', [dod, val1])
|
||||
cfg = Config(od1)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st': None, 'dodval2.st': None, 'val1': ['val1', 'val2']}
|
||||
|
@ -459,7 +502,7 @@ def test_build_dyndescription_context():
|
|||
def test_subpath_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od1 = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -470,7 +513,7 @@ def test_subpath_dyndescription_context():
|
|||
def test_list_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -484,7 +527,7 @@ def test_list_dyndescription_context():
|
|||
def test_mod_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -509,7 +552,7 @@ def test_mod_dyndescription_context():
|
|||
def test_del_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -526,7 +569,7 @@ def test_del_dyndescription_context():
|
|||
def test_multi_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -555,7 +598,7 @@ def test_multi_dyndescription_context():
|
|||
def test_prop_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', properties=('test',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -573,7 +616,7 @@ def test_prop_dyndescription_context():
|
|||
def test_callback_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', Calculation(return_dynval))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -598,7 +641,7 @@ def test_callback_dyndescription_context():
|
|||
def test_mandatory_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -624,7 +667,7 @@ def test_mandatory_dyndescription_context():
|
|||
def test_increase_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -643,7 +686,7 @@ def test_increase_dyndescription_context():
|
|||
def test_decrease_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', properties=('mandatory',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -680,13 +723,13 @@ def test_dyndescription_root():
|
|||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None)}))
|
||||
st1 = StrOption('st', '', properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [boolean, st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [boolean, st1], identifiers=Calculation(return_list))
|
||||
with pytest.raises(ConfigError):
|
||||
cfg = Config(dod)
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyndescription_disable_suffix_root():
|
||||
def test_dyndescription_disable_identifier_root():
|
||||
boolean = BoolOption('boolean', '', True)
|
||||
disabled_property = Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
|
@ -695,7 +738,7 @@ def test_dyndescription_disable_suffix_root():
|
|||
'default': ParamValue(None)}))
|
||||
val = StrOption('val', '', ['ext1', 'ext2'], properties=(disabled_property,), multi=True)
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
od1 = OptionDescription('root', 'root', [boolean, val, dod])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
|
@ -706,7 +749,7 @@ def test_dyndescription_disable_suffix_root():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyndescription_disable_suffix_root_2():
|
||||
def test_dyndescription_disable_identifier_root_2():
|
||||
boolean = BoolOption('boolean', '', False)
|
||||
disabled_property = Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
|
@ -715,7 +758,7 @@ def test_dyndescription_disable_suffix_root_2():
|
|||
'default': ParamValue(None)}))
|
||||
val = StrOption('val', '', ['ext1', 'ext2'], properties=(disabled_property,), multi=True)
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
od1 = OptionDescription('root', 'root', [boolean, val, dod])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
|
@ -726,7 +769,7 @@ def test_dyndescription_disable_suffix_root_2():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_dyndescription_disable_suffix():
|
||||
def test_dyndescription_disable_identifier():
|
||||
boolean = BoolOption('boolean', '', True)
|
||||
disabled_property = Calculation(calc_value,
|
||||
Params(ParamValue('disabled'),
|
||||
|
@ -735,7 +778,7 @@ def test_dyndescription_disable_suffix():
|
|||
'default': ParamValue(None)}))
|
||||
val = StrOption('val', '', ['ext1', 'ext2'], properties=(disabled_property,), multi=True)
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(calc_value, Params(ParamOption(val, notraisepropertyerror=True))), properties=(disabled_property,))
|
||||
od = OptionDescription('root', 'root', [boolean, val, dod])
|
||||
od1 = OptionDescription('root', 'root', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -755,7 +798,7 @@ def test_requires_dyndescription():
|
|||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None)}))
|
||||
st1 = StrOption('st', '', properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od1, boolean])
|
||||
cfg = Config(od2)
|
||||
|
@ -811,7 +854,7 @@ def test_requires_dyndescription_boolean():
|
|||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None)}))
|
||||
st = StrOption('st', '', properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od, boolean1, boolean])
|
||||
cfg = Config(od2)
|
||||
|
@ -844,7 +887,7 @@ def test_requires_dyndescription_in_dyn():
|
|||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None)}))
|
||||
st = StrOption('st', '', properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [boolean, st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [boolean, st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -870,8 +913,8 @@ def test_requires_dyndescription_in_dyn():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def calc_value_not_same(param, condition, expected, default, suffix):
|
||||
if suffix == 'val1':
|
||||
def calc_value_not_same(param, condition, expected, default, identifier):
|
||||
if identifier == 'val1':
|
||||
index = 0
|
||||
else:
|
||||
index = 1
|
||||
|
@ -885,10 +928,10 @@ def test_requires_dyndescription_in_dyn_not_same():
|
|||
kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
|
||||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None),
|
||||
'suffix': ParamSuffix()}))
|
||||
'identifier': ParamIdentifier()}))
|
||||
st = StrOption('st', '', properties=(disabled_property,))
|
||||
dod1 = DynOptionDescription('dod1', '', [boolean], suffixes=Calculation(return_list))
|
||||
dod2 = DynOptionDescription('dod2', '', [st], suffixes=Calculation(return_list))
|
||||
dod1 = DynOptionDescription('dod1', '', [boolean], identifiers=Calculation(return_list))
|
||||
dod2 = DynOptionDescription('dod2', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod1, dod2])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -922,7 +965,7 @@ def test_requires_dyndescription2():
|
|||
kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
|
||||
'expected': ParamValue(False),
|
||||
'default': ParamValue(None)}))
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_list), properties=(disabled_property,))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_list), properties=(disabled_property,))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od1, boolean])
|
||||
cfg = Config(od2)
|
||||
|
@ -967,7 +1010,7 @@ def test_requires_dyndescription2():
|
|||
def test_validator_dyndescription():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', validators=[Calculation(return_true, Params((ParamSelfOption(), ParamValue('yes'))))], default='val')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -981,7 +1024,7 @@ def test_validator_dyndescription():
|
|||
def test_makedict_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -993,7 +1036,7 @@ def test_makedict_dyndescription_context():
|
|||
#def test_find_dyndescription_context():
|
||||
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
# st = StrOption('st', '')
|
||||
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
# od = OptionDescription('od', '', [dod, val1])
|
||||
# od2 = OptionDescription('od', '', [od])
|
||||
# cfg = Config(od2)
|
||||
|
@ -1015,7 +1058,7 @@ def test_makedict_dyndescription_context():
|
|||
def test_information_dyndescription_context():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '', informations={'testst': 'val2'})
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list), informations={'testod': 'val1'})
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list), informations={'testod': 'val1'})
|
||||
od = OptionDescription('od', '', [dod, val1])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -1049,7 +1092,7 @@ def test_all_dyndescription():
|
|||
dod = DynOptionDescription('dod', '', [st, ip, network, netmask, ch, ch1,
|
||||
boo, intr, floa, uni, port, broad,
|
||||
domain, email, url, username,
|
||||
filename], suffixes=Calculation(return_list))
|
||||
filename], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
assert cfg.option('dodval1.st').value.get() is None
|
||||
|
@ -1128,7 +1171,7 @@ def test_leadership_dyndescription():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1188,7 +1231,7 @@ def test_leadership_dyndescription_force_store_value_leader():
|
|||
st2 = StrOption('st2', "", multi=True, default=Calculation(return_list, Params(ParamOption(st1))))
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
val1 = StrOption('val1', '', multi=True, default=['val1', 'val2'])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [val1, st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1221,7 +1264,7 @@ def test_leadership_dyndescription_force_store_value():
|
|||
st2 = StrOption('st2', "", multi=True, properties=('force_store_value',), default=Calculation(return_list, Params(ParamOption(st1))))
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
val1 = StrOption('val1', '', multi=True, default=['val1', 'val2'])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [val1, st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1253,7 +1296,7 @@ def test_leadership_default_multi_dyndescription1():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1280,7 +1323,7 @@ def test_leadership_dyndescription_param():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [st, odval])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1339,7 +1382,7 @@ def test_leadership_default_multi_dyndescription2():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1421,7 +1464,7 @@ def test_leadership_dyndescription_param_leader():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
od = OptionDescription('od', '', [st, odval])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1433,7 +1476,7 @@ def test_leadership_default_multi_dyndescription3():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od2 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od2)
|
||||
|
@ -1461,7 +1504,7 @@ def test_leadership_dyndescription_param_follower():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list, Params(ParamOption(val2))))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list, Params(ParamOption(val2))))
|
||||
od = OptionDescription('od', '', [st, odval])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1473,7 +1516,7 @@ def test_leadership_default_multi_dyndescription_sub():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1498,7 +1541,7 @@ def test_leadership_submulti_dyndescription():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=submulti)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
std = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
std = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [std])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -1531,7 +1574,7 @@ def test_leadership_callback_dyndescription():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", Calculation(return_dynval, Params(kwargs={'value': ParamOption(st1)})), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st1 = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st1 = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [st1])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -1593,7 +1636,7 @@ def test_leadership_callback_value_dyndescription():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", Calculation(return_dynval, Params(kwargs={'value': ParamValue('val')})), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1610,7 +1653,7 @@ def test_leadership_callback_nomulti_dyndescription():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", Calculation(return_dynval, Params(ParamOption(v11))), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
stt = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
stt = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [stt])
|
||||
od2 = OptionDescription('od', '', [od1, v11])
|
||||
cfg = Config(od2)
|
||||
|
@ -1626,7 +1669,7 @@ def test_leadership_callback_samegroup_dyndescription():
|
|||
st2 = StrOption('st2', "", multi=True)
|
||||
st3 = StrOption('st3', "", Calculation(return_dynval, Params(ParamOption(st2))), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2, st3])
|
||||
stt = DynOptionDescription('st', '', [stm], suffixes=Calculation(return_list))
|
||||
stt = DynOptionDescription('st', '', [stm], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [stt])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -1655,7 +1698,7 @@ def test_leadership_callback_samegroup_dyndescription():
|
|||
|
||||
def test_invalid_conflict_dyndescription():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
dodinvalid = StrOption('dodinvalid', '')
|
||||
dod, dodinvalid
|
||||
with pytest.raises(ConflictError):
|
||||
|
@ -1668,7 +1711,7 @@ def test_leadership_default_multi_dyndescription4():
|
|||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
od1 = OptionDescription('od1', '', [stm])
|
||||
st = DynOptionDescription('st', '', [od1], suffixes=Calculation(return_list))
|
||||
st = DynOptionDescription('st', '', [od1], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -1698,8 +1741,8 @@ def test_leadership_default_multi_dyndescription4():
|
|||
|
||||
def test_subdynod_dyndescription_root():
|
||||
st2 = StrOption('st2', '')
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], suffixes=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], suffixes=Calculation(return_list))
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], identifiers=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], identifiers=Calculation(return_list))
|
||||
st3 = StrOption('st3', '', Calculation(return_dynval, Params(ParamDynOption(st2, ['val1', 'a']))))
|
||||
# FIXME st4 = StrOption('st4', '', Calculation(return_dynval, Params(ParamOption(st2))), multi=True)
|
||||
od1 = OptionDescription('od', '', [dod, st3]) #, st4])
|
||||
|
@ -1764,8 +1807,8 @@ def test_subdynod_dyndescription_root():
|
|||
|
||||
def test_subdynod_dyndescription():
|
||||
st2 = StrOption('st2', '')
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], suffixes=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], suffixes=Calculation(return_list))
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], identifiers=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
st3 = StrOption('st3', '', Calculation(return_dynval, Params(ParamDynOption(st2, ['val1', 'a']))))
|
||||
od = OptionDescription('od', '', [od1, st3]) #, st4])
|
||||
|
@ -1830,8 +1873,8 @@ def test_subdynod_dyndescription():
|
|||
def test_subdynod_dyndescription_2():
|
||||
st2 = StrOption('st2', '')
|
||||
st1 = StrOption('st1', '', default=['a', 'b'], multi=True)
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], suffixes=Calculation(return_list, Params(ParamOption(st1))))
|
||||
dod = DynOptionDescription('dod', '', [dod1, st1], suffixes=Calculation(return_list))
|
||||
dod1 = DynOptionDescription('dod1', '', [st2], identifiers=Calculation(return_list, Params(ParamOption(st1))))
|
||||
dod = DynOptionDescription('dod', '', [dod1, st1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
st3 = StrOption('st3', '', Calculation(return_dynval, Params(ParamDynOption(st2, ['val1', 'a']))))
|
||||
od = OptionDescription('od', '', [od1, st3]) #, st4])
|
||||
|
@ -1868,8 +1911,8 @@ def test_subdynod_dyndescription_leadership():
|
|||
st1 = StrOption('st1', '', multi=True)
|
||||
st2 = StrOption('st2', '', multi=True)
|
||||
stm = Leadership('stm', '', [st1, st2])
|
||||
dod1 = DynOptionDescription('dod1', '', [stm], suffixes=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], suffixes=Calculation(return_list))
|
||||
dod1 = DynOptionDescription('dod1', '', [stm], identifiers=Calculation(return_list, Params(ParamValue(['a', 'b']))))
|
||||
dod = DynOptionDescription('dod', '', [dod1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
st3 = StrOption('st3', '', Calculation(return_dynval, Params(ParamDynOption(st1, ['val1', 'a']))), multi=True)
|
||||
# FIXME st4 = StrOption('st4', '', Calculation(return_dynval, Params(ParamOption(st2))), multi=True)
|
||||
|
@ -1916,7 +1959,7 @@ def test_dyndescription_symlink():
|
|||
st = StrOption('st', '')
|
||||
st2 = SymLinkOption('st2', st)
|
||||
# with pytest.raises(ConfigError):
|
||||
dod = DynOptionDescription('dod', '', [st, st2], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st, st2], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st': None, 'dodval1.st2': None, 'dodval2.st': None, 'dodval2.st2': None}
|
||||
|
@ -1927,10 +1970,10 @@ def test_dyndescription_symlink():
|
|||
|
||||
def test_dyndescription_symlink_not_same():
|
||||
st = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
st2 = SymLinkOption('st2', st)
|
||||
# with pytest.raises(ConfigError):
|
||||
dod2 = DynOptionDescription('sdod', '', [st2], suffixes=Calculation(return_list))
|
||||
dod2 = DynOptionDescription('sdod', '', [st2], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod, dod2])
|
||||
cfg = Config(od)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st': None, 'dodval2.st': None, 'sdodval1.st2': [None, None], 'sdodval2.st2': [None, None]}
|
||||
|
@ -1942,7 +1985,7 @@ def test_dyndescription_symlink_not_same():
|
|||
def test_dyndescription_symlink_outside():
|
||||
st = StrOption('st', '')
|
||||
# with pytest.raises(ConfigError):
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
st2 = SymLinkOption('st2', st)
|
||||
od = OptionDescription('od', '', [dod, st2])
|
||||
cfg = Config(od)
|
||||
|
@ -1956,7 +1999,7 @@ def test_dyndescription_symlink_inside():
|
|||
st = StrOption('st', '')
|
||||
st2 = SymLinkOption('st2', st)
|
||||
# with pytest.raises(ConfigError):
|
||||
dod = DynOptionDescription('dod', '', [st2], suffixes=Calculation(return_list))
|
||||
dod = DynOptionDescription('dod', '', [st2], identifiers=Calculation(return_list))
|
||||
od = OptionDescription('od', '', [dod, st])
|
||||
cfg = Config(od)
|
||||
assert parse_od_get(cfg.value.get()) == {'dodval1.st2': None, 'dodval2.st2': None, 'st': None}
|
||||
|
@ -1975,7 +2018,7 @@ def test_nocallback_dyndescription():
|
|||
|
||||
def test_invalid_samevalue_dyndescription():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_same_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_same_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -1985,7 +2028,7 @@ def test_invalid_samevalue_dyndescription():
|
|||
|
||||
def test_invalid_name_dyndescription():
|
||||
st1 = StrOption('st', '')
|
||||
dod = DynOptionDescription('dod', '', [st1], suffixes=Calculation(return_wrong_list))
|
||||
dod = DynOptionDescription('dod', '', [st1], identifiers=Calculation(return_wrong_list))
|
||||
od1 = OptionDescription('od', '', [dod])
|
||||
cfg = Config(od1)
|
||||
with pytest.raises(ValueError):
|
||||
|
@ -1997,7 +2040,7 @@ def test_leadership_dyndescription_convert():
|
|||
st1 = StrOption('st1', "", multi=True)
|
||||
st2 = StrOption('st2', "", multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2])
|
||||
st = ConvertDynOptionDescription('st', '', [stm], suffixes=Calculation(return_list_dot))
|
||||
st = ConvertDynOptionDescription('st', '', [stm], identifiers=Calculation(return_list_dot))
|
||||
od = OptionDescription('od', '', [st])
|
||||
od1 = OptionDescription('od', '', [od])
|
||||
cfg = Config(od1)
|
||||
|
@ -2057,7 +2100,7 @@ def test_leadership_callback_samegroup_dyndescription_convert():
|
|||
st2 = StrOption('st2', "", multi=True)
|
||||
st3 = StrOption('st3', "", Calculation(return_dynval, Params(ParamOption(st2))), multi=True)
|
||||
stm = Leadership('st1', '', [st1, st2, st3])
|
||||
stt = ConvertDynOptionDescription('st', '', [stm], suffixes=Calculation(return_list_dot))
|
||||
stt = ConvertDynOptionDescription('st', '', [stm], identifiers=Calculation(return_list_dot))
|
||||
od1 = OptionDescription('od', '', [stt])
|
||||
od2 = OptionDescription('od', '', [od1])
|
||||
cfg = Config(od2)
|
||||
|
@ -2088,7 +2131,7 @@ def test_dyn_with_leader_hidden_in_config():
|
|||
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=('hidden',))
|
||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('hidden',))
|
||||
dyn = DynOptionDescription('leader', '', [interface1], suffixes=Calculation(return_list))
|
||||
dyn = DynOptionDescription('leader', '', [interface1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('root', '', [dyn])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
|
@ -2110,7 +2153,7 @@ def test_dyn_with_leader_hidden_in_config2():
|
|||
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=('hidden',))
|
||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
dyn = DynOptionDescription('leader', '', [interface1], suffixes=Calculation(return_list))
|
||||
dyn = DynOptionDescription('leader', '', [interface1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('root', '', [dyn])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
|
@ -2135,7 +2178,7 @@ def test_dyn_leadership_requires():
|
|||
'index': ParamIndex()}))
|
||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=(disabled_property,))
|
||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
dyn = DynOptionDescription('leader', '', [interface1], suffixes=Calculation(return_list))
|
||||
dyn = DynOptionDescription('leader', '', [interface1], identifiers=Calculation(return_list))
|
||||
od1 = OptionDescription('toto', '', [dyn])
|
||||
cfg = Config(od1)
|
||||
cfg.property.read_write()
|
||||
|
@ -2175,7 +2218,7 @@ def test_dyn_leadership_mandatory():
|
|||
hostname = DomainnameOption(name="hostname_", doc="hostname_", multi=True, type='hostname')
|
||||
choice = ChoiceOption(name="type_", doc="type_", values=('A', 'CNAME'), multi=True, default_multi="A")
|
||||
leadership = Leadership(name="hostname_", doc="hostname_", children=[hostname, choice], properties=frozenset({Calculation(calc_value, Params(ParamValue('hidden'), kwargs={'condition': ParamOption(is_auto, notraisepropertyerror=True), 'expected': ParamValue(True)}))}))
|
||||
dyn = DynOptionDescription(name="nsd_zone_", doc="Zone ", suffixes=Calculation(calc_value, Params((ParamOption(nsd_zones_all, notraisepropertyerror=True)))), children=[is_auto, leadership], properties=frozenset({"normal"}))
|
||||
dyn = DynOptionDescription(name="nsd_zone_", doc="Zone ", identifiers=Calculation(calc_value, Params((ParamOption(nsd_zones_all, notraisepropertyerror=True)))), children=[is_auto, leadership], properties=frozenset({"normal"}))
|
||||
od1 = OptionDescription(name="nsd", doc="nsd", children=[nsd_zones_all, dyn])
|
||||
cfg = Config(od1)
|
||||
assert cfg.value.mandatory() == []
|
||||
|
@ -2184,8 +2227,8 @@ def test_dyn_leadership_mandatory():
|
|||
|
||||
def test_dyn_symlink():
|
||||
remotes = StrOption("remotes", "Remotes", ['a', 'b', 'c'], multi=True)
|
||||
remote_ip = StrOption("remote_ip_", "Remote IP", Calculation(calc_value, Params(ParamSuffix())))
|
||||
dyn_remote = DynOptionDescription("remote_", "Account for ", suffixes=Calculation(calc_value, Params((ParamOption(remotes)))), children=[remote_ip])
|
||||
remote_ip = StrOption("remote_ip_", "Remote IP", Calculation(calc_value, Params(ParamIdentifier())))
|
||||
dyn_remote = DynOptionDescription("remote_", "Account for ", identifiers=Calculation(calc_value, Params((ParamOption(remotes)))), children=[remote_ip])
|
||||
name = SymLinkOption("name", opt=remote_ip)
|
||||
od1 = OptionDescription(name="accounts", doc="accounts.remote_.remote_ip_", children=[remotes, dyn_remote, name])
|
||||
cfg = Config(od1)
|
||||
|
@ -2198,8 +2241,8 @@ def test_dyn_symlink():
|
|||
|
||||
def test_dyn_callback_with_not_dyn():
|
||||
remotes = StrOption("remotes", "Remotes", ['a', 'b', 'c'], multi=True)
|
||||
remote_ip = StrOption("remote_ip_", "Remote IP", Calculation(calc_value, Params(ParamSuffix())))
|
||||
dyn_remote = DynOptionDescription("remote_", "Account for ", suffixes=Calculation(calc_value, Params((ParamOption(remotes)))), children=[remote_ip])
|
||||
remote_ip = StrOption("remote_ip_", "Remote IP", Calculation(calc_value, Params(ParamIdentifier())))
|
||||
dyn_remote = DynOptionDescription("remote_", "Account for ", identifiers=Calculation(calc_value, Params((ParamOption(remotes)))), children=[remote_ip])
|
||||
names = StrOption('names', '', Calculation(calc_value, Params(ParamOption(remote_ip))), multi=True)
|
||||
od1 = OptionDescription(name="accounts", doc="accounts.remote_.remote_ip_", children=[remotes, dyn_remote, names])
|
||||
cfg = Config(od1)
|
||||
|
@ -2217,7 +2260,7 @@ def test_dyn_link_subdyn():
|
|||
password2 = StrOption(name="password", doc="password", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
user = OptionDescription(name="user", doc="user", children=[name, password2])
|
||||
sub = OptionDescription(name="sub", doc="sub", children=[user])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[user_database, database_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2279,7 +2322,7 @@ def test_dyn_link_subdyn_2():
|
|||
name = StrOption(name="name", doc="name", properties=('mandatory',))
|
||||
user = OptionDescription(name="user", doc="user", children=[name, password2])
|
||||
sub = OptionDescription(name="sub", doc="sub", children=[user])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[password, sub])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[user_database, database_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2342,10 +2385,10 @@ def test_dyn_link_subdyn_twice():
|
|||
login = StrOption(name="login", doc="login", default=Calculation(calc_value, Params((ParamOption(name)))), properties=('mandatory',))
|
||||
password2 = StrOption(name="password2", doc="password2", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
database_names = StrOption(name="database_names", doc="database_names", multi=True, default=["srep", "snom", "srem"])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = OptionDescription(name="databases", doc="database", children=[password, user_database])
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1", "schema2", "schema3"])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[database_names, databases])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[database_names, databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2517,11 +2560,11 @@ def test_dyn_link_subdyn_tree():
|
|||
login = StrOption(name="login", doc="login", default=Calculation(calc_value, Params((ParamOption(name)))), properties=('mandatory',))
|
||||
password2 = StrOption(name="password2", doc="password2", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
user_names = StrOption(name="users", doc="users", multi=True, default=["user1"])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(user_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(user_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
database_names = StrOption(name="database_names", doc="database_names", multi=True, default=["srep"])
|
||||
databases = DynOptionDescription(name="db_", doc="database", suffixes=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[user_names, password, user_database])
|
||||
databases = DynOptionDescription(name="db_", doc="database", identifiers=Calculation(calc_value, Params((ParamOption(database_names, notraisepropertyerror=True)))), children=[user_names, password, user_database])
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1"])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[database_names, databases])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[database_names, databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2595,9 +2638,9 @@ def test_dyn_link_subdyn_same_variable():
|
|||
login = StrOption(name="login", doc="login", default=Calculation(calc_value, Params((ParamOption(name)))), properties=('mandatory',))
|
||||
password2 = StrOption(name="password2", doc="password2", default=Calculation(calc_value, Params((ParamOption(password)))), properties=('mandatory',))
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1"])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = DynOptionDescription(name="db_", doc="database", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[password, user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = DynOptionDescription(name="db_", doc="database", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[password, user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2696,9 +2739,9 @@ def test_dyn_link_subdyn_disabled():
|
|||
'default': ParamValue(None)}))
|
||||
password2 = StrOption(name="password2", doc="password2", default=Calculation(calc_value, Params((ParamOption(password)))), properties=(disabled_property,))
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1"])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = DynOptionDescription(name="db_", doc="database", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[password, user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
user_database = DynOptionDescription(name="user_database_", doc="user database", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[name, login, password2])
|
||||
databases = DynOptionDescription(name="db_", doc="database", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[password, user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root)
|
||||
|
@ -2757,8 +2800,8 @@ def test_option_dynoption_display_name():
|
|||
password = StrOption(name="password", doc="password")
|
||||
schema_names = StrOption(name="database_schemas", doc="database_schemas", multi=True, default=["schema1"])
|
||||
user_database = OptionDescription(name="user_database", doc="user database", children=[password])
|
||||
databases = DynOptionDescription(name="db_", doc="database", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
databases = DynOptionDescription(name="db_", doc="database", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[user_database])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params((ParamOption(schema_names, notraisepropertyerror=True)))), children=[databases])
|
||||
socle = OptionDescription(name="socle", doc="socle", children=[schema, schema_names])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[socle])
|
||||
cfg = Config(root, display_name=display_name)
|
||||
|
@ -2768,7 +2811,7 @@ def test_option_dynoption_display_name():
|
|||
def test_option_dynoption_param_information():
|
||||
info1 = StrOption("info1", '', Calculation(calc_value, Params(ParamSelfInformation('key'))), informations={'key': 'value'})
|
||||
info2 = StrOption("info2", '', Calculation(calc_value, Params(ParamInformation('key', option=info1))))
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", suffixes=Calculation(calc_value, Params(ParamValue(['1', '2']))), children=[info1, info2])
|
||||
schema = DynOptionDescription(name="schema_", doc="schema_", identifiers=Calculation(calc_value, Params(ParamValue(['1', '2']))), children=[info1, info2])
|
||||
root = OptionDescription(name="baseoption", doc="baseoption", children=[schema])
|
||||
cfg = Config(root, display_name=display_name)
|
||||
assert parse_od_get(cfg.value.get()) == {'schema_1.info1': 'value', 'schema_1.info2': 'value', 'schema_2.info1': 'value', 'schema_2.info2': 'value'}
|
||||
|
@ -2777,10 +2820,10 @@ def test_option_dynoption_param_information():
|
|||
|
||||
|
||||
def test_callback_list_dyndescription_information():
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamSuffix())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamInformation('suffix'))))
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamIdentifier())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamInformation('identifier'))))
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od], informations={'suffix': ['ival1', 'ival2']})
|
||||
od2 = OptionDescription('od', '', [od], informations={'identifier': ['ival1', 'ival2']})
|
||||
cfg = Config(od2)
|
||||
owner = cfg.owner.get()
|
||||
assert cfg.option('od.dodival1.st').value.get() == ['ival1', 'val2']
|
||||
|
@ -2792,16 +2835,16 @@ def test_callback_list_dyndescription_information():
|
|||
assert cfg.option('od.dodival2.st').value.get() == ['ival2', 'val2']
|
||||
assert cfg.option('od.dodival1.st').owner.get() == owner
|
||||
assert cfg.option('od.dodival2.st').owner.isdefault()
|
||||
cfg.information.set('suffix', ['ival3'])
|
||||
cfg.information.set('identifier', ['ival3'])
|
||||
assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2']
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
def test_callback_list_dyndescription_information_not_list():
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamSuffix())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], suffixes=["sval1", Calculation(return_dynval, Params(ParamInformation('suffix')))])
|
||||
st = StrOption('st', '', Calculation(return_list2, Params(ParamIdentifier())), multi=True, properties=('notunique',))
|
||||
dod = DynOptionDescription('dod', '', [st], identifiers=["sval1", Calculation(return_dynval, Params(ParamInformation('identifier')))])
|
||||
od = OptionDescription('od', '', [dod])
|
||||
od2 = OptionDescription('od', '', [od], informations={'suffix': 'ival2'})
|
||||
od2 = OptionDescription('od', '', [od], informations={'identifier': 'ival2'})
|
||||
cfg = Config(od2)
|
||||
owner = cfg.owner.get()
|
||||
assert cfg.option('od.dodsval1.st').value.get() == ['sval1', 'val2']
|
||||
|
@ -2813,6 +2856,6 @@ def test_callback_list_dyndescription_information_not_list():
|
|||
assert cfg.option('od.dodival2.st').value.get() == ['ival2', 'val2']
|
||||
assert cfg.option('od.dodsval1.st').owner.get() == owner
|
||||
assert cfg.option('od.dodival2.st').owner.isdefault()
|
||||
cfg.information.set('suffix', 'ival3')
|
||||
cfg.information.set('identifier', 'ival3')
|
||||
assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2']
|
||||
# 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 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').defaultmulti() == 'value'
|
||||
assert cfg.option('leadership.netmask_admin_eth0').value.defaultmulti() == 'value'
|
||||
if config_type == 'tiramisu-api':
|
||||
cfg.send()
|
||||
# assert not list_sessions()
|
||||
|
|
|
@ -681,7 +681,7 @@ def test_mandatory_od_disabled():
|
|||
# assert not list_sessions()
|
||||
|
||||
|
||||
def return_list(val=None, suffix=None):
|
||||
def return_list(val=None, identifier=None):
|
||||
if val:
|
||||
return val
|
||||
else:
|
||||
|
@ -690,7 +690,7 @@ def return_list(val=None, suffix=None):
|
|||
|
||||
#def test_mandatory_dyndescription():
|
||||
# st = StrOption('st', '', properties=('mandatory',))
|
||||
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||
# od = OptionDescription('od', '', [dod])
|
||||
# od2 = OptionDescription('od', '', [od])
|
||||
# cfg = Config(od2)
|
||||
|
@ -701,7 +701,7 @@ def return_list(val=None, suffix=None):
|
|||
#def test_mandatory_dyndescription_context():
|
||||
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
# st = StrOption('st', '', properties=('mandatory',))
|
||||
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
|
||||
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||
# od = OptionDescription('od', '', [dod, val1])
|
||||
# od2 = OptionDescription('od', '', [od])
|
||||
# cfg = Config(od2)
|
||||
|
|
|
@ -20,7 +20,7 @@ def a_func():
|
|||
return None
|
||||
|
||||
|
||||
def display_name(*args):
|
||||
def display_name(*args, with_quote=False):
|
||||
return 'display_name'
|
||||
|
||||
|
||||
|
|
|
@ -294,7 +294,7 @@ def test_callback(config_type):
|
|||
cfg.option('val1').value.set('new-val')
|
||||
assert cfg.option('val1').value.get() == 'new-val'
|
||||
with pytest.raises(ConfigError):
|
||||
assert cfg.option('val1').defaultmulti() == None
|
||||
assert cfg.option('val1').value.defaultmulti() == None
|
||||
cfg.option('val1').value.reset()
|
||||
assert cfg.option('val1').value.get() == 'val'
|
||||
# assert not list_sessions()
|
||||
|
@ -548,7 +548,7 @@ def test_callback_multi(config_type):
|
|||
cfg = get_config(cfg, config_type)
|
||||
assert cfg.option('val1').value.get() == ['val']
|
||||
cfg.option('val1').value.set(['new-val'])
|
||||
assert cfg.option('val1').defaultmulti() == None
|
||||
assert cfg.option('val1').value.defaultmulti() == None
|
||||
assert cfg.option('val1').value.get() == ['new-val']
|
||||
cfg.option('val1').value.set(['new-val', 'new-val2'])
|
||||
assert cfg.option('val1').value.get() == ['new-val', 'new-val2']
|
||||
|
@ -945,7 +945,7 @@ def test_consistency_leader_and_followers_leader_mandatory_transitive():
|
|||
try:
|
||||
cfg.option('val1.val2', 0).value.get()
|
||||
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:
|
||||
raise Exception('must raises')
|
||||
assert list(cfg.value.mandatory()) == []
|
||||
|
@ -963,7 +963,7 @@ def test_callback_leader_and_followers_leader_list(config_type):
|
|||
assert cfg.option('val1.val1').value.get() == ['val', 'val']
|
||||
assert cfg.option('val1.val2', 0).value.get() == None
|
||||
assert cfg.option('val1.val2', 1).value.get() == None
|
||||
default_multi = cfg.option('val1.val1').defaultmulti()
|
||||
default_multi = cfg.option('val1.val1').value.defaultmulti()
|
||||
cfg.option('val1.val1').value.set(['val', 'val', default_multi])
|
||||
assert cfg.option('val1.val1').value.get() == ['val', 'val', None]
|
||||
assert cfg.option('val1.val2', 0).value.get() == None
|
||||
|
@ -1502,6 +1502,22 @@ def test_leadership_callback_description(config_type):
|
|||
# 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():
|
||||
opt1 = BoolOption('opt1', 'Option 1', Calculation(return_raise))
|
||||
opt2 = BoolOption('opt2', 'Option 2', Calculation(return_valueerror))
|
||||
|
|
23
tests/test_option_regexp.py
Normal file
23
tests/test_option_regexp.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
""" 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')
|
|
@ -514,10 +514,10 @@ def test_accepts_multiple_changes_from_option():
|
|||
od1 = OptionDescription("options", "", [s])
|
||||
cfg = Config(od1)
|
||||
cfg.option('string').value.set("egg")
|
||||
assert cfg.option('string').default() == "string"
|
||||
assert cfg.option('string').value.default() == "string"
|
||||
assert cfg.option('string').value.get() == "egg"
|
||||
cfg.option('string').value.set('blah')
|
||||
assert cfg.option('string').default() == "string"
|
||||
assert cfg.option('string').value.default() == "string"
|
||||
assert cfg.option('string').value.get() == "blah"
|
||||
cfg.option('string').value.set('bol')
|
||||
assert cfg.option('string').value.get() == 'bol'
|
||||
|
@ -626,25 +626,195 @@ def test_reset_properties_force_store_value():
|
|||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
cfg = Config(od1)
|
||||
assert cfg.property.exportation() == {None: {None: frozenset({'validator', 'warnings', 'cache'})}}
|
||||
assert cfg.property.exportation() == {'properties': {None: {None: frozenset({'cache',
|
||||
'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')
|
||||
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()
|
||||
assert cfg.property.exportation() == {None: {}}
|
||||
assert cfg.property.exportation() == {'properties': {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')
|
||||
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}}
|
||||
assert cfg.property.exportation() == {
|
||||
'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()
|
||||
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}}
|
||||
assert cfg.property.exportation() == {
|
||||
'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')
|
||||
assert cfg.property.exportation() == \
|
||||
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
|
||||
{
|
||||
'properties': {None: {None: frozenset({'frozen'})},
|
||||
'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')
|
||||
assert cfg.property.exportation() == \
|
||||
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
|
||||
{
|
||||
'properties': {None: {None: frozenset({'frozen'})}, '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.option('gc.dummy').property.add('test')
|
||||
assert cfg.property.exportation() == \
|
||||
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
|
||||
{
|
||||
'properties': {None: {None: frozenset({'frozen'})}, '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'}),
|
||||
}
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
@ -674,10 +844,79 @@ def test_set_modified_value():
|
|||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||
cfg = Config(od1)
|
||||
assert cfg.property.exportation() == {None: {None: frozenset({'warnings', 'validator', 'cache'})}}
|
||||
cfg.property.importation({None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}})
|
||||
assert cfg.property.exportation() == {
|
||||
'properties': {None: {None: frozenset({'cache',
|
||||
'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() == \
|
||||
{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()
|
||||
|
||||
|
||||
|
@ -694,7 +933,7 @@ def test_set_modified_value():
|
|||
#
|
||||
#
|
||||
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 = _('the value of "{0}" is {1}')
|
||||
properties = _('properties')
|
||||
|
@ -749,8 +988,7 @@ def test_pprint():
|
|||
|
||||
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)) + ')'
|
||||
print('FIXME')
|
||||
# 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
|
||||
|
||||
err = None
|
||||
|
@ -759,8 +997,7 @@ def test_pprint():
|
|||
except PropertiesOptionError as error:
|
||||
err = error
|
||||
|
||||
print('FIXME')
|
||||
# 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
|
||||
#try:
|
||||
|
@ -781,7 +1018,7 @@ def test_pprint():
|
|||
except Exception as 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
|
||||
|
||||
err = None
|
||||
|
@ -790,13 +1027,13 @@ def test_pprint():
|
|||
except Exception as 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
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
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 = _('the value of "{0}" is {1}')
|
||||
properties = _('properties')
|
||||
|
@ -851,7 +1088,7 @@ def test_pprint_not_todict():
|
|||
|
||||
list_disabled = '"disabled"'
|
||||
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
|
||||
|
||||
err = None
|
||||
|
@ -860,7 +1097,7 @@ def test_pprint_not_todict():
|
|||
except PropertiesOptionError as 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
|
||||
try:
|
||||
|
@ -868,7 +1105,7 @@ def test_pprint_not_todict():
|
|||
except Exception as 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
|
||||
|
||||
err = None
|
||||
|
@ -877,7 +1114,7 @@ def test_pprint_not_todict():
|
|||
except Exception as 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
|
||||
# assert not list_sessions()
|
||||
|
||||
|
|
|
@ -158,13 +158,38 @@ def test_with_many_subgroups(config_type):
|
|||
|
||||
def test_password_option(config_type):
|
||||
o = PasswordOption('o', '')
|
||||
od1 = OptionDescription('d', '', [o])
|
||||
o1 = PasswordOption('o1', '', min_len=4)
|
||||
o2 = PasswordOption('o2', '', max_len=4)
|
||||
o3 = PasswordOption('o3', '', forbidden_char=['p'])
|
||||
od1 = OptionDescription('d', '', [o, o1, o2, o3])
|
||||
cfg = Config(od1)
|
||||
cfg = get_config(cfg, config_type)
|
||||
|
||||
cfg.option('o').value.set('a_valid_password')
|
||||
with pytest.raises(ValueError):
|
||||
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()
|
||||
|
||||
|
||||
|
|
|
@ -334,7 +334,7 @@ def test_validator_warning(config_type):
|
|||
assert len(w) == 1
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
cfg.nowarnings.option('opt2').value.set('val')
|
||||
|
@ -352,7 +352,7 @@ def test_validator_warning(config_type):
|
|||
assert len(w) == 1
|
||||
if config_type != 'tiramisu-api':
|
||||
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 pytest.raises(ValueError):
|
||||
|
@ -365,9 +365,9 @@ def test_validator_warning(config_type):
|
|||
assert len(w) == 2
|
||||
if config_type != 'tiramisu-api':
|
||||
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 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()
|
||||
|
||||
|
||||
|
@ -436,13 +436,13 @@ def test_validator_warning_leadership(config_type):
|
|||
assert len(w) == 1
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
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'])
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
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'])
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
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'])
|
||||
if config_type != 'tiramisu-api':
|
||||
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:
|
||||
assert len(w) == 3
|
||||
# assert not list_sessions()
|
||||
|
@ -1046,12 +1046,12 @@ def test_validator_error_prefix():
|
|||
try:
|
||||
cfg.option('b').value.set(1)
|
||||
except Exception as err:
|
||||
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {}').format('"a"')
|
||||
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {0}').format('"a"')
|
||||
try:
|
||||
cfg.option('b').value.set(1)
|
||||
except Exception as err:
|
||||
err.prefix = ''
|
||||
assert str(err) == _('value is identical to {}').format('"a"')
|
||||
assert str(err) == _('value is identical to {0}').format('"a"')
|
||||
# assert not list_sessions()
|
||||
|
||||
|
||||
|
|
|
@ -196,12 +196,10 @@ def test_requires_same_action(config_type):
|
|||
submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
||||
if config_type == 'tiramisu':
|
||||
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)) + ')'
|
||||
print('FIXME')
|
||||
# assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_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))
|
||||
#access to cache
|
||||
print('FIXME')
|
||||
# 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:
|
||||
# FIXME
|
||||
assert str(err) == 'error'
|
||||
|
@ -428,9 +426,9 @@ def test_requires_transitive_unrestraint(config_type):
|
|||
#
|
||||
if config_type == 'tiramisu-api':
|
||||
cfg.send()
|
||||
assert cfg_ori.unrestraint.option('activate_service_web').property.get() == {'disabled'}
|
||||
print('FIXME')
|
||||
# assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
||||
assert cfg_ori.option('activate_service_web').property.get() == {'disabled'}
|
||||
# FIXME 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()
|
||||
|
||||
|
||||
|
@ -594,7 +592,7 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
|
|||
cfg.option('activate_service').value.set(False)
|
||||
except ConfigError as 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:
|
||||
cfg.option('activate_service').value.set(False)
|
||||
#
|
||||
|
@ -610,7 +608,7 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
|
|||
cfg.option('ip_address_service_web').value.get()
|
||||
except ConfigError as 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 str(req) == error_msg
|
||||
del req
|
||||
|
@ -622,14 +620,14 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
|
|||
cfg = get_config(cfg_ori, config_type)
|
||||
except ConfigError as 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:
|
||||
cfg = get_config(cfg_ori, config_type)
|
||||
try:
|
||||
cfg.option('ip_address_service_web').value.get()
|
||||
except ConfigError as 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 str(req) == error_msg
|
||||
del req
|
||||
|
|
|
@ -115,18 +115,18 @@ def test_append_submulti():
|
|||
#
|
||||
assert cfg.option('multi2').value.get() == []
|
||||
assert cfg.option('multi2').owner.get() == owners.default
|
||||
cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti()])
|
||||
cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti()])
|
||||
assert cfg.option('multi2').owner.get() == owner
|
||||
assert cfg.option('multi2').value.get() == [['yes']]
|
||||
cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti(), ['no']])
|
||||
cfg.option('multi2').value.set([cfg.option('multi2').value.defaultmulti(), ['no']])
|
||||
assert cfg.option('multi2').value.get() == [['yes'], ['no']]
|
||||
#
|
||||
assert cfg.option('multi3').value.get() == [['yes']]
|
||||
assert cfg.option('multi3').owner.get() == owners.default
|
||||
cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), []])
|
||||
cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), []])
|
||||
assert cfg.option('multi3').owner.get() == owner
|
||||
assert cfg.option('multi3').value.get() == [['yes'], []]
|
||||
cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), [], ['no']])
|
||||
cfg.option('multi3').value.set([cfg.option('multi2').value.defaultmulti(), [], ['no']])
|
||||
assert cfg.option('multi3').value.get() == [['yes'], [], ['no']]
|
||||
# assert not list_sessions()
|
||||
|
||||
|
@ -193,7 +193,7 @@ def test_callback_submulti_str():
|
|||
owner = cfg.owner.get()
|
||||
assert cfg.option('multi').owner.get() == owners.default
|
||||
assert cfg.option('multi').value.get() == [['val']]
|
||||
cfg.option('multi').value.set([['val'], cfg.option('multi').defaultmulti()])
|
||||
cfg.option('multi').value.set([['val'], cfg.option('multi').value.defaultmulti()])
|
||||
assert cfg.option('multi').owner.get() == owner
|
||||
assert cfg.option('multi').value.get() == [['val'], ['val']]
|
||||
cfg.option('multi').value.reset()
|
||||
|
@ -209,10 +209,10 @@ def test_callback_submulti_list():
|
|||
owner = cfg.owner.get()
|
||||
assert cfg.option('multi').value.get() == [['val', 'val']]
|
||||
assert cfg.option('multi').owner.get() == owners.default
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()])
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()])
|
||||
assert cfg.option('multi').owner.get() == owner
|
||||
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']]
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti(), cfg.option('multi').defaultmulti()])
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti(), cfg.option('multi').value.defaultmulti()])
|
||||
assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']]
|
||||
cfg.option('multi').value.reset()
|
||||
assert cfg.option('multi').owner.get() == owners.default
|
||||
|
@ -227,7 +227,7 @@ def test_callback_submulti_list_list():
|
|||
owner = cfg.owner.get()
|
||||
assert cfg.option('multi').value.get() == [['val', 'val']]
|
||||
assert cfg.option('multi').owner.get() == owners.default
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()])
|
||||
cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').value.defaultmulti()])
|
||||
assert cfg.option('multi').owner.get() == owner
|
||||
assert cfg.option('multi').value.get() == [['val', 'val'], []]
|
||||
cfg.option('multi').value.reset()
|
||||
|
|
|
@ -54,17 +54,13 @@ def test_symlink_default(config_type):
|
|||
assert not cfg.option('c').ismulti()
|
||||
assert not cfg.option('s1.b').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('c').value.default()
|
||||
with pytest.raises(ConfigError):
|
||||
assert not cfg.option('s1.b').defaultmulti()
|
||||
assert not cfg.option('s1.b').value.defaultmulti()
|
||||
with pytest.raises(ConfigError):
|
||||
assert not cfg.option('c').defaultmulti()
|
||||
assert not cfg.option('c').value.defaultmulti()
|
||||
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('c').value.default()
|
||||
## assert not list_sessions()
|
||||
|
@ -82,19 +78,15 @@ def test_symlink_default_multi(config_type):
|
|||
assert cfg.option('c').ismulti()
|
||||
assert not cfg.option('s1.b').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('c').value.default() == [False]
|
||||
assert cfg.option('s1.b').defaultmulti()
|
||||
assert cfg.option('c').defaultmulti()
|
||||
assert cfg.option('s1.b').value.defaultmulti()
|
||||
assert cfg.option('c').value.defaultmulti()
|
||||
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('c').value.default() == [False]
|
||||
assert cfg.option('s1.b').defaultmulti()
|
||||
assert cfg.option('c').defaultmulti()
|
||||
assert cfg.option('s1.b').value.defaultmulti()
|
||||
assert cfg.option('c').value.defaultmulti()
|
||||
## assert not list_sessions()
|
||||
|
||||
|
||||
|
@ -297,11 +289,59 @@ def test_symlink_leader():
|
|||
|
||||
|
||||
def test_symlink_followers():
|
||||
a = StrOption('a', "", multi=True)
|
||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||
netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', a)
|
||||
with pytest.raises(ValueError):
|
||||
Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||
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 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):
|
||||
|
|
|
@ -14,11 +14,29 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""Configuration management library written in python
|
||||
"""
|
||||
from .function import calc_value, calc_value_property_help, valid_ip_netmask, \
|
||||
valid_network_netmask, valid_in_network, valid_broadcast, \
|
||||
valid_not_equal, function_waiting_for_dict
|
||||
from .autolib import Calculation, Params, ParamOption, ParamDynOption, ParamSelfOption, \
|
||||
ParamValue, ParamIndex, ParamSuffix, ParamInformation, ParamSelfInformation
|
||||
from .function import (
|
||||
calc_value,
|
||||
calc_value_property_help,
|
||||
valid_ip_netmask,
|
||||
valid_network_netmask,
|
||||
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 .error import ConfigError
|
||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||
|
@ -26,34 +44,36 @@ from .option import __all__ as all_options
|
|||
from .setting import owners, groups, undefined
|
||||
|
||||
|
||||
allfuncs = ['Calculation',
|
||||
'Params',
|
||||
'ParamOption',
|
||||
'ParamDynOption',
|
||||
'ParamSelfOption',
|
||||
'ParamValue',
|
||||
'ParamIndex',
|
||||
'ParamSuffix',
|
||||
'ParamInformation',
|
||||
'ParamSelfInformation',
|
||||
'MetaConfig',
|
||||
'MixConfig',
|
||||
'GroupConfig',
|
||||
'Config',
|
||||
'ConfigError',
|
||||
'undefined',
|
||||
'owners',
|
||||
'groups',
|
||||
'calc_value',
|
||||
'calc_value_property_help',
|
||||
'valid_ip_netmask',
|
||||
'valid_network_netmask',
|
||||
'valid_in_network',
|
||||
'valid_broadcast',
|
||||
'function_waiting_for_dict',
|
||||
]
|
||||
allfuncs = [
|
||||
"Calculation",
|
||||
"Params",
|
||||
"ParamOption",
|
||||
"ParamDynOption",
|
||||
"ParamSelfOption",
|
||||
"ParamValue",
|
||||
"ParamIndex",
|
||||
"ParamIdentifier",
|
||||
"ParamInformation",
|
||||
"ParamSelfInformation",
|
||||
"MetaConfig",
|
||||
"MixConfig",
|
||||
"GroupConfig",
|
||||
"Config",
|
||||
"ConfigError",
|
||||
"undefined",
|
||||
"owners",
|
||||
"groups",
|
||||
"calc_value",
|
||||
"calc_value_property_help",
|
||||
"valid_ip_netmask",
|
||||
"valid_network_netmask",
|
||||
"valid_in_network",
|
||||
"valid_broadcast",
|
||||
"function_waiting_for_dict",
|
||||
"function_waiting_for_error",
|
||||
]
|
||||
allfuncs.extend(all_options)
|
||||
del(all_options)
|
||||
del all_options
|
||||
__all__ = tuple(allfuncs)
|
||||
del(allfuncs)
|
||||
del allfuncs
|
||||
__version__ = "4.1.0"
|
||||
|
|
1733
tiramisu/api.py
1733
tiramisu/api.py
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -19,9 +19,9 @@ from time import time
|
|||
|
||||
|
||||
class Cache:
|
||||
"""cache object
|
||||
"""
|
||||
__slots__ = ('_cache',)
|
||||
"""cache object"""
|
||||
|
||||
__slots__ = ("_cache",)
|
||||
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
|
@ -35,29 +35,30 @@ class Cache:
|
|||
index = subconfig.index
|
||||
return path, index
|
||||
|
||||
def getcache(self,
|
||||
subconfig,
|
||||
type_,
|
||||
expiration=True,
|
||||
):
|
||||
"""get the cache value fot a specified path
|
||||
"""
|
||||
def getcache(
|
||||
self,
|
||||
subconfig,
|
||||
type_,
|
||||
expiration=True,
|
||||
):
|
||||
"""get the cache value fot a specified path"""
|
||||
no_cache = False, None, False
|
||||
path, index = self._get_path_index(subconfig)
|
||||
if path not in self._cache or index not in self._cache[path]:
|
||||
return no_cache
|
||||
value, timestamp, validated = self._cache[path][index]
|
||||
props = subconfig.config_bag.properties
|
||||
if type_ == 'self_props':
|
||||
if type_ == "self_props":
|
||||
# cached value is self_props
|
||||
self_props = value
|
||||
else:
|
||||
self_props = subconfig.properties
|
||||
if 'cache' in props or \
|
||||
'cache' in self_props:
|
||||
if expiration and timestamp and \
|
||||
('expire' in props or \
|
||||
'expire' in self_props):
|
||||
if "cache" in props or "cache" in self_props:
|
||||
if (
|
||||
expiration
|
||||
and timestamp
|
||||
and ("expire" in props or "expire" in self_props)
|
||||
):
|
||||
ntime = int(time())
|
||||
if timestamp + subconfig.config_bag.expiration_time >= ntime:
|
||||
return True, value, validated
|
||||
|
@ -65,37 +66,38 @@ class Cache:
|
|||
return True, value, validated
|
||||
return no_cache
|
||||
|
||||
def setcache(self,
|
||||
subconfig,
|
||||
val,
|
||||
type_='values',
|
||||
validated=True,
|
||||
):
|
||||
def setcache(
|
||||
self,
|
||||
subconfig,
|
||||
val,
|
||||
type_="values",
|
||||
validated=True,
|
||||
):
|
||||
"""add val in cache for a specified path
|
||||
if follower, add index
|
||||
"""
|
||||
if type_ == 'values':
|
||||
if 'cache' not in subconfig.config_bag.properties and \
|
||||
'cache' not in subconfig.properties:
|
||||
if type_ == "values":
|
||||
if (
|
||||
"cache" not in subconfig.config_bag.properties
|
||||
and "cache" not in subconfig.properties
|
||||
):
|
||||
return
|
||||
elif (subconfig is None or 'cache' not in subconfig.config_bag.properties) and \
|
||||
'cache' not in val:
|
||||
elif (
|
||||
subconfig is None or "cache" not in subconfig.config_bag.properties
|
||||
) and "cache" not in val:
|
||||
return
|
||||
path, index = self._get_path_index(subconfig)
|
||||
self._cache.setdefault(path, {})[index] = (val, int(time()), validated)
|
||||
|
||||
def delcache(self, path):
|
||||
"""reset cache a a specified path
|
||||
"""
|
||||
if path in self._cache:
|
||||
"""reset cache a a specified path"""
|
||||
if path in self._cache:
|
||||
del self._cache[path]
|
||||
|
||||
def get_cached(self):
|
||||
"""get cache values
|
||||
"""
|
||||
"""get cache values"""
|
||||
return self._cache
|
||||
|
||||
def reset_all_cache(self):
|
||||
"""reset all cache values
|
||||
"""
|
||||
"""reset all cache values"""
|
||||
self._cache.clear()
|
||||
|
|
1936
tiramisu/config.py
1936
tiramisu/config.py
File diff suppressed because it is too large
Load diff
|
@ -19,17 +19,18 @@ import weakref
|
|||
from .i18n import _
|
||||
|
||||
|
||||
def display_list(lst,
|
||||
*,
|
||||
separator='and',
|
||||
add_quote=False,
|
||||
) -> str():
|
||||
def display_list(
|
||||
lst,
|
||||
*,
|
||||
separator="and",
|
||||
add_quote=False,
|
||||
) -> str():
|
||||
if not lst:
|
||||
return '""'
|
||||
if separator == 'and':
|
||||
separator = _('and')
|
||||
elif separator == 'or':
|
||||
separator = _('or')
|
||||
if separator == "and":
|
||||
separator = _("and")
|
||||
elif separator == "or":
|
||||
separator = _("or")
|
||||
if isinstance(lst, tuple) or isinstance(lst, frozenset):
|
||||
lst = list(lst)
|
||||
if len(lst) == 1:
|
||||
|
@ -51,30 +52,35 @@ def display_list(lst,
|
|||
lst__.append(l)
|
||||
lst__.sort()
|
||||
last = lst__[-1]
|
||||
return ', '.join(lst__[:-1]) + _(' {} ').format(separator) + '{}'.format(last)
|
||||
return ", ".join(lst__[:-1]) + _(" {} ").format(separator) + "{}".format(last)
|
||||
|
||||
|
||||
# Exceptions for an Option
|
||||
class PropertiesOptionError(AttributeError):
|
||||
"attempt to access to an option with a property that is not allowed"
|
||||
def __init__(self,
|
||||
subconfig,
|
||||
proptype,
|
||||
settings,
|
||||
opt_type=None,
|
||||
name=None,
|
||||
orig_opt=None,
|
||||
help_properties=None):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
subconfig,
|
||||
proptype,
|
||||
settings,
|
||||
opt_type=None,
|
||||
name=None,
|
||||
orig_opt=None,
|
||||
help_properties=None,
|
||||
):
|
||||
if opt_type:
|
||||
self._opt_type = opt_type
|
||||
self._name = name
|
||||
self._orig_opt = orig_opt
|
||||
else:
|
||||
if subconfig.option.impl_is_optiondescription():
|
||||
self._opt_type = 'optiondescription'
|
||||
self._opt_type = "optiondescription"
|
||||
else:
|
||||
self._opt_type = 'option'
|
||||
self._name = subconfig.option.impl_get_display_name(subconfig)
|
||||
self._opt_type = "option"
|
||||
self._name = subconfig.option.impl_get_display_name(
|
||||
subconfig, with_quote=True
|
||||
)
|
||||
self._orig_opt = None
|
||||
self._subconfig = subconfig
|
||||
self.proptype = proptype
|
||||
|
@ -91,7 +97,7 @@ class PropertiesOptionError(AttributeError):
|
|||
if self.msg is not None:
|
||||
return self.msg
|
||||
if self._settings is None:
|
||||
return 'error'
|
||||
return "error"
|
||||
if self.help_properties:
|
||||
properties = list(self.help_properties)
|
||||
else:
|
||||
|
@ -99,46 +105,47 @@ class PropertiesOptionError(AttributeError):
|
|||
only_one = len(properties) == 1
|
||||
properties_msg = display_list(properties, add_quote=True)
|
||||
if only_one:
|
||||
prop_msg = _('property')
|
||||
prop_msg = _("property")
|
||||
else:
|
||||
prop_msg = _('properties')
|
||||
if properties == ['frozen']:
|
||||
prop_msg = _("properties")
|
||||
if properties == ["frozen"]:
|
||||
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:
|
||||
msg = 'cannot modify the {0} "{1}" because has {2} {3}'
|
||||
msg = _("cannot modify the {0} {1} because has {2} {3}")
|
||||
else:
|
||||
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:
|
||||
msg = 'cannot access to {0} "{1}" because has {2} {3}'
|
||||
msg = _("cannot access to {0} {1} because has {2} {3}")
|
||||
if self._orig_opt:
|
||||
# FIXME _orig_opt ?
|
||||
self.msg = _(msg).format(self._opt_type,
|
||||
self._orig_opt.impl_get_display_name(subconfig),
|
||||
self._name,
|
||||
prop_msg,
|
||||
properties_msg)
|
||||
self.msg = msg.format(
|
||||
self._opt_type,
|
||||
self._orig_opt.impl_get_display_name(subconfig, with_quote=True),
|
||||
self._name,
|
||||
prop_msg,
|
||||
properties_msg,
|
||||
)
|
||||
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._settings, self._orig_opt
|
||||
return self.msg
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
# ____________________________________________________________
|
||||
# Exceptions for a Config
|
||||
class ConfigError(Exception):
|
||||
"""attempt to change an option's owner without a value
|
||||
or in case of `_descr` is None
|
||||
or if a calculation cannot be carried out"""
|
||||
def __init__(self,
|
||||
exp,
|
||||
ori_err=None,
|
||||
):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
exp,
|
||||
ori_err=None,
|
||||
):
|
||||
super().__init__(exp)
|
||||
self.ori_err = ori_err
|
||||
|
||||
|
@ -148,8 +155,8 @@ class ConflictError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
# miscellaneous exceptions
|
||||
# ____________________________________________________________
|
||||
# miscellaneous exceptions
|
||||
class LeadershipError(Exception):
|
||||
"problem with a leadership's value length"
|
||||
pass
|
||||
|
@ -161,13 +168,7 @@ class ConstError(TypeError):
|
|||
|
||||
|
||||
class _CommonError:
|
||||
def __init__(self,
|
||||
subconfig,
|
||||
val,
|
||||
display_type,
|
||||
opt,
|
||||
err_msg,
|
||||
index):
|
||||
def __init__(self, subconfig, val, display_type, opt, err_msg, index):
|
||||
self.val = val
|
||||
self.display_type = display_type
|
||||
self.opt = weakref.ref(opt)
|
||||
|
@ -180,24 +181,24 @@ class _CommonError:
|
|||
try:
|
||||
msg = self.prefix
|
||||
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
|
||||
if self.err_msg:
|
||||
if msg:
|
||||
msg += ', {}'.format(self.err_msg)
|
||||
msg += ", {}".format(self.err_msg)
|
||||
else:
|
||||
msg = self.err_msg
|
||||
if not msg:
|
||||
msg = _('invalid value')
|
||||
msg = _("invalid value")
|
||||
return msg
|
||||
|
||||
|
||||
class ValueWarning(_CommonError, UserWarning):
|
||||
tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"')
|
||||
tmpl = None
|
||||
|
||||
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:
|
||||
self.msg = args[0]
|
||||
else:
|
||||
|
@ -211,8 +212,18 @@ class ValueWarning(_CommonError, UserWarning):
|
|||
|
||||
|
||||
class ValueOptionError(_CommonError, ValueError):
|
||||
tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||
tmpl = None
|
||||
|
||||
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):
|
||||
tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||
tmpl = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if ValueErrorWarning.tmpl is None:
|
||||
ValueErrorWarning.tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
@ -23,6 +23,7 @@ from .error import display_list
|
|||
|
||||
|
||||
FUNCTION_WAITING_FOR_DICT = []
|
||||
FUNCTION_WAITING_FOR_ERROR = []
|
||||
|
||||
|
||||
def function_waiting_for_dict(function):
|
||||
|
@ -36,74 +37,94 @@ def function_waiting_for_dict(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
|
||||
def valid_network_netmask(network: dict,
|
||||
netmask: dict,
|
||||
):
|
||||
def valid_network_netmask(
|
||||
network: dict,
|
||||
netmask: dict,
|
||||
):
|
||||
"""
|
||||
validates if network and netmask are coherent
|
||||
this validator must be set to netmask option
|
||||
"""
|
||||
if None in [network['value'], netmask['value']]:
|
||||
if None in [network["value"], netmask["value"]]:
|
||||
return
|
||||
try:
|
||||
ip_network(f'{network["value"]}/{netmask["value"]}')
|
||||
except ValueError as err:
|
||||
raise ValueError(_(f'network "{network["value"]}" ({network["name"]}) does not match '
|
||||
'with this netmask')) from err
|
||||
raise ValueError(
|
||||
_('network "{0}" ({1}) does not match with this netmask').format(
|
||||
network["value"], network["name"]
|
||||
)
|
||||
) from err
|
||||
|
||||
|
||||
@function_waiting_for_dict
|
||||
def valid_ip_netmask(ip: dict, # pylint: disable=invalid-name
|
||||
netmask: dict,
|
||||
):
|
||||
def valid_ip_netmask(
|
||||
ip: dict, # pylint: disable=invalid-name
|
||||
netmask: dict,
|
||||
):
|
||||
"""validates if ip and netmask are coherent
|
||||
this validator must be set to netmask option
|
||||
"""
|
||||
if None in [ip['value'], netmask['value']]:
|
||||
if None in [ip["value"], netmask["value"]]:
|
||||
return
|
||||
ip_netmask = ip_interface(f'{ip["value"]}/{netmask["value"]}')
|
||||
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||
msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is '
|
||||
'in fact a network address')
|
||||
msg = _('IP "{0}" ({1}) with this netmask is in fact a network address').format(
|
||||
ip["value"], ip["name"]
|
||||
)
|
||||
raise ValueError(msg)
|
||||
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||
msg = _(f'IP "{ip["value"]}" ({ip["name"]}) with this netmask is '
|
||||
'in fact a broacast address')
|
||||
msg = _(
|
||||
'IP "{0}" ({1}) with this netmask is in fact a broadcast address'
|
||||
).format(ip["value"], ip["name"])
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
@function_waiting_for_dict
|
||||
def valid_broadcast(network: dict,
|
||||
netmask: dict,
|
||||
broadcast: dict,
|
||||
):
|
||||
"""validates if the broadcast is coherent with network and netmask
|
||||
"""
|
||||
if None in [network['value'], netmask['value'], broadcast['value']]:
|
||||
def valid_broadcast(
|
||||
network: dict,
|
||||
netmask: dict,
|
||||
broadcast: dict,
|
||||
):
|
||||
"""validates if the broadcast is coherent with network and netmask"""
|
||||
if None in [network["value"], netmask["value"], broadcast["value"]]:
|
||||
return
|
||||
if ip_network(f'{network["value"]}/{netmask["value"]}').broadcast_address != \
|
||||
ip_address(broadcast['value']):
|
||||
msg = _(f'broadcast invalid with network {network["value"]} ({network["name"]}) '
|
||||
f'and netmask {netmask["value"]} ({netmask["name"]})')
|
||||
if ip_network(
|
||||
f'{network["value"]}/{netmask["value"]}'
|
||||
).broadcast_address != ip_address(broadcast["value"]):
|
||||
msg = _(
|
||||
"broadcast invalid with network {0} ({1}) and netmask {2} ({3})"
|
||||
).format(network["value"], network["name"], netmask["value"], netmask["name"])
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
@function_waiting_for_dict
|
||||
def valid_in_network(ip: dict, # pylint: disable=invalid-name
|
||||
network: dict,
|
||||
netmask=Optional[dict],
|
||||
):
|
||||
def valid_in_network(
|
||||
ip: dict, # pylint: disable=invalid-name
|
||||
network: dict,
|
||||
netmask=Optional[dict],
|
||||
):
|
||||
"""validates if an IP is in a network
|
||||
this validator must be set to ip option
|
||||
"""
|
||||
if None in [ip['value'], network['value']]:
|
||||
if None in [ip["value"], network["value"]]:
|
||||
return
|
||||
if '/' in network['value']:
|
||||
if "/" in network["value"]:
|
||||
# it's a CIDR network
|
||||
network_value = network['value']
|
||||
network_value = network["value"]
|
||||
else:
|
||||
if netmask is None or netmask['value'] is None:
|
||||
if netmask is None or netmask["value"] is None:
|
||||
return
|
||||
network_value = f'{network["value"]}/{netmask["value"]}'
|
||||
network_obj = ip_network(network_value)
|
||||
|
@ -112,56 +133,63 @@ def valid_in_network(ip: dict, # pylint: disable=invalid-name
|
|||
if netmask is None:
|
||||
msg = _('this IP is not in network {network["value"]} ({network["name"]})')
|
||||
else:
|
||||
msg = _('this IP is not in network {network["value"]} ({network["name"]}) '
|
||||
'with netmask {netmask["value"]} ({netmask["name"]})')
|
||||
msg = _(
|
||||
'this IP is not in network {network["value"]} ({network["name"]}) '
|
||||
'with netmask {netmask["value"]} ({netmask["name"]})'
|
||||
)
|
||||
raise ValueError(msg)
|
||||
# test if ip is not network/broadcast IP
|
||||
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||
msg = _(f'this IP with the network {network["value"]} ({network["value"]} '
|
||||
'is in fact a network address')
|
||||
msg = _(
|
||||
"this IP with the network {0} ({1}) is in fact a network address"
|
||||
).format(network["value"], network["name"])
|
||||
raise ValueError(msg)
|
||||
if ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||
msg = _(f'this IP with the network {network["value"]} ({network["value"]} '
|
||||
'is in fact a broadcast address')
|
||||
msg = _(
|
||||
"this IP with the network {0} ({1}) is in fact a broadcast address"
|
||||
).format(network["value"], network["value"])
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
@function_waiting_for_dict
|
||||
def valid_not_equal(*values):
|
||||
"""valid that two options have not same value
|
||||
"""
|
||||
"""valid that two options have not same value"""
|
||||
equal = set()
|
||||
for val in values[1:]:
|
||||
if 'propertyerror' in val:
|
||||
if "propertyerror" in val:
|
||||
continue
|
||||
if values[0]['value'] == val['value'] is not None:
|
||||
equal.add(val['name'])
|
||||
if values[0]["value"] == val["value"] is not None:
|
||||
equal.add(val["name"])
|
||||
if not equal:
|
||||
return
|
||||
msg = _(f'value is identical to {display_list(list(equal), add_quote=True)}')
|
||||
msg = _("value is identical to {0}").format(
|
||||
display_list(list(equal), add_quote=True)
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class CalcValue:
|
||||
"""class to calc_value with different functions
|
||||
"""
|
||||
"""class to calc_value with different functions"""
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
def __call__(self,
|
||||
*args: List[Any],
|
||||
multi: bool=False,
|
||||
default: Any=undefined,
|
||||
condition: Any=undefined,
|
||||
no_condition_is_invalid: bool=False,
|
||||
expected: Any=undefined,
|
||||
condition_operator: str='AND',
|
||||
reverse_condition: bool=False,
|
||||
allow_none: bool=False,
|
||||
remove_duplicate_value: bool=False,
|
||||
join: Optional[str]=None,
|
||||
min_args_len: Optional[int]=None,
|
||||
operator: Optional[str]=None,
|
||||
index: Optional[int]=None,
|
||||
**kwargs) -> Any:
|
||||
def __call__(
|
||||
self,
|
||||
*args: List[Any],
|
||||
multi: bool = False,
|
||||
default: Any = undefined,
|
||||
condition: Any = undefined,
|
||||
no_condition_is_invalid: bool = False,
|
||||
expected: Any = undefined,
|
||||
condition_operator: str = "AND",
|
||||
reverse_condition: bool = False,
|
||||
allow_none: bool = False,
|
||||
remove_duplicate_value: bool = False,
|
||||
join: Optional[str] = None,
|
||||
min_args_len: Optional[int] = None,
|
||||
operator: Optional[str] = None,
|
||||
index: Optional[int] = None,
|
||||
**kwargs,
|
||||
) -> Any:
|
||||
# pylint: disable=too-many-statements,too-many-branches,too-many-nested-blocks,too-many-locals
|
||||
"""calculate value
|
||||
:param args: list of value
|
||||
|
@ -325,10 +353,13 @@ class CalcValue:
|
|||
self.condition_operator = condition_operator
|
||||
self.reverse_condition = reverse_condition
|
||||
self.kwargs = kwargs
|
||||
self.no_condition_is_invalid = no_condition_is_invalid # pylint: disable=attribute-defined-outside-init
|
||||
value = self.get_value(default,
|
||||
min_args_len,
|
||||
)
|
||||
self.no_condition_is_invalid = (
|
||||
no_condition_is_invalid # pylint: disable=attribute-defined-outside-init
|
||||
)
|
||||
value = self.get_value(
|
||||
default,
|
||||
min_args_len,
|
||||
)
|
||||
if not multi:
|
||||
if join is not None:
|
||||
if None not in value:
|
||||
|
@ -337,11 +368,12 @@ class CalcValue:
|
|||
value = None
|
||||
elif value and operator:
|
||||
new_value = value[0]
|
||||
oper = {'mul': mul,
|
||||
'add': add,
|
||||
'div': truediv,
|
||||
'sub': sub,
|
||||
}[operator]
|
||||
oper = {
|
||||
"mul": mul,
|
||||
"add": add,
|
||||
"div": truediv,
|
||||
"sub": sub,
|
||||
}[operator]
|
||||
for val in value[1:]:
|
||||
new_value = oper(new_value, val)
|
||||
value = new_value
|
||||
|
@ -365,8 +397,9 @@ class CalcValue:
|
|||
break
|
||||
lval = len(val)
|
||||
if length_val is not None and length_val != lval:
|
||||
msg = _('unexpected value in calc_value with join attribute '
|
||||
f'"{val}" with invalid length "{length_val}"')
|
||||
msg = _(
|
||||
'unexpected value in calc_value with join attribute "{0}" with invalid length "{1}"'
|
||||
).format(val, length_val)
|
||||
raise ValueError(msg)
|
||||
length_val = lval
|
||||
new_value = []
|
||||
|
@ -392,19 +425,16 @@ class CalcValue:
|
|||
value = new_value
|
||||
return value
|
||||
|
||||
def value_from_kwargs(self,
|
||||
value: Any,
|
||||
pattern: str,
|
||||
to_dict: bool=False,
|
||||
empty_test=undefined) -> Any:
|
||||
"""get value from kwargs
|
||||
"""
|
||||
def value_from_kwargs(
|
||||
self, value: Any, pattern: str, to_dict: bool = False, empty_test=undefined
|
||||
) -> Any:
|
||||
"""get value from kwargs"""
|
||||
# pylint: disable=too-many-branches
|
||||
# if value attribute exist return it's value
|
||||
# otherwise pattern_0, pattern_1, ...
|
||||
# otherwise undefined
|
||||
if value is not empty_test:
|
||||
if to_dict == 'all':
|
||||
if to_dict == "all":
|
||||
returns = {None: value}
|
||||
else:
|
||||
returns = value
|
||||
|
@ -415,7 +445,7 @@ class CalcValue:
|
|||
if key.startswith(pattern):
|
||||
index = int(key[len_pattern:])
|
||||
if isinstance(pattern_value, dict):
|
||||
pattern_value = pattern_value['value']
|
||||
pattern_value = pattern_value["value"]
|
||||
kwargs_matches[index] = pattern_value
|
||||
if not kwargs_matches:
|
||||
returns = undefined
|
||||
|
@ -432,38 +462,47 @@ class CalcValue:
|
|||
returns.append(kwargs_matches[key])
|
||||
return returns
|
||||
|
||||
def is_condition_matches(self,
|
||||
condition_value,
|
||||
):
|
||||
"""verify the condition
|
||||
"""
|
||||
def is_condition_matches(
|
||||
self,
|
||||
condition_value,
|
||||
):
|
||||
"""verify the condition"""
|
||||
# pylint: disable=too-many-branches
|
||||
calculated_conditions = self.value_from_kwargs(condition_value,
|
||||
'condition_',
|
||||
to_dict='all',
|
||||
)
|
||||
calculated_conditions = self.value_from_kwargs(
|
||||
condition_value,
|
||||
"condition_",
|
||||
to_dict="all",
|
||||
)
|
||||
if calculated_conditions is undefined:
|
||||
is_matches = not self.no_condition_is_invalid
|
||||
else:
|
||||
is_matches = None
|
||||
calculated_expected = self.value_from_kwargs(self.expected,
|
||||
'expected_',
|
||||
to_dict=True,
|
||||
)
|
||||
calculated_reverse = self.value_from_kwargs(self.reverse_condition,
|
||||
'reverse_condition_',
|
||||
to_dict=True,
|
||||
empty_test=False,
|
||||
)
|
||||
calculated_expected = self.value_from_kwargs(
|
||||
self.expected,
|
||||
"expected_",
|
||||
to_dict=True,
|
||||
)
|
||||
calculated_reverse = self.value_from_kwargs(
|
||||
self.reverse_condition,
|
||||
"reverse_condition_",
|
||||
to_dict=True,
|
||||
empty_test=False,
|
||||
)
|
||||
for idx, calculated_condition in calculated_conditions.items():
|
||||
if isinstance(calculated_expected, dict):
|
||||
if idx is not None:
|
||||
if isinstance(calculated_expected[idx], list):
|
||||
current_matches = calculated_condition in calculated_expected[idx]
|
||||
current_matches = (
|
||||
calculated_condition in calculated_expected[idx]
|
||||
)
|
||||
else:
|
||||
current_matches = calculated_condition == calculated_expected[idx]
|
||||
current_matches = (
|
||||
calculated_condition == calculated_expected[idx]
|
||||
)
|
||||
else:
|
||||
current_matches = calculated_condition in calculated_expected.values()
|
||||
current_matches = (
|
||||
calculated_condition in calculated_expected.values()
|
||||
)
|
||||
else:
|
||||
current_matches = calculated_condition == calculated_expected
|
||||
if isinstance(calculated_reverse, dict) and idx in calculated_reverse:
|
||||
|
@ -472,36 +511,41 @@ class CalcValue:
|
|||
reverse_condition = False
|
||||
if is_matches is None:
|
||||
is_matches = current_matches
|
||||
if self.condition_operator == 'AND':
|
||||
if self.condition_operator == "AND":
|
||||
is_matches = is_matches and current_matches
|
||||
if reverse_condition:
|
||||
is_matches = not is_matches
|
||||
if not is_matches:
|
||||
break
|
||||
elif self.condition_operator == 'OR':
|
||||
elif self.condition_operator == "OR":
|
||||
is_matches = is_matches or current_matches
|
||||
if reverse_condition:
|
||||
is_matches = not is_matches
|
||||
if is_matches:
|
||||
break
|
||||
else:
|
||||
msg = _(f'unexpected {self.condition_operator} condition_operator '
|
||||
'in calc_value')
|
||||
msg = _(
|
||||
"unexpected {0} condition_operator " "in calc_value"
|
||||
).format(self.condition_operator)
|
||||
raise ValueError(msg)
|
||||
is_matches = is_matches and not self.reverse_condition \
|
||||
or not is_matches and self.reverse_condition
|
||||
is_matches = (
|
||||
is_matches
|
||||
and not self.reverse_condition
|
||||
or not is_matches
|
||||
and self.reverse_condition
|
||||
)
|
||||
return is_matches
|
||||
|
||||
def get_value(self,
|
||||
default,
|
||||
min_args_len,
|
||||
):
|
||||
"""get the value from arguments
|
||||
"""
|
||||
def get_value(
|
||||
self,
|
||||
default,
|
||||
min_args_len,
|
||||
):
|
||||
"""get the value from arguments"""
|
||||
# retrieve the condition
|
||||
if isinstance(self.condition, dict):
|
||||
if 'value' in self.condition:
|
||||
condition_value = self.condition['value']
|
||||
if "value" in self.condition:
|
||||
condition_value = self.condition["value"]
|
||||
else:
|
||||
condition_value = undefined
|
||||
else:
|
||||
|
@ -516,9 +560,10 @@ class CalcValue:
|
|||
value = []
|
||||
if not value:
|
||||
# default value
|
||||
new_default = self.value_from_kwargs(default,
|
||||
'default_',
|
||||
)
|
||||
new_default = self.value_from_kwargs(
|
||||
default,
|
||||
"default_",
|
||||
)
|
||||
if new_default is not undefined:
|
||||
if not isinstance(new_default, list):
|
||||
value = [new_default]
|
||||
|
@ -527,34 +572,32 @@ class CalcValue:
|
|||
return value
|
||||
|
||||
def get_args(self):
|
||||
"""get all arguments
|
||||
"""
|
||||
"""get all arguments"""
|
||||
return list(self.args)
|
||||
|
||||
|
||||
class CalcValuePropertyHelp(CalcValue):
|
||||
"""special class to display property error
|
||||
"""
|
||||
"""special class to display property error"""
|
||||
|
||||
def get_name(self):
|
||||
"""get the condition name
|
||||
"""
|
||||
return self.condition['name']
|
||||
"""get the condition name"""
|
||||
return self.condition["name"]
|
||||
|
||||
def get_indexed_name(self, index: int) -> str:
|
||||
"""get name for a specified index
|
||||
"""
|
||||
condition_index = self.kwargs.get(f'condition_{index}')
|
||||
"""get name for a specified index"""
|
||||
condition_index = self.kwargs.get(f"condition_{index}")
|
||||
if condition_index is not None and not isinstance(condition_index, dict):
|
||||
raise ValueError(_(f'unexpected condition_{index} must have "todict" argument'))
|
||||
return condition_index['name']
|
||||
raise ValueError(
|
||||
_('unexpected condition_{0} must have "todict" argument').format(index)
|
||||
)
|
||||
return condition_index["name"]
|
||||
|
||||
|
||||
def build_property_message(self,
|
||||
name: str,
|
||||
value: Any,
|
||||
) -> str:
|
||||
"""prepare message to display error message if needed
|
||||
"""
|
||||
def build_property_message(
|
||||
self,
|
||||
name: str,
|
||||
value: Any,
|
||||
) -> str:
|
||||
"""prepare message to display error message if needed"""
|
||||
if not self.reverse_condition:
|
||||
msg = _('the value of "{0}" is {1}').format(name, value)
|
||||
else:
|
||||
|
@ -564,34 +607,36 @@ class CalcValuePropertyHelp(CalcValue):
|
|||
def get_args(self):
|
||||
args = super().get_args()
|
||||
action = args[0]
|
||||
calculated_expected = self.value_from_kwargs(self.expected,
|
||||
'expected_',
|
||||
to_dict=True)
|
||||
calculated_expected = self.value_from_kwargs(
|
||||
self.expected, "expected_", to_dict=True
|
||||
)
|
||||
if self.condition is not undefined:
|
||||
if 'propertyerror' in self.condition:
|
||||
msg = self.condition['propertyerror']
|
||||
if "propertyerror" in self.condition:
|
||||
msg = self.condition["propertyerror"]
|
||||
else:
|
||||
name = self.get_name()
|
||||
if isinstance(calculated_expected, dict):
|
||||
calc_values = calculated_expected.values()
|
||||
else:
|
||||
calc_values = [calculated_expected]
|
||||
display_value = display_list([str(val) for val in calc_values],
|
||||
'or',
|
||||
add_quote=True)
|
||||
display_value = display_list(
|
||||
[str(val) for val in calc_values], separator="or", add_quote=True
|
||||
)
|
||||
msg = self.build_property_message(name, display_value)
|
||||
else:
|
||||
msgs = []
|
||||
for key, value in calculated_expected.items():
|
||||
name = self.get_indexed_name(key)
|
||||
msgs.append(self.build_property_message(name, f'"{value}"'))
|
||||
msg = display_list(msgs, self.condition_operator.lower())
|
||||
msg = display_list(msgs, separator=self.condition_operator.lower())
|
||||
return [(action, f'"{action}" ({msg})')]
|
||||
|
||||
|
||||
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)
|
||||
calc_value_property_help = CalcValuePropertyHelp()
|
||||
calc_value_property_help.__name__ = 'calc_value_property_help' # pylint: disable=attribute-defined-outside-init
|
||||
calc_value_property_help.__name__ = (
|
||||
"calc_value_property_help" # pylint: disable=attribute-defined-outside-init
|
||||
)
|
||||
function_waiting_for_dict(calc_value_property_help)
|
||||
|
|
|
@ -18,55 +18,9 @@
|
|||
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||
# the whole pypy projet is under MIT licence
|
||||
"internationalisation utilities"
|
||||
from .log import log
|
||||
from gettext import translation
|
||||
from pathlib import Path
|
||||
|
||||
from gettext import translation, NullTranslations
|
||||
from platform import system
|
||||
from pkg_resources import resource_filename
|
||||
from os import environ
|
||||
t = translation("tiramisu", str(Path(__file__).parent / "locale"), fallback=True)
|
||||
|
||||
|
||||
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()
|
||||
_ = t.gettext
|
||||
|
|
BIN
tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo
Normal file
BIN
tiramisu/locale/fr/LC_MESSAGES/tiramisu.mo
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -1,711 +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: 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 ""
|
||||
|
|
@ -19,12 +19,12 @@ from logging import getLogger, DEBUG, StreamHandler, Formatter
|
|||
import os
|
||||
|
||||
|
||||
log = getLogger('tiramisu')
|
||||
if os.environ.get('TIRAMISU_DEBUG') == 'True': # pragma: no cover
|
||||
log = getLogger("tiramisu")
|
||||
if os.environ.get("TIRAMISU_DEBUG") == "True": # pragma: no cover
|
||||
log.setLevel(DEBUG)
|
||||
handler = StreamHandler()
|
||||
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)
|
||||
|
||||
log.addHandler(handler)
|
||||
|
|
|
@ -25,7 +25,8 @@ from .dynoptiondescription import DynOptionDescription
|
|||
from .leadership import Leadership
|
||||
from .baseoption import submulti
|
||||
from .symlinkoption import SymLinkOption
|
||||
#from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership
|
||||
|
||||
# from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership
|
||||
from .option import Option
|
||||
from .choiceoption import ChoiceOption
|
||||
from .booloption import BoolOption
|
||||
|
@ -48,12 +49,33 @@ from .macoption import MACOption
|
|||
from .permissionsoption import PermissionsOption
|
||||
|
||||
|
||||
__all__ = ('Leadership', 'OptionDescription', 'DynOptionDescription',
|
||||
# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption',
|
||||
'Option', 'SymLinkOption',
|
||||
'ChoiceOption', 'BoolOption', 'DateOption',
|
||||
'IntOption', 'FloatOption', 'StrOption',
|
||||
'IPOption', 'PortOption', 'NetworkOption', 'NetmaskOption',
|
||||
'BroadcastOption', 'DomainnameOption', 'EmailOption', 'URLOption',
|
||||
'UsernameOption', 'GroupnameOption', 'FilenameOption', 'PasswordOption', 'submulti',
|
||||
'RegexpOption', 'MACOption', 'PermissionsOption')
|
||||
__all__ = (
|
||||
"Leadership",
|
||||
"OptionDescription",
|
||||
"DynOptionDescription",
|
||||
# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption',
|
||||
"Option",
|
||||
"SymLinkOption",
|
||||
"ChoiceOption",
|
||||
"BoolOption",
|
||||
"DateOption",
|
||||
"IntOption",
|
||||
"FloatOption",
|
||||
"StrOption",
|
||||
"IPOption",
|
||||
"PortOption",
|
||||
"NetworkOption",
|
||||
"NetmaskOption",
|
||||
"BroadcastOption",
|
||||
"DomainnameOption",
|
||||
"EmailOption",
|
||||
"URLOption",
|
||||
"UsernameOption",
|
||||
"GroupnameOption",
|
||||
"FilenameOption",
|
||||
"PasswordOption",
|
||||
"submulti",
|
||||
"RegexpOption",
|
||||
"MACOption",
|
||||
"PermissionsOption",
|
||||
)
|
||||
|
|
|
@ -36,40 +36,41 @@ submulti = 2
|
|||
|
||||
|
||||
def valid_name(name):
|
||||
"""valid option name
|
||||
"""
|
||||
"""valid option name"""
|
||||
if not isinstance(name, str):
|
||||
return False
|
||||
if '.' in name:
|
||||
if "." in name:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
# ____________________________________________________________
|
||||
#
|
||||
class Base:
|
||||
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)
|
||||
"""
|
||||
__slots__ = ('_name',
|
||||
'_path',
|
||||
'_informations',
|
||||
'_subdyns',
|
||||
'_properties',
|
||||
'_has_dependency',
|
||||
'_dependencies',
|
||||
'_dependencies_information',
|
||||
'_suffixes_dependencies',
|
||||
'__weakref__'
|
||||
)
|
||||
"""Base use by all *Option* classes (Option, OptionDescription, SymLinkOption, ...)"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
informations: Optional[Dict],
|
||||
*,
|
||||
properties=None,
|
||||
is_multi: bool=False,
|
||||
) -> None:
|
||||
__slots__ = (
|
||||
"_name",
|
||||
"_path",
|
||||
"_informations",
|
||||
"_subdyns",
|
||||
"_properties",
|
||||
"_has_dependency",
|
||||
"_dependencies",
|
||||
"_dependencies_information",
|
||||
"_identifiers_dependencies",
|
||||
"__weakref__",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
informations: Optional[Dict],
|
||||
*,
|
||||
properties=None,
|
||||
is_multi: bool = False,
|
||||
) -> None:
|
||||
if not valid_name(name):
|
||||
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||
if properties is None:
|
||||
|
@ -80,88 +81,99 @@ class Base:
|
|||
# if option is a multi, it cannot be 'empty' (None not allowed in the list)
|
||||
# and cannot have multiple time the same value
|
||||
# 'empty' and 'unique' are removed for follower's option
|
||||
if 'notunique' not in properties:
|
||||
properties = properties | {'unique'}
|
||||
if 'notempty' not in properties:
|
||||
properties = properties | {'empty'}
|
||||
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
|
||||
' must be a frozenset').format(type(properties),
|
||||
name)
|
||||
if "notunique" not in properties:
|
||||
properties = properties | {"unique"}
|
||||
if "notempty" not in properties:
|
||||
properties = properties | {"empty"}
|
||||
assert isinstance(properties, frozenset), _(
|
||||
"invalid properties type {0} for {1}," " must be a frozenset"
|
||||
).format(type(properties), name)
|
||||
_setattr = object.__setattr__
|
||||
_setattr(self, '_name', name)
|
||||
_setattr(self, '_informations', {'doc': doc})
|
||||
_setattr(self, "_name", name)
|
||||
_setattr(self, "_informations", {"doc": doc})
|
||||
for prop in properties:
|
||||
if not isinstance(prop, str):
|
||||
if not isinstance(prop, Calculation):
|
||||
raise ValueError(_('invalid property type {0} for {1}, must be a string or a '
|
||||
'Calculation').format(type(prop), name))
|
||||
raise ValueError(
|
||||
_(
|
||||
"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()):
|
||||
if isinstance(param, ParamOption):
|
||||
param.option._add_dependency(self)
|
||||
if properties:
|
||||
_setattr(self, '_properties', properties)
|
||||
_setattr(self, "_properties", properties)
|
||||
self.set_informations(informations)
|
||||
|
||||
def set_informations(self,
|
||||
informations: Optional[Dict],
|
||||
) -> None:
|
||||
def set_informations(
|
||||
self,
|
||||
informations: Optional[Dict],
|
||||
) -> None:
|
||||
if not informations:
|
||||
return
|
||||
for key, value in informations.items():
|
||||
self._set_information(key,
|
||||
value,
|
||||
)
|
||||
self._set_information(
|
||||
key,
|
||||
value,
|
||||
)
|
||||
|
||||
def impl_has_dependency(self,
|
||||
self_is_dep: bool=True,
|
||||
) -> bool:
|
||||
"""this has dependency
|
||||
"""
|
||||
def impl_has_dependency(
|
||||
self,
|
||||
self_is_dep: bool = True,
|
||||
) -> bool:
|
||||
"""this has dependency"""
|
||||
if self_is_dep is True:
|
||||
return getattr(self, '_has_dependency', False)
|
||||
return hasattr(self, '_dependencies')
|
||||
return getattr(self, "_has_dependency", False)
|
||||
return hasattr(self, "_dependencies")
|
||||
|
||||
def get_dependencies(self,
|
||||
context_od,
|
||||
) -> Set[str]:
|
||||
ret = set(getattr(self, '_dependencies', STATIC_TUPLE))
|
||||
if context_od and hasattr(context_od, '_dependencies'):
|
||||
def get_dependencies(
|
||||
self,
|
||||
context_od,
|
||||
) -> Set[str]:
|
||||
ret = set(getattr(self, "_dependencies", STATIC_TUPLE))
|
||||
if context_od and hasattr(context_od, "_dependencies"):
|
||||
# add options that have context is set in calculation
|
||||
return set(context_od._dependencies) | ret # pylint: disable=protected-access
|
||||
return (
|
||||
set(context_od._dependencies) | ret
|
||||
) # pylint: disable=protected-access
|
||||
return ret
|
||||
|
||||
def _get_suffixes_dependencies(self) -> Set[str]:
|
||||
return getattr(self, '_suffixes_dependencies', STATIC_TUPLE)
|
||||
def _get_identifiers_dependencies(self) -> Set[str]:
|
||||
return getattr(self, "_identifiers_dependencies", STATIC_TUPLE)
|
||||
|
||||
def _add_dependency(self,
|
||||
option,
|
||||
is_suffix: bool=False,
|
||||
) -> None:
|
||||
def _add_dependency(
|
||||
self,
|
||||
option,
|
||||
is_identifier: bool = False,
|
||||
) -> None:
|
||||
woption = weakref.ref(option)
|
||||
options = self.get_dependencies(None)
|
||||
options.add(woption)
|
||||
self._dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init
|
||||
if is_suffix:
|
||||
options = list(self._get_suffixes_dependencies())
|
||||
self._dependencies = tuple(
|
||||
options
|
||||
) # pylint: disable=attribute-defined-outside-init
|
||||
if is_identifier:
|
||||
options = list(self._get_identifiers_dependencies())
|
||||
options.append(woption)
|
||||
self._suffixes_dependencies = tuple(options) # pylint: disable=attribute-defined-outside-init
|
||||
self._identifiers_dependencies = tuple(
|
||||
options
|
||||
) # pylint: disable=attribute-defined-outside-init
|
||||
|
||||
def impl_is_optiondescription(self) -> bool:
|
||||
"""option is an option description
|
||||
"""
|
||||
"""option is an option description"""
|
||||
return False
|
||||
|
||||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
"""option is not a dyn option description
|
||||
"""
|
||||
"""option is not a dyn option description"""
|
||||
return False
|
||||
|
||||
def impl_is_sub_dyn_optiondescription(self):
|
||||
return False
|
||||
|
||||
def impl_getname(self) -> str:
|
||||
"""get name
|
||||
"""
|
||||
"""get name"""
|
||||
return self._name # pylint: disable=no-member
|
||||
|
||||
def _set_readonly(self) -> None:
|
||||
|
@ -170,40 +182,39 @@ class Base:
|
|||
dico = self._informations # pylint: disable=no-member
|
||||
keys = tuple(dico.keys())
|
||||
if len(keys) == 1:
|
||||
dico = dico['doc']
|
||||
dico = dico["doc"]
|
||||
else:
|
||||
dico = tuple([keys, tuple(dico.values())])
|
||||
_setattr(self, '_informations', dico)
|
||||
extra = getattr(self, '_extra', None)
|
||||
_setattr(self, "_informations", dico)
|
||||
extra = getattr(self, "_extra", None)
|
||||
if extra is not None:
|
||||
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
|
||||
_setattr(
|
||||
self, "_extra", tuple([tuple(extra.keys()), tuple(extra.values())])
|
||||
)
|
||||
|
||||
def impl_is_readonly(self) -> str:
|
||||
"""the option is readonly
|
||||
"""
|
||||
return hasattr(self, '_path')
|
||||
"""the option is readonly"""
|
||||
return hasattr(self, "_path")
|
||||
|
||||
def impl_getproperties(self) -> FrozenSet[str]:
|
||||
"""get properties
|
||||
"""
|
||||
return getattr(self, '_properties', frozenset())
|
||||
"""get properties"""
|
||||
return getattr(self, "_properties", frozenset())
|
||||
|
||||
def _setsubdyn(self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
def _setsubdyn(
|
||||
self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
if getattr(self, '_subdyns', None) is None:
|
||||
if getattr(self, "_subdyns", None) is None:
|
||||
self._subdyns = []
|
||||
self._subdyns.append(subdyn)
|
||||
|
||||
def issubdyn(self) -> bool:
|
||||
"""is sub dynoption
|
||||
"""
|
||||
return getattr(self, '_subdyns', None) is not None
|
||||
"""is sub dynoption"""
|
||||
return getattr(self, "_subdyns", None) is not None
|
||||
|
||||
def getsubdyn(self):
|
||||
"""get sub dynoption
|
||||
"""
|
||||
"""get sub dynoption"""
|
||||
return self._subdyns[0]()
|
||||
|
||||
def get_sub_dyns(self):
|
||||
|
@ -211,11 +222,12 @@ class Base:
|
|||
|
||||
# ____________________________________________________________
|
||||
# information
|
||||
def _get_information(self,
|
||||
subconfig: "SubConfig",
|
||||
key: str,
|
||||
default: Any=undefined,
|
||||
) -> Any:
|
||||
def _get_information(
|
||||
self,
|
||||
subconfig: "SubConfig",
|
||||
key: str,
|
||||
default: Any = undefined,
|
||||
) -> Any:
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
|
@ -225,7 +237,7 @@ class Base:
|
|||
if key in dico[0]:
|
||||
return dico[1][dico[0].index(key)]
|
||||
elif isinstance(dico, str):
|
||||
if key == 'doc':
|
||||
if key == "doc":
|
||||
return dico
|
||||
elif isinstance(dico, dict):
|
||||
if key in dico:
|
||||
|
@ -233,13 +245,17 @@ class Base:
|
|||
if default is not undefined:
|
||||
return default
|
||||
# pylint: disable=no-member
|
||||
raise ValueError(_(f'information\'s item for "{self.impl_get_display_name(subconfig)}" '
|
||||
f'not found: "{key}"'))
|
||||
raise ValueError(
|
||||
_('information\'s item for {0} not found: "{1}"').format(
|
||||
self.impl_get_display_name(subconfig, with_quote=True), key
|
||||
)
|
||||
)
|
||||
|
||||
def _set_information(self,
|
||||
key: str,
|
||||
value: Any,
|
||||
) -> None:
|
||||
def _set_information(
|
||||
self,
|
||||
key: str,
|
||||
value: Any,
|
||||
) -> None:
|
||||
"""updates the information's attribute
|
||||
(which is a dictionary)
|
||||
|
||||
|
@ -247,20 +263,20 @@ class Base:
|
|||
:param value: information's value (ex: "the help string")
|
||||
"""
|
||||
if self.impl_is_readonly():
|
||||
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||
" read-only").format(self.__class__.__name__,
|
||||
self,
|
||||
key))
|
||||
raise AttributeError(
|
||||
_("'{0}' ({1}) object attribute '{2}' is" " read-only").format(
|
||||
self.__class__.__name__, self, key
|
||||
)
|
||||
)
|
||||
self._informations[key] = value # pylint: disable=no-member
|
||||
|
||||
def _list_information(self) -> Any:
|
||||
"""get the list of information keys
|
||||
"""
|
||||
"""get the list of information keys"""
|
||||
dico = self._informations # pylint: disable=no-member
|
||||
if isinstance(dico, tuple):
|
||||
return list(dico[0])
|
||||
if not isinstance(dico, dict):
|
||||
return ['doc']
|
||||
return ["doc"]
|
||||
# it's a dict
|
||||
return list(dico.keys())
|
||||
|
||||
|
@ -270,12 +286,14 @@ class BaseOption(Base):
|
|||
in options that have to be set only once, it is of course done in the
|
||||
__setattr__ method
|
||||
"""
|
||||
__slots__ = ('_display_name_function',)
|
||||
|
||||
def __setattr__(self,
|
||||
name: str,
|
||||
value: Any,
|
||||
) -> Any:
|
||||
__slots__ = ("_display_name_function",)
|
||||
|
||||
def __setattr__(
|
||||
self,
|
||||
name: str,
|
||||
value: Any,
|
||||
) -> Any:
|
||||
"""set once and only once some attributes in the option,
|
||||
like `_name`. `_name` cannot be changed once the option is
|
||||
pushed in the :class:`tiramisu.option.OptionDescription`.
|
||||
|
@ -286,84 +304,97 @@ class BaseOption(Base):
|
|||
"""
|
||||
# never change _name in an option or attribute when object is readonly
|
||||
if self.impl_is_readonly():
|
||||
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
|
||||
' read-only').format(self.__class__.__name__,
|
||||
self.impl_get_display_name(None),
|
||||
name))
|
||||
raise AttributeError(
|
||||
_('"{}" ({}) object attribute "{}" is' " read-only").format(
|
||||
self.__class__.__name__, self.impl_get_display_name(None), name
|
||||
)
|
||||
)
|
||||
super().__setattr__(name, value)
|
||||
|
||||
def impl_getpath(self) -> str:
|
||||
"""get the path of the option
|
||||
"""
|
||||
"""get the path of the option"""
|
||||
try:
|
||||
return self._path
|
||||
except AttributeError as err:
|
||||
raise AttributeError(_(f'"{self.impl_get_display_name(None)}" not part of any Config')) \
|
||||
from err
|
||||
raise AttributeError(
|
||||
_("{0} not part of any Config").format(
|
||||
self.impl_get_display_name(None, with_quote=True)
|
||||
)
|
||||
) from err
|
||||
|
||||
def impl_get_display_name(self,
|
||||
subconfig: "SubConfig",
|
||||
) -> str:
|
||||
"""get display name
|
||||
"""
|
||||
if hasattr(self, '_display_name_function'):
|
||||
return self._display_name_function(self, subconfig)
|
||||
name = self._get_information(subconfig, 'doc', None)
|
||||
if name is None or name == '':
|
||||
def impl_get_display_name(
|
||||
self,
|
||||
subconfig: "SubConfig",
|
||||
*,
|
||||
with_quote: bool = False,
|
||||
) -> str:
|
||||
"""get display name"""
|
||||
if hasattr(self, "_display_name_function"):
|
||||
return self._display_name_function(
|
||||
self,
|
||||
subconfig,
|
||||
with_quote=with_quote,
|
||||
)
|
||||
name = self._get_information(subconfig, "doc", None)
|
||||
if name is None or name == "":
|
||||
if subconfig and subconfig.path:
|
||||
name = subconfig.path.rsplit('.', 1)[-1]
|
||||
name = subconfig.path.rsplit(".", 1)[-1]
|
||||
else:
|
||||
name = self._name
|
||||
if with_quote:
|
||||
return f'"{name}"'
|
||||
return name
|
||||
|
||||
def reset_cache(self,
|
||||
path: str,
|
||||
config_bag: 'OptionBag',
|
||||
resetted_opts: List[Base], # pylint: disable=unused-argument
|
||||
) -> None:
|
||||
"""reset cache
|
||||
"""
|
||||
def reset_cache(
|
||||
self,
|
||||
path: str,
|
||||
config_bag: "OptionBag",
|
||||
resetted_opts: List[Base], # pylint: disable=unused-argument
|
||||
) -> None:
|
||||
"""reset cache"""
|
||||
context = config_bag.context
|
||||
context.properties_cache.delcache(path)
|
||||
context._impl_permissives_cache.delcache(path) # pylint: disable=protected-access
|
||||
context._impl_permissives_cache.delcache(
|
||||
path
|
||||
) # pylint: disable=protected-access
|
||||
if not self.impl_is_optiondescription():
|
||||
context.get_values_cache().delcache(path) # pylint: disable=protected-access
|
||||
context.get_values_cache().delcache(
|
||||
path
|
||||
) # pylint: disable=protected-access
|
||||
|
||||
def impl_is_symlinkoption(self) -> bool:
|
||||
"""the option is not a symlinkoption
|
||||
"""
|
||||
"""the option is not a symlinkoption"""
|
||||
return False
|
||||
|
||||
def get_dependencies_information(self) -> List[str]:
|
||||
"""get dependencies information
|
||||
"""
|
||||
return getattr(self, '_dependencies_information', {})
|
||||
"""get dependencies information"""
|
||||
return getattr(self, "_dependencies_information", {})
|
||||
|
||||
def value_dependencies(self,
|
||||
value: Any,
|
||||
is_suffix: bool=False,
|
||||
) -> Any:
|
||||
"""parse dependancies to add dependencies
|
||||
"""
|
||||
def value_dependencies(
|
||||
self,
|
||||
value: Any,
|
||||
is_identifier: bool = False,
|
||||
) -> Any:
|
||||
"""parse dependancies to add dependencies"""
|
||||
if isinstance(value, list):
|
||||
for val in value:
|
||||
if isinstance(value, list):
|
||||
self.value_dependencies(val, is_suffix)
|
||||
self.value_dependencies(val, is_identifier)
|
||||
elif isinstance(value, Calculation):
|
||||
self.value_dependency(val, is_suffix)
|
||||
self.value_dependency(val, is_identifier)
|
||||
elif isinstance(value, Calculation):
|
||||
self.value_dependency(value, is_suffix)
|
||||
self.value_dependency(value, is_identifier)
|
||||
|
||||
def value_dependency(self,
|
||||
value: Any,
|
||||
is_suffix: bool=False,
|
||||
) -> Any:
|
||||
"""parse dependancy to add dependencies
|
||||
"""
|
||||
def value_dependency(
|
||||
self,
|
||||
value: Any,
|
||||
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_suffix=is_suffix)
|
||||
param.option._add_dependency(self, is_identifier=is_identifier)
|
||||
self._has_dependency = True
|
||||
elif isinstance(param, ParamInformation):
|
||||
dest = self
|
||||
|
@ -375,7 +406,9 @@ class BaseOption(Base):
|
|||
else:
|
||||
param.set_self_option(self)
|
||||
opt = None
|
||||
if not getattr(dest, '_dependencies_information', {}):
|
||||
if not getattr(dest, "_dependencies_information", {}):
|
||||
dest._dependencies_information = {None: []}
|
||||
dest._dependencies_information[None].append(param)
|
||||
dest._dependencies_information.setdefault(param.information_name, []).append(opt)
|
||||
dest._dependencies_information.setdefault(
|
||||
param.information_name, []
|
||||
).append(opt)
|
||||
|
|
|
@ -26,15 +26,15 @@ from .option import Option
|
|||
|
||||
|
||||
class BoolOption(Option):
|
||||
"""represents a choice between ``True`` and ``False``
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'boolean'
|
||||
"""represents a choice between ``True`` and ``False``"""
|
||||
|
||||
def validate(self,
|
||||
value: bool,
|
||||
) -> None:
|
||||
"""validate value
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = "boolean"
|
||||
|
||||
def validate(
|
||||
self,
|
||||
value: bool,
|
||||
) -> None:
|
||||
"""validate value"""
|
||||
if not isinstance(value, bool):
|
||||
raise ValueError()
|
||||
|
|
|
@ -27,21 +27,21 @@ from .option import Option
|
|||
|
||||
|
||||
class BroadcastOption(Option):
|
||||
"""represents the choice of a broadcast
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'broadcast address'
|
||||
"""represents the choice of a broadcast"""
|
||||
|
||||
def validate(self,
|
||||
value: str,
|
||||
) -> None:
|
||||
"""validate
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = "broadcast address"
|
||||
|
||||
def validate(
|
||||
self,
|
||||
value: str,
|
||||
) -> None:
|
||||
"""validate"""
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
if value.count('.') != 3:
|
||||
raise ValueError(_("invalid string"))
|
||||
if value.count(".") != 3:
|
||||
raise ValueError()
|
||||
for val in value.split('.'):
|
||||
for val in value.split("."):
|
||||
if val.startswith("0") and len(val) > 1:
|
||||
raise ValueError()
|
||||
try:
|
||||
|
|
|
@ -34,73 +34,73 @@ class ChoiceOption(Option):
|
|||
|
||||
The option can also have the value ``None``
|
||||
"""
|
||||
|
||||
__slots__ = tuple()
|
||||
_type = 'choice'
|
||||
|
||||
def __init__(self,
|
||||
name,
|
||||
doc,
|
||||
values,
|
||||
*args,
|
||||
**kwargs):
|
||||
_type = "choice"
|
||||
|
||||
def __init__(self, name, doc, values, *args, **kwargs):
|
||||
"""
|
||||
:param values: is a list of values the option can possibly take
|
||||
"""
|
||||
if not isinstance(values, (Calculation, tuple)):
|
||||
raise TypeError(_('values must be a tuple or a calculation for {0}'
|
||||
).format(name))
|
||||
raise TypeError(
|
||||
_("values must be a tuple or a calculation for {0}").format(name)
|
||||
)
|
||||
self._choice_values = values
|
||||
super().__init__(name,
|
||||
doc,
|
||||
*args,
|
||||
**kwargs)
|
||||
super().__init__(name, doc, *args, **kwargs)
|
||||
|
||||
def impl_get_values(self,
|
||||
subconfig: "SubConfig",
|
||||
uncalculated: bool=False,
|
||||
):
|
||||
"""get values allowed by option
|
||||
"""
|
||||
def impl_get_values(
|
||||
self,
|
||||
subconfig: "SubConfig",
|
||||
uncalculated: bool = False,
|
||||
):
|
||||
"""get values allowed by option"""
|
||||
choices = self._choice_values
|
||||
if isinstance(choices, tuple):
|
||||
choices = list(choices)
|
||||
if uncalculated:
|
||||
return choices
|
||||
values = get_calculated_value(subconfig,
|
||||
choices,
|
||||
)[0]
|
||||
|
||||
values = get_calculated_value(
|
||||
subconfig,
|
||||
choices,
|
||||
)[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()))
|
||||
raise ConfigError(
|
||||
_('the calculated values "{0}" for "{1}" is not a list' "").format(
|
||||
values, self.impl_getname()
|
||||
)
|
||||
)
|
||||
return values
|
||||
|
||||
def validate(self,
|
||||
value: Any,
|
||||
) -> None:
|
||||
"""nothing to valide
|
||||
"""
|
||||
def validate(
|
||||
self,
|
||||
value: Any,
|
||||
) -> None:
|
||||
"""nothing to valide"""
|
||||
|
||||
def validate_with_option(self,
|
||||
value: Any,
|
||||
subconfig: "SubConfig",
|
||||
loaded: bool,
|
||||
) -> None:
|
||||
def validate_with_option(
|
||||
self,
|
||||
value: Any,
|
||||
subconfig: "SubConfig",
|
||||
loaded: bool,
|
||||
) -> None:
|
||||
if loaded and isinstance(self._choice_values, Calculation):
|
||||
return
|
||||
values = self.impl_get_values(subconfig)
|
||||
self.validate_values(value, values)
|
||||
|
||||
def validate_values(self,
|
||||
value,
|
||||
values,
|
||||
) -> None:
|
||||
"""validate values
|
||||
"""
|
||||
def validate_values(
|
||||
self,
|
||||
value,
|
||||
values,
|
||||
) -> None:
|
||||
"""validate values"""
|
||||
if values is not undefined and value not in values:
|
||||
if len(values) == 1:
|
||||
raise ValueError(_('only "{0}" is allowed'
|
||||
'').format(values[0]))
|
||||
raise ValueError(_('only {0} are allowed'
|
||||
'').format(display_list(values, add_quote=True)))
|
||||
raise ValueError(_('only "{0}" is allowed' "").format(values[0]))
|
||||
raise ValueError(
|
||||
_("only {0} are allowed" "").format(
|
||||
display_list(values, add_quote=True)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -27,13 +27,12 @@ from .stroption import StrOption
|
|||
|
||||
|
||||
class DateOption(StrOption):
|
||||
"""represents the choice of a date
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'date'
|
||||
"""represents the choice of a date"""
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
__slots__ = tuple()
|
||||
_type = "date"
|
||||
|
||||
def validate(self, value: str) -> None:
|
||||
super().validate(value)
|
||||
try:
|
||||
datetime.strptime(value, "%Y-%m-%d")
|
||||
|
|
|
@ -39,126 +39,139 @@ class DomainnameOption(StrOption):
|
|||
domainname:
|
||||
fqdn: with tld, not supported yet
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'domain name'
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
*args,
|
||||
allow_ip: bool=False,
|
||||
allow_cidr_network: bool=False,
|
||||
type: str='domainname',
|
||||
allow_without_dot: bool=False,
|
||||
allow_startswith_dot: bool=False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
__slots__ = tuple()
|
||||
_type = "domain name"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
*args,
|
||||
allow_ip: bool = False,
|
||||
allow_cidr_network: bool = False,
|
||||
type: str = "domainname",
|
||||
allow_without_dot: bool = False,
|
||||
allow_startswith_dot: bool = False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
||||
if type not in ['netbios', 'hostname', 'domainname']:
|
||||
raise ValueError(_('unknown type {0} for hostname').format(type))
|
||||
extra = {'_dom_type': type}
|
||||
if type not in ["netbios", "hostname", "domainname"]:
|
||||
raise ValueError(_("unknown type {0} for hostname").format(type))
|
||||
extra = {"_dom_type": type}
|
||||
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):
|
||||
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):
|
||||
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):
|
||||
raise ValueError(_('allow_startswith_dot must be a boolean'))
|
||||
extra['_allow_without_dot'] = allow_without_dot
|
||||
if type == 'domainname':
|
||||
raise ValueError(_("allow_startswith_dot must be a boolean"))
|
||||
extra["_allow_without_dot"] = allow_without_dot
|
||||
if type == "domainname":
|
||||
if allow_without_dot:
|
||||
min_time = 0
|
||||
else:
|
||||
min_time = 1
|
||||
regexp = r'((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}'.format(self._get_len(type), min_time)
|
||||
regexp = r"((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}".format(
|
||||
self._get_len(type), min_time
|
||||
)
|
||||
else:
|
||||
regexp = r'((?!-)[a-z0-9-]{{1,{0}}})'.format(self._get_len(type))
|
||||
msg = _('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')
|
||||
regexp = r"((?!-)[a-z0-9-]{{1,{0}}})".format(self._get_len(type))
|
||||
msg = _(
|
||||
'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'
|
||||
)
|
||||
if allow_ip:
|
||||
msg = _('could be a IP, otherwise {}').format(msg)
|
||||
msg_warning = _('could be a IP, otherwise {}').format(msg_warning)
|
||||
msg = _("could be a IP, otherwise {}").format(msg)
|
||||
msg_warning = _("could be a IP, otherwise {}").format(msg_warning)
|
||||
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)
|
||||
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
|
||||
)
|
||||
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)
|
||||
regexp = r'^{0}$'.format(regexp)
|
||||
extra['_domain_re'] = re.compile(regexp)
|
||||
extra['_domain_re_message'] = msg
|
||||
extra['_domain_re_message_warning'] = msg_warning
|
||||
extra['_has_upper'] = re.compile('[A-Z]')
|
||||
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 = r"^{0}$".format(regexp)
|
||||
extra["_domain_re"] = re.compile(regexp)
|
||||
extra["_domain_re_message"] = msg
|
||||
extra["_domain_re_message_warning"] = msg_warning
|
||||
extra["_has_upper"] = re.compile("[A-Z]")
|
||||
if allow_ip:
|
||||
extra['_ip'] = IPOption(name,
|
||||
doc,
|
||||
)
|
||||
extra['_allow_ip'] = allow_ip
|
||||
extra["_ip"] = IPOption(
|
||||
name,
|
||||
doc,
|
||||
)
|
||||
extra["_allow_ip"] = allow_ip
|
||||
if allow_cidr_network:
|
||||
extra['_network'] = NetworkOption(name,
|
||||
doc,
|
||||
cidr=True,
|
||||
)
|
||||
extra['_allow_cidr_network'] = allow_cidr_network
|
||||
extra['_allow_startswith_dot'] = allow_startswith_dot
|
||||
extra["_network"] = NetworkOption(
|
||||
name,
|
||||
doc,
|
||||
cidr=True,
|
||||
)
|
||||
extra["_allow_cidr_network"] = allow_cidr_network
|
||||
extra["_allow_startswith_dot"] = allow_startswith_dot
|
||||
|
||||
super().__init__(name,
|
||||
doc,
|
||||
*args,
|
||||
extra=extra,
|
||||
**kwargs,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
*args,
|
||||
extra=extra,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def _get_len(self, type_):
|
||||
if type_ == 'netbios':
|
||||
if type_ == "netbios":
|
||||
return 15
|
||||
return 63
|
||||
|
||||
def _validate_domain(self,
|
||||
value: str) -> None:
|
||||
def _validate_domain(self, value: str) -> None:
|
||||
def _valid_length(val):
|
||||
if len(val) < 1:
|
||||
raise ValueError(_("invalid length (min 1)"))
|
||||
if len(val) > part_name_length:
|
||||
raise ValueError(_("invalid length (max {0})"
|
||||
"").format(part_name_length))
|
||||
raise ValueError(
|
||||
_("invalid length (max {0})" "").format(part_name_length)
|
||||
)
|
||||
|
||||
part_name_length = self._get_len(self.impl_get_extra('_dom_type'))
|
||||
if self.impl_get_extra('_dom_type') == 'domainname':
|
||||
if not self.impl_get_extra('_allow_without_dot') and not "." in value:
|
||||
part_name_length = self._get_len(self.impl_get_extra("_dom_type"))
|
||||
if self.impl_get_extra("_dom_type") == "domainname":
|
||||
if not self.impl_get_extra("_allow_without_dot") and not "." in value:
|
||||
raise ValueError(_("must have dot"))
|
||||
if len(value) > 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:]
|
||||
else:
|
||||
val = value
|
||||
if val.endswith('.'):
|
||||
if val.endswith("."):
|
||||
nval = val[:-1]
|
||||
else:
|
||||
nval = val
|
||||
for dom in nval.split('.'):
|
||||
for dom in nval.split("."):
|
||||
_valid_length(dom)
|
||||
else:
|
||||
_valid_length(value)
|
||||
|
||||
def _validate_ip_network(self,
|
||||
value: str) -> None:
|
||||
allow_ip = self.impl_get_extra('_allow_ip')
|
||||
allow_cidr_network = self.impl_get_extra('_allow_cidr_network')
|
||||
def _validate_ip_network(self, value: str) -> None:
|
||||
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:
|
||||
raise ValueError(_('must not be an IP'))
|
||||
raise ValueError(_("must not be an IP"))
|
||||
if allow_ip is True:
|
||||
try:
|
||||
self.impl_get_extra('_ip').validate(value)
|
||||
self.impl_get_extra("_ip").validate(value)
|
||||
return
|
||||
except ValueError as err:
|
||||
if allow_cidr_network is False:
|
||||
raise err
|
||||
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)
|
||||
try:
|
||||
# check if it's an IP or network
|
||||
|
@ -168,42 +181,40 @@ class DomainnameOption(StrOption):
|
|||
else:
|
||||
self._validate_ip_network(value)
|
||||
|
||||
def _second_level_validation_domain(self,
|
||||
value: str,
|
||||
warnings_only: bool) -> None:
|
||||
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('.'):
|
||||
def _second_level_validation_domain(self, value: str, warnings_only: bool) -> None:
|
||||
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:]
|
||||
else:
|
||||
val = value
|
||||
if val.endswith('.'):
|
||||
if val.endswith("."):
|
||||
nval = val[:-1]
|
||||
else:
|
||||
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:
|
||||
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_warning"))
|
||||
raise ValueError(self.impl_get_extra("_domain_re_message"))
|
||||
|
||||
def _second_level_validation_ip_network(self,
|
||||
value: str,
|
||||
warnings_only: bool) -> None:
|
||||
allow_ip = self.impl_get_extra('_allow_ip')
|
||||
allow_cidr_network = self.impl_get_extra('_allow_cidr_network')
|
||||
def _second_level_validation_ip_network(
|
||||
self, value: str, warnings_only: bool
|
||||
) -> None:
|
||||
allow_ip = self.impl_get_extra("_allow_ip")
|
||||
allow_cidr_network = self.impl_get_extra("_allow_cidr_network")
|
||||
# it's an IP so validate with IPOption
|
||||
if allow_ip is True and allow_cidr_network is False:
|
||||
try:
|
||||
self.impl_get_extra('_ip').second_level_validation(value, warnings_only)
|
||||
self.impl_get_extra("_ip").second_level_validation(value, warnings_only)
|
||||
return
|
||||
except ValueError as err:
|
||||
raise err
|
||||
if allow_cidr_network is True:
|
||||
self.impl_get_extra('_network').second_level_validation(value, warnings_only)
|
||||
self.impl_get_extra("_network").second_level_validation(
|
||||
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:
|
||||
# check if it's an IP or network
|
||||
ip_interface(value)
|
||||
|
|
|
@ -35,111 +35,120 @@ from ..error import ConfigError
|
|||
from ..autolib import Calculation, get_calculated_value
|
||||
|
||||
|
||||
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
|
||||
class DynOptionDescription(OptionDescription):
|
||||
"""dyn option description
|
||||
"""
|
||||
__slots__ = ('_suffixes',
|
||||
'_subdyns',
|
||||
)
|
||||
NAME_REGEXP = re.compile(r"^[a-zA-Z\d\-_]*$")
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
children: List[BaseOption],
|
||||
suffixes: Calculation,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
|
||||
class DynOptionDescription(OptionDescription):
|
||||
"""dyn option description"""
|
||||
|
||||
__slots__ = (
|
||||
"_identifiers",
|
||||
"_subdyns",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
children: List[BaseOption],
|
||||
identifiers: Calculation,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
# pylint: disable=too-many-arguments
|
||||
super().__init__(name,
|
||||
doc,
|
||||
children,
|
||||
**kwargs,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
children,
|
||||
**kwargs,
|
||||
)
|
||||
# check children + set relation to this dynoptiondescription
|
||||
wself = weakref.ref(self)
|
||||
for child in children:
|
||||
child._setsubdyn(wself)
|
||||
# add suffixes
|
||||
self.value_dependencies(suffixes, is_suffix=True)
|
||||
# if __debug__ and not isinstance(suffixes, Calculation):
|
||||
# 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
|
||||
# add identifiers
|
||||
self.value_dependencies(identifiers, is_identifier=True)
|
||||
self._identifiers = identifiers
|
||||
|
||||
def convert_suffix_to_path(self,
|
||||
suffix: Any,
|
||||
) -> str:
|
||||
"""convert suffix to use it to a path
|
||||
"""
|
||||
if suffix is None:
|
||||
def convert_identifier_to_path(
|
||||
self,
|
||||
identifier: Any,
|
||||
) -> str:
|
||||
"""convert identifier to use it to a path"""
|
||||
if identifier is None:
|
||||
return None
|
||||
if not isinstance(suffix, str):
|
||||
suffix = str(suffix)
|
||||
if '.' in suffix:
|
||||
suffix = suffix.replace('.', '_')
|
||||
return suffix
|
||||
if not isinstance(identifier, str):
|
||||
identifier = str(identifier)
|
||||
if "." in identifier:
|
||||
identifier = identifier.replace(".", "_")
|
||||
return identifier
|
||||
|
||||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
return True
|
||||
|
||||
def option_is_self(self,
|
||||
option,
|
||||
) -> bool:
|
||||
def option_is_self(
|
||||
self,
|
||||
option,
|
||||
) -> bool:
|
||||
return option == self
|
||||
|
||||
def impl_getname(self, suffix=None) -> str:
|
||||
"""get name
|
||||
"""
|
||||
def impl_getname(self, identifier=None) -> str:
|
||||
"""get name"""
|
||||
name = super().impl_getname()
|
||||
if suffix is None:
|
||||
if identifier is None:
|
||||
return name
|
||||
path_suffix = self.convert_suffix_to_path(suffix)
|
||||
return name + path_suffix
|
||||
path_identifier = self.convert_identifier_to_path(identifier)
|
||||
return name + path_identifier
|
||||
|
||||
def get_suffixes(self,
|
||||
parent: 'SubConfig',
|
||||
*,
|
||||
uncalculated: bool=False,
|
||||
) -> List[str]:
|
||||
"""get dynamic suffixes
|
||||
"""
|
||||
subconfig = parent.get_child(self,
|
||||
None,
|
||||
False,
|
||||
properties=None,
|
||||
)
|
||||
suffixes = self._suffixes
|
||||
if isinstance(suffixes, list):
|
||||
suffixes = suffixes.copy()
|
||||
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 suffixes
|
||||
values = get_calculated_value(subconfig,
|
||||
suffixes,
|
||||
validate_properties=False,
|
||||
)[0]
|
||||
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 suffixes for '
|
||||
f'option "{self.impl_get_display_name(subconfig)}", is not '
|
||||
f'a list ({values})'))
|
||||
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_suffix_to_path(val)
|
||||
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 suffix "{}" for option "{}"'
|
||||
'').format(cval,
|
||||
self.impl_get_display_name(subconfig)))
|
||||
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(_(f'DynOptionDescription "{self._name}" suffixes return a list with '
|
||||
f'same values "{values_}"'''))
|
||||
raise ValueError(
|
||||
_(
|
||||
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'
|
||||
).format(self._name, values_)
|
||||
)
|
||||
return values_
|
||||
|
|
|
@ -27,8 +27,10 @@ from .stroption import RegexpOption
|
|||
|
||||
|
||||
class EmailOption(RegexpOption):
|
||||
"""represents a choice of an email
|
||||
"""
|
||||
"""represents a choice of an email"""
|
||||
|
||||
__slots__ = tuple()
|
||||
_regexp = re.compile(r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||
_type = 'email address'
|
||||
_regexp = re.compile(
|
||||
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"
|
||||
)
|
||||
_type = "email address"
|
||||
|
|
|
@ -28,45 +28,54 @@ from .stroption import StrOption
|
|||
|
||||
|
||||
class FilenameOption(StrOption):
|
||||
"""validate file or directory name
|
||||
"""
|
||||
"""validate file or directory name"""
|
||||
|
||||
__slots__ = tuple()
|
||||
_type = 'file name'
|
||||
_type = "file name"
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
*args,
|
||||
allow_relative=False,
|
||||
test_existence=False,
|
||||
types=['file', 'directory'],
|
||||
**kwargs):
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
*args,
|
||||
allow_relative=False,
|
||||
test_existence=False,
|
||||
types=["file", "directory"],
|
||||
**kwargs,
|
||||
):
|
||||
if not isinstance(types, list):
|
||||
raise ValueError(_(f'types parameter must be a list, not "{types}" for "{name}"'))
|
||||
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']:
|
||||
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)
|
||||
extra = {
|
||||
"_allow_relative": allow_relative,
|
||||
"_test_existence": test_existence,
|
||||
"_types": types,
|
||||
}
|
||||
super().__init__(name, *args, extra=extra, **kwargs)
|
||||
|
||||
def validate(self,
|
||||
value: str,
|
||||
) -> None:
|
||||
def validate(
|
||||
self,
|
||||
value: str,
|
||||
) -> None:
|
||||
super().validate(value)
|
||||
if not self.impl_get_extra('_allow_relative') and not value.startswith('/'):
|
||||
if not self.impl_get_extra("_allow_relative") and not value.startswith("/"):
|
||||
raise ValueError(_('must starts with "/"'))
|
||||
if value is not None and self.impl_get_extra('_test_existence'):
|
||||
types = self.impl_get_extra('_types')
|
||||
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():
|
||||
if "file" in types and file.is_file():
|
||||
found = True
|
||||
if not found and 'directory' in types and file.is_dir():
|
||||
if not found and "directory" in types and file.is_dir():
|
||||
found = True
|
||||
if not found:
|
||||
raise ValueError(_(f'cannot find {display_list(types, separator="or")} "{value}"'))
|
||||
raise ValueError(
|
||||
_('cannot find {0} "{1}"').format(
|
||||
display_list(types, separator="or"), value
|
||||
)
|
||||
)
|
||||
|
|
|
@ -26,12 +26,11 @@ from .option import Option
|
|||
|
||||
|
||||
class FloatOption(Option):
|
||||
"""represents a choice of a floating point number
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'float'
|
||||
"""represents a choice of a floating point number"""
|
||||
|
||||
def validate(self,
|
||||
value: float) -> None:
|
||||
__slots__ = tuple()
|
||||
_type = "float"
|
||||
|
||||
def validate(self, value: float) -> None:
|
||||
if not isinstance(value, float):
|
||||
raise ValueError()
|
||||
|
|
|
@ -28,40 +28,35 @@ from .option import Option
|
|||
class IntOption(Option):
|
||||
"represents a choice of an integer"
|
||||
__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 = {}
|
||||
if min_number is not None:
|
||||
extra['min_number'] = min_number
|
||||
extra["min_number"] = min_number
|
||||
if max_number is not None:
|
||||
extra['max_number'] = max_number
|
||||
extra["max_number"] = max_number
|
||||
super().__init__(*args, extra=extra, **kwargs)
|
||||
|
||||
def validate(self,
|
||||
value: int,
|
||||
) -> None:
|
||||
def validate(
|
||||
self,
|
||||
value: int,
|
||||
) -> None:
|
||||
if not isinstance(value, int):
|
||||
raise ValueError()
|
||||
|
||||
def second_level_validation(self,
|
||||
value,
|
||||
warnings_only):
|
||||
min_number = self.impl_get_extra('min_number')
|
||||
def second_level_validation(self, value, warnings_only):
|
||||
min_number = self.impl_get_extra("min_number")
|
||||
if min_number is not None and value < min_number:
|
||||
if warnings_only:
|
||||
msg = 'value should be greater than "{0}"'
|
||||
msg = _('value should be equal or greater than "{0}"')
|
||||
else:
|
||||
msg = 'value must be greater than "{0}"'
|
||||
raise ValueError(_(msg).format(min_number))
|
||||
max_number = self.impl_get_extra('max_number')
|
||||
msg = _('value must be equal or greater than "{0}"')
|
||||
raise ValueError(msg.format(min_number))
|
||||
max_number = self.impl_get_extra("max_number")
|
||||
if max_number is not None and value > max_number:
|
||||
if warnings_only:
|
||||
msg = 'value should be less than "{0}"'
|
||||
msg = _('value should be less than "{0}"')
|
||||
else:
|
||||
msg = 'value must be less than "{0}"'
|
||||
raise ValueError(_(msg).format(max_number))
|
||||
msg = _('value must be less than "{0}"')
|
||||
raise ValueError(msg.format(max_number))
|
||||
|
|
|
@ -27,26 +27,26 @@ from .stroption import StrOption
|
|||
|
||||
|
||||
class IPOption(StrOption):
|
||||
"""represents the choice of an ip
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'IP'
|
||||
"""represents the choice of an ip"""
|
||||
|
||||
def __init__(self,
|
||||
*args,
|
||||
private_only=False,
|
||||
allow_reserved=False,
|
||||
cidr=False,
|
||||
extra=None,
|
||||
**kwargs):
|
||||
__slots__ = tuple()
|
||||
_type = "IP"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
private_only=False,
|
||||
allow_reserved=False,
|
||||
cidr=False,
|
||||
extra=None,
|
||||
**kwargs,
|
||||
):
|
||||
if extra is None:
|
||||
extra = {}
|
||||
extra['_private_only'] = private_only
|
||||
extra['_allow_reserved'] = allow_reserved
|
||||
extra['_cidr'] = cidr
|
||||
super().__init__(*args,
|
||||
extra=extra,
|
||||
**kwargs)
|
||||
extra["_private_only"] = private_only
|
||||
extra["_allow_reserved"] = allow_reserved
|
||||
extra["_cidr"] = cidr
|
||||
super().__init__(*args, extra=extra, **kwargs)
|
||||
|
||||
def _validate_cidr(self, value):
|
||||
try:
|
||||
|
@ -64,27 +64,24 @@ class IPOption(StrOption):
|
|||
except ValueError as err:
|
||||
raise ValueError() from err
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
def validate(self, value: str) -> None:
|
||||
super().validate(value)
|
||||
if self.impl_get_extra('_cidr'):
|
||||
if '/' not in value:
|
||||
if self.impl_get_extra("_cidr"):
|
||||
if "/" not in value:
|
||||
raise ValueError(_('CIDR address must have a "/"'))
|
||||
self._validate_cidr(value)
|
||||
else:
|
||||
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)
|
||||
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:
|
||||
msg = _("shouldn't be reserved IP")
|
||||
else:
|
||||
msg = _("mustn't be reserved IP")
|
||||
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:
|
||||
msg = _("should be private IP")
|
||||
else:
|
||||
|
|
|
@ -26,6 +26,7 @@ from typing import List, Iterator, Optional
|
|||
from ..i18n import _
|
||||
from ..setting import groups, undefined, ALLOWED_LEADER_PROPERTIES
|
||||
from .optiondescription import OptionDescription
|
||||
|
||||
# from .syndynoption import SynDynLeadership
|
||||
from .baseoption import BaseOption
|
||||
from .option import Option
|
||||
|
@ -34,60 +35,95 @@ from ..autolib import Calculation
|
|||
|
||||
|
||||
class Leadership(OptionDescription):
|
||||
"""Leadership
|
||||
"""
|
||||
# pylint: disable=too-many-arguments
|
||||
__slots__ = ('leader',
|
||||
'followers',
|
||||
)
|
||||
"""Leadership"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc,
|
||||
children: List[BaseOption],
|
||||
**kwargs,
|
||||
) -> None:
|
||||
super().__init__(name,
|
||||
doc,
|
||||
children,
|
||||
**kwargs,
|
||||
)
|
||||
# pylint: disable=too-many-arguments
|
||||
__slots__ = (
|
||||
"leader",
|
||||
"followers",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc,
|
||||
children: List[BaseOption],
|
||||
**kwargs,
|
||||
) -> None:
|
||||
if "group_type" in kwargs:
|
||||
raise LeadershipError(
|
||||
_('cannot set "group_type" attribute for a Leadership')
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
children,
|
||||
**kwargs,
|
||||
)
|
||||
self._group_type = groups.leadership
|
||||
followers = []
|
||||
if len(children) < 2:
|
||||
raise ValueError(_('a leader and a follower are mandatories in leadership "{}"'
|
||||
'').format(name))
|
||||
leader = children[0]
|
||||
raise ValueError(
|
||||
_(
|
||||
'a leader and a follower are mandatories in leadership "{}"' ""
|
||||
).format(name)
|
||||
)
|
||||
for idx, child in enumerate(children):
|
||||
if __debug__:
|
||||
self._check_child_is_valid(child)
|
||||
self._check_child_is_valid(child, idx, children)
|
||||
if idx != 0:
|
||||
if __debug__:
|
||||
self._check_default_value(child)
|
||||
# remove empty property for follower
|
||||
child._properties = frozenset(child._properties - {'empty', 'unique'})
|
||||
child._properties = frozenset(child._properties - {"empty", "unique"})
|
||||
followers.append(child)
|
||||
child._add_dependency(self)
|
||||
child._leadership = weakref.ref(self)
|
||||
if __debug__:
|
||||
leader = children[0]
|
||||
for prop in leader.impl_getproperties():
|
||||
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation):
|
||||
raise LeadershipError(_('leader cannot have "{}" property').format(prop))
|
||||
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(
|
||||
prop, Calculation
|
||||
):
|
||||
raise LeadershipError(
|
||||
_('leader cannot have "{}" property').format(prop)
|
||||
)
|
||||
|
||||
def _check_child_is_valid(self, child: BaseOption):
|
||||
def _check_child_is_valid(
|
||||
self,
|
||||
child: BaseOption,
|
||||
index: int,
|
||||
children: [BaseOption],
|
||||
) -> None:
|
||||
if child.impl_is_symlinkoption():
|
||||
raise ValueError(_('leadership "{0}" shall not have '
|
||||
"a symlinkoption").format(self.impl_get_display_name(None)))
|
||||
if not index:
|
||||
raise ValueError(
|
||||
_("leadership {0} shall not have " "a symlinkoption").format(
|
||||
self.impl_get_display_name(None, with_quote=True)
|
||||
)
|
||||
)
|
||||
return
|
||||
if not isinstance(child, Option):
|
||||
raise ValueError(_('leadership "{0}" shall not have '
|
||||
'a subgroup').format(self.impl_get_display_name(None)))
|
||||
raise ValueError(
|
||||
_("leadership {0} shall not have " "a subgroup").format(
|
||||
self.impl_get_display_name(None, with_quote=True)
|
||||
)
|
||||
)
|
||||
if not child.impl_is_multi():
|
||||
raise ValueError(_('only multi option allowed in leadership "{0}" but option '
|
||||
'"{1}" is not a multi'
|
||||
'').format(self.impl_get_display_name(None),
|
||||
child.impl_get_display_name(None)))
|
||||
raise ValueError(
|
||||
_(
|
||||
"only multi option allowed in leadership {0} but option "
|
||||
"{1} is not a multi"
|
||||
""
|
||||
).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):
|
||||
if child.impl_is_symlinkoption():
|
||||
return
|
||||
default = child.impl_getdefault()
|
||||
if default != []:
|
||||
if child.impl_is_submulti() and isinstance(default, (list, tuple)):
|
||||
|
@ -101,78 +137,84 @@ class Leadership(OptionDescription):
|
|||
else:
|
||||
calculation = isinstance(default, Calculation)
|
||||
if not calculation:
|
||||
raise ValueError(_('not allowed default value for follower option '
|
||||
f'"{child.impl_get_display_name(None)}" in leadership '
|
||||
f'"{self.impl_get_display_name(None)}"'))
|
||||
raise ValueError(
|
||||
_(
|
||||
"not allowed default value for follower option {0} in leadership {1}"
|
||||
).format(
|
||||
child.impl_get_display_name(None, with_quote=True),
|
||||
self.impl_get_display_name(None, with_quote=True),
|
||||
)
|
||||
)
|
||||
|
||||
def _setsubdyn(self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
def _setsubdyn(
|
||||
self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
for chld in self._children[1]:
|
||||
chld._setsubdyn(subdyn)
|
||||
super()._setsubdyn(subdyn)
|
||||
|
||||
def is_leader(self,
|
||||
opt: Option,
|
||||
) -> bool:
|
||||
"""the option is the leader
|
||||
"""
|
||||
def is_leader(
|
||||
self,
|
||||
opt: Option,
|
||||
) -> bool:
|
||||
"""the option is the leader"""
|
||||
leader = self.get_leader()
|
||||
if opt.impl_is_dynsymlinkoption():
|
||||
opt = opt.opt
|
||||
return opt == leader
|
||||
|
||||
def get_leader(self) -> Option:
|
||||
"""get leader
|
||||
"""
|
||||
"""get leader"""
|
||||
return self._children[1][0]
|
||||
|
||||
def get_followers(self) -> Iterator[Option]:
|
||||
"""get all followers
|
||||
"""
|
||||
"""get all followers"""
|
||||
for follower in self._children[1][1:]:
|
||||
yield follower
|
||||
|
||||
def in_same_leadership(self,
|
||||
opt: Option,
|
||||
) -> bool:
|
||||
"""check if followers are in same leadership
|
||||
"""
|
||||
def in_same_leadership(
|
||||
self,
|
||||
opt: Option,
|
||||
) -> bool:
|
||||
"""check if followers are in same leadership"""
|
||||
if opt.impl_is_dynsymlinkoption():
|
||||
opt = opt.opt
|
||||
return opt in self._children[1]
|
||||
|
||||
def reset(self, parent: "SubConfig") -> None:
|
||||
"""reset follower value
|
||||
"""
|
||||
"""reset follower value"""
|
||||
values = parent.config_bag.context.get_values()
|
||||
for follower in self.get_followers():
|
||||
subconfig_follower = parent.get_child(follower,
|
||||
None,
|
||||
False,
|
||||
)
|
||||
values.reset(subconfig_follower,
|
||||
validate=False,
|
||||
)
|
||||
subconfig_follower = parent.get_child(
|
||||
follower,
|
||||
None,
|
||||
False,
|
||||
)
|
||||
values.reset(
|
||||
subconfig_follower,
|
||||
validate=False,
|
||||
)
|
||||
|
||||
def follower_force_store_value(self,
|
||||
value,
|
||||
subconfig: 'SubConfig',
|
||||
owner,
|
||||
) -> None:
|
||||
"""apply force_store_value to follower
|
||||
"""
|
||||
def follower_force_store_value(
|
||||
self,
|
||||
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:
|
||||
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:
|
||||
|
@ -183,25 +225,27 @@ class Leadership(OptionDescription):
|
|||
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,
|
||||
)
|
||||
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,
|
||||
*,
|
||||
followers: Optional[List[Option]]=undefined,
|
||||
) -> None:
|
||||
"""pop leader value and follower's one
|
||||
"""
|
||||
def pop(
|
||||
self,
|
||||
subconfig: "SubConfig",
|
||||
index: int,
|
||||
*,
|
||||
followers: Optional[List[Option]] = undefined,
|
||||
) -> None:
|
||||
"""pop leader value and follower's one"""
|
||||
if followers is undefined:
|
||||
# followers are not undefined only in SynDynLeadership
|
||||
followers = self.get_followers()
|
||||
|
@ -209,60 +253,58 @@ class Leadership(OptionDescription):
|
|||
config_bag.remove_validation()
|
||||
values = config_bag.context.get_values()
|
||||
for follower in followers:
|
||||
sub_subconfig = subconfig.parent.get_child(follower,
|
||||
index,
|
||||
True,
|
||||
properties=set(), # do not check force_default_on_freeze
|
||||
# or force_metaconfig_on_freeze
|
||||
config_bag=config_bag,
|
||||
)
|
||||
sub_subconfig = subconfig.parent.get_child(
|
||||
follower,
|
||||
index,
|
||||
True,
|
||||
properties=set(), # do not check force_default_on_freeze
|
||||
# or force_metaconfig_on_freeze
|
||||
config_bag=config_bag,
|
||||
)
|
||||
values.reduce_index(sub_subconfig)
|
||||
|
||||
def reset_cache(self,
|
||||
path: str,
|
||||
config_bag: 'ConfigBag',
|
||||
resetted_opts: List[Option],
|
||||
) -> None:
|
||||
self._reset_cache(path,
|
||||
self.get_leader(),
|
||||
self.get_followers(),
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
def reset_cache(
|
||||
self,
|
||||
path: str,
|
||||
config_bag: "ConfigBag",
|
||||
resetted_opts: List[Option],
|
||||
) -> None:
|
||||
self._reset_cache(
|
||||
path,
|
||||
self.get_leader(),
|
||||
self.get_followers(),
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
|
||||
def _reset_cache(self,
|
||||
path: str,
|
||||
leader: Option,
|
||||
followers: List[Option],
|
||||
config_bag: 'ConfigBag',
|
||||
resetted_opts: List[Option],
|
||||
) -> None:
|
||||
super().reset_cache(path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
def _reset_cache(
|
||||
self,
|
||||
path: str,
|
||||
leader: Option,
|
||||
followers: List[Option],
|
||||
config_bag: "ConfigBag",
|
||||
resetted_opts: List[Option],
|
||||
) -> None:
|
||||
super().reset_cache(
|
||||
path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
leader_path = leader.impl_getpath()
|
||||
if leader_path not in resetted_opts:
|
||||
leader.reset_cache(leader_path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
leader.reset_cache(
|
||||
leader_path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
for follower in followers:
|
||||
follower_path = follower.impl_getpath()
|
||||
if follower_path not in resetted_opts:
|
||||
follower.reset_cache(follower_path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
follower.reset_cache(
|
||||
follower_path,
|
||||
config_bag,
|
||||
resetted_opts,
|
||||
)
|
||||
|
||||
def impl_is_leadership(self) -> None:
|
||||
return True
|
||||
#
|
||||
# def to_dynoption(self,
|
||||
# rootpath: str,
|
||||
# suffixes: Optional[list],
|
||||
# ) -> SynDynLeadership:
|
||||
# return SynDynLeadership(self,
|
||||
# rootpath,
|
||||
# suffixes,
|
||||
# )
|
||||
|
|
|
@ -27,8 +27,8 @@ from .stroption import RegexpOption
|
|||
|
||||
|
||||
class MACOption(RegexpOption):
|
||||
"""represents the choice of a mac address
|
||||
"""
|
||||
"""represents the choice of a mac address"""
|
||||
|
||||
__slots__ = tuple()
|
||||
_regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$")
|
||||
_type = 'mac address'
|
||||
_type = "mac address"
|
||||
|
|
|
@ -26,18 +26,17 @@ from .stroption import StrOption
|
|||
|
||||
|
||||
class NetmaskOption(StrOption):
|
||||
"""represents the choice of a netmask
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'netmask address'
|
||||
"""represents the choice of a netmask"""
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
__slots__ = tuple()
|
||||
_type = "netmask address"
|
||||
|
||||
def validate(self, value: str) -> None:
|
||||
super().validate(value)
|
||||
for val in value.split('.'):
|
||||
for val in value.split("."):
|
||||
if val.startswith("0") and len(val) > 1:
|
||||
raise ValueError()
|
||||
try:
|
||||
ip_network(f'0.0.0.0/{value}')
|
||||
ip_network(f"0.0.0.0/{value}")
|
||||
except ValueError as err:
|
||||
raise ValueError() from err
|
||||
|
|
|
@ -29,30 +29,24 @@ from .stroption import StrOption
|
|||
class NetworkOption(StrOption):
|
||||
"represents the choice of a network"
|
||||
__slots__ = tuple()
|
||||
_type = 'network address'
|
||||
_type = "network address"
|
||||
|
||||
def __init__(self,
|
||||
*args,
|
||||
cidr=False,
|
||||
**kwargs):
|
||||
extra = {'_cidr': cidr}
|
||||
super().__init__(*args,
|
||||
extra=extra,
|
||||
**kwargs)
|
||||
def __init__(self, *args, 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)
|
||||
if value.count('.') != 3:
|
||||
if value.count(".") != 3:
|
||||
raise ValueError()
|
||||
cidr = self.impl_get_extra('_cidr')
|
||||
cidr = self.impl_get_extra("_cidr")
|
||||
if cidr:
|
||||
if '/' not in value:
|
||||
raise ValueError(_('must use CIDR notation'))
|
||||
value_ = value.split('/')[0]
|
||||
if "/" not in value:
|
||||
raise ValueError(_("must use CIDR notation"))
|
||||
value_ = value.split("/")[0]
|
||||
else:
|
||||
value_ = value
|
||||
for val in value_.split('.'):
|
||||
for val in value_.split("."):
|
||||
if val.startswith("0") and len(val) > 1:
|
||||
raise ValueError()
|
||||
try:
|
||||
|
@ -60,9 +54,7 @@ class NetworkOption(StrOption):
|
|||
except ValueError as 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 warnings_only:
|
||||
msg = _("shouldn't be reserved network")
|
||||
|
|
|
@ -37,37 +37,43 @@ class Option(BaseOption):
|
|||
|
||||
Reminder: an Option object is **not** a container for the value.
|
||||
"""
|
||||
__slots__ = ('_extra',
|
||||
'_warnings_only',
|
||||
# multi
|
||||
'_multi',
|
||||
# value
|
||||
'_default',
|
||||
'_default_multi',
|
||||
#
|
||||
'_validators',
|
||||
#
|
||||
'_leadership',
|
||||
'_choice_values',
|
||||
'_choice_values_params',
|
||||
)
|
||||
__slots__ = (
|
||||
"_extra",
|
||||
"_warnings_only",
|
||||
# multi
|
||||
"_multi",
|
||||
# value
|
||||
"_default",
|
||||
"_default_multi",
|
||||
#
|
||||
"_validators",
|
||||
#
|
||||
"_leadership",
|
||||
"_choice_values",
|
||||
"_choice_values_params",
|
||||
)
|
||||
_type = None
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
default: Any=undefined,
|
||||
default_multi: Any=None,
|
||||
multi: bool=False,
|
||||
validators: Optional[List[Calculation]]=None,
|
||||
properties: Optional[List[str]]=None,
|
||||
warnings_only: bool=False,
|
||||
extra: Optional[Dict]=None,
|
||||
informations: Optional[Dict]=None,
|
||||
):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
default: Any = undefined,
|
||||
default_multi: Any = None,
|
||||
multi: bool = False,
|
||||
validators: Optional[List[Calculation]] = None,
|
||||
properties: Optional[List[str]] = None,
|
||||
warnings_only: bool = False,
|
||||
extra: Optional[Dict] = None,
|
||||
informations: Optional[Dict] = None,
|
||||
):
|
||||
_setattr = object.__setattr__
|
||||
if not multi and default_multi is not None:
|
||||
raise ValueError(_("default_multi is set whereas multi is False"
|
||||
" in option: {0}").format(name))
|
||||
raise ValueError(
|
||||
_(
|
||||
"default_multi is set whereas multi is False" " in option: {0}"
|
||||
).format(name)
|
||||
)
|
||||
if default is undefined:
|
||||
if multi is False:
|
||||
default = None
|
||||
|
@ -83,117 +89,140 @@ class Option(BaseOption):
|
|||
is_multi = True
|
||||
_multi = submulti
|
||||
else:
|
||||
raise ValueError(_('invalid multi type "{}" for "{}"').format(multi,
|
||||
name,
|
||||
))
|
||||
raise ValueError(
|
||||
_('invalid multi type "{}" for "{}"').format(
|
||||
multi,
|
||||
name,
|
||||
)
|
||||
)
|
||||
if _multi != 1:
|
||||
_setattr(self, '_multi', _multi)
|
||||
_setattr(self, "_multi", _multi)
|
||||
if multi is not False and default is None:
|
||||
default = []
|
||||
super().__init__(name,
|
||||
doc,
|
||||
informations,
|
||||
properties=properties,
|
||||
is_multi=is_multi,
|
||||
)
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
informations,
|
||||
properties=properties,
|
||||
is_multi=is_multi,
|
||||
)
|
||||
if validators is not None:
|
||||
if __debug__ and not isinstance(validators, list):
|
||||
raise ValueError(_(f'validators must be a list of Calculation for "{name}"'))
|
||||
raise ValueError(
|
||||
_('validators must be a list of Calculation for "{0}"').format(name)
|
||||
)
|
||||
for validator in validators:
|
||||
if __debug__ and not isinstance(validator, Calculation):
|
||||
raise ValueError(_('validators must be a Calculation for "{}"').format(name))
|
||||
raise ValueError(
|
||||
_('validators must be a Calculation for "{0}"').format(name)
|
||||
)
|
||||
self.value_dependency(validator)
|
||||
self._validators = tuple(validators)
|
||||
if extra is not None and extra != {}:
|
||||
_setattr(self, '_extra', extra)
|
||||
_setattr(self, "_extra", extra)
|
||||
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:
|
||||
|
||||
def test_multi_value(value):
|
||||
if isinstance(value, Calculation):
|
||||
return
|
||||
# option_bag = OptionBag(self,
|
||||
# None,
|
||||
# undefined,
|
||||
# properties=None,
|
||||
# )
|
||||
# option_bag = OptionBag(self,
|
||||
# None,
|
||||
# undefined,
|
||||
# properties=None,
|
||||
# )
|
||||
try:
|
||||
self.validate(value)
|
||||
self.validate_with_option(value,
|
||||
None,
|
||||
loaded=True,
|
||||
)
|
||||
self.validate_with_option(
|
||||
value,
|
||||
None,
|
||||
loaded=True,
|
||||
)
|
||||
except ValueError as err:
|
||||
str_err = str(err)
|
||||
if not str_err:
|
||||
raise ValueError(_('invalid default_multi value "{0}" '
|
||||
'for option "{1}"').format(str(value),
|
||||
self.impl_get_display_name(None))
|
||||
) from err
|
||||
raise ValueError(_(f'invalid default_multi value "{value}" for option '
|
||||
f'"{self.impl_get_display_name(None)}", {str_err}')
|
||||
) from err
|
||||
raise ValueError(
|
||||
_(
|
||||
'invalid default_multi value "{0}" ' "for option {1}"
|
||||
).format(
|
||||
str(value),
|
||||
self.impl_get_display_name(None, with_quote=True),
|
||||
)
|
||||
) from err
|
||||
raise ValueError(
|
||||
_(
|
||||
'invalid default_multi value "{0}" for option {1}, {2}'
|
||||
).format(
|
||||
value,
|
||||
self.impl_get_display_name(None, with_quote=True),
|
||||
str_err,
|
||||
)
|
||||
) from err
|
||||
|
||||
if _multi is submulti:
|
||||
if not isinstance(default_multi, Calculation):
|
||||
if not isinstance(default_multi, list):
|
||||
raise ValueError(_('invalid default_multi value "{0}" '
|
||||
'for option "{1}", must be a list for a submulti'
|
||||
'').format(str(default_multi),
|
||||
self.impl_get_display_name(None)))
|
||||
raise ValueError(
|
||||
_(
|
||||
'invalid default_multi value "{0}" '
|
||||
"for option {1}, must be a list for a submulti"
|
||||
""
|
||||
).format(
|
||||
str(default_multi),
|
||||
self.impl_get_display_name(None, with_quote=True),
|
||||
)
|
||||
)
|
||||
for value in default_multi:
|
||||
test_multi_value(value)
|
||||
else:
|
||||
test_multi_value(default_multi)
|
||||
_setattr(self, '_default_multi', default_multi)
|
||||
# option_bag = OptionBag(self,
|
||||
# None,
|
||||
# undefined,
|
||||
# properties=None,
|
||||
# )
|
||||
self.impl_validate(None,
|
||||
default,
|
||||
loaded=True,
|
||||
)
|
||||
self.impl_validate(None,
|
||||
default,
|
||||
check_error=False,
|
||||
loaded=True,
|
||||
)
|
||||
_setattr(self, "_default_multi", default_multi)
|
||||
# option_bag = OptionBag(self,
|
||||
# None,
|
||||
# undefined,
|
||||
# properties=None,
|
||||
# )
|
||||
self.impl_validate(
|
||||
None,
|
||||
default,
|
||||
loaded=True,
|
||||
)
|
||||
self.impl_validate(
|
||||
None,
|
||||
default,
|
||||
check_error=False,
|
||||
loaded=True,
|
||||
)
|
||||
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):
|
||||
default = tuple(default)
|
||||
_setattr(self, '_default', default)
|
||||
_setattr(self, "_default", default)
|
||||
|
||||
#__________________________________________________________________________
|
||||
# __________________________________________________________________________
|
||||
# option's information
|
||||
|
||||
def impl_is_multi(self) -> bool:
|
||||
"""is it a multi option
|
||||
"""
|
||||
return getattr(self, '_multi', 1) != 1
|
||||
"""is it a multi option"""
|
||||
return getattr(self, "_multi", 1) != 1
|
||||
|
||||
def impl_is_submulti(self) -> bool:
|
||||
"""is it a submulti option
|
||||
"""
|
||||
return getattr(self, '_multi', 1) == 2
|
||||
"""is it a submulti option"""
|
||||
return getattr(self, "_multi", 1) == 2
|
||||
|
||||
def impl_is_dynsymlinkoption(self) -> bool:
|
||||
"""is a dynsymlinkoption?
|
||||
"""
|
||||
"""is a dynsymlinkoption?"""
|
||||
return False
|
||||
|
||||
def get_type(self) -> str:
|
||||
"""get the type of option
|
||||
"""
|
||||
"""get the type of option"""
|
||||
return self._type
|
||||
|
||||
def impl_getdefault(self) -> Any:
|
||||
"""accessing the default value
|
||||
"""
|
||||
"""accessing the default value"""
|
||||
is_multi = self.impl_is_multi()
|
||||
default = getattr(self, '_default', undefined)
|
||||
default = getattr(self, "_default", undefined)
|
||||
if default is undefined:
|
||||
if is_multi:
|
||||
default = []
|
||||
|
@ -204,164 +233,186 @@ class Option(BaseOption):
|
|||
return default
|
||||
|
||||
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():
|
||||
default_value = []
|
||||
else:
|
||||
default_value = None
|
||||
return getattr(self, '_default_multi', default_value)
|
||||
return getattr(self, "_default_multi", default_value)
|
||||
|
||||
def impl_get_extra(self,
|
||||
key: str,
|
||||
) -> Any:
|
||||
"""if extra parameters are store get it
|
||||
"""
|
||||
extra = getattr(self, '_extra', {})
|
||||
def impl_get_extra(
|
||||
self,
|
||||
key: str,
|
||||
) -> Any:
|
||||
"""if extra parameters are store get it"""
|
||||
extra = getattr(self, "_extra", {})
|
||||
if isinstance(extra, tuple):
|
||||
if key in extra[0]:
|
||||
return extra[1][extra[0].index(key)]
|
||||
return None
|
||||
return extra.get(key)
|
||||
|
||||
#__________________________________________________________________________
|
||||
# __________________________________________________________________________
|
||||
# validator
|
||||
def impl_validate(self,
|
||||
subconfig: Optional["SubConfig"],
|
||||
value: Any,
|
||||
*,
|
||||
check_error: bool=True,
|
||||
loaded: bool=False,
|
||||
) -> bool:
|
||||
def impl_validate(
|
||||
self,
|
||||
subconfig: Optional["SubConfig"],
|
||||
value: Any,
|
||||
*,
|
||||
check_error: bool = True,
|
||||
loaded: bool = False,
|
||||
) -> bool:
|
||||
"""Return True if value is really valid
|
||||
If not validate or invalid return it returns False
|
||||
"""
|
||||
if check_error and subconfig and \
|
||||
not 'validator' in subconfig.config_bag.properties:
|
||||
if (
|
||||
check_error
|
||||
and subconfig
|
||||
and not "validator" in subconfig.config_bag.properties
|
||||
):
|
||||
return False
|
||||
if subconfig:
|
||||
force_index = subconfig.index
|
||||
else:
|
||||
force_index = None
|
||||
is_warnings_only = getattr(self, '_warnings_only', False)
|
||||
is_warnings_only = getattr(self, "_warnings_only", False)
|
||||
|
||||
def _is_not_unique(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
|
||||
lvalue = [val for val in value if val is not None]
|
||||
if len(set(lvalue)) == len(lvalue):
|
||||
return
|
||||
for idx, val in enumerate(value):
|
||||
if val not in value[idx+1:]:
|
||||
if val not in value[idx + 1 :]:
|
||||
continue
|
||||
raise ValueError(_('the value "{}" is not unique'
|
||||
'').format(val))
|
||||
raise ValueError(_('the value "{}" is not unique' "").format(val))
|
||||
|
||||
def calculation_validator(val,
|
||||
_index,
|
||||
):
|
||||
for validator in getattr(self, '_validators', []):
|
||||
calc_is_warnings_only = hasattr(validator, 'warnings_only') and \
|
||||
validator.warnings_only
|
||||
if ((check_error and not calc_is_warnings_only) or
|
||||
(not check_error and calc_is_warnings_only)):
|
||||
def calculation_validator(
|
||||
val,
|
||||
_index,
|
||||
):
|
||||
for validator in getattr(self, "_validators", []):
|
||||
calc_is_warnings_only = (
|
||||
hasattr(validator, "warnings_only") and validator.warnings_only
|
||||
)
|
||||
if (check_error and not calc_is_warnings_only) or (
|
||||
not check_error and calc_is_warnings_only
|
||||
):
|
||||
try:
|
||||
kwargs = {'allow_value_error': True,
|
||||
'force_value_warning': calc_is_warnings_only,
|
||||
}
|
||||
kwargs = {
|
||||
"allow_value_error": True,
|
||||
"force_value_warning": calc_is_warnings_only,
|
||||
}
|
||||
if _index is not None and subconfig.index == _index:
|
||||
lsubconfig = subconfig
|
||||
else:
|
||||
suffix = subconfig.suffixes
|
||||
if suffix is not None:
|
||||
suffix = suffix[-1]
|
||||
lsubconfig = subconfig.parent.get_child(subconfig.option,
|
||||
_index,
|
||||
False,
|
||||
properties=subconfig.properties,
|
||||
suffix=suffix,
|
||||
name=subconfig.path.rsplit('.', 1)[-1],
|
||||
check_index=False,
|
||||
)
|
||||
kwargs['orig_value'] = value
|
||||
identifier = subconfig.identifiers
|
||||
if identifier is not None:
|
||||
identifier = identifier[-1]
|
||||
lsubconfig = subconfig.parent.get_child(
|
||||
subconfig.option,
|
||||
_index,
|
||||
False,
|
||||
properties=subconfig.properties,
|
||||
identifier=identifier,
|
||||
name=subconfig.path.rsplit(".", 1)[-1],
|
||||
check_index=False,
|
||||
)
|
||||
kwargs["orig_value"] = value
|
||||
|
||||
validator.execute(lsubconfig,
|
||||
**kwargs,
|
||||
)
|
||||
validator.execute(
|
||||
lsubconfig,
|
||||
**kwargs,
|
||||
)
|
||||
except ValueWarning as warn:
|
||||
warnings.warn_explicit(ValueWarning(subconfig,
|
||||
val,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(warn),
|
||||
_index,
|
||||
),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 319)
|
||||
warnings.warn_explicit(
|
||||
ValueWarning(
|
||||
subconfig,
|
||||
val,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(warn),
|
||||
_index,
|
||||
),
|
||||
ValueWarning,
|
||||
self.__class__.__name__,
|
||||
319,
|
||||
)
|
||||
|
||||
def do_validation(_value,
|
||||
_index,
|
||||
):
|
||||
def do_validation(
|
||||
_value,
|
||||
_index,
|
||||
):
|
||||
#
|
||||
if _value is None:
|
||||
return
|
||||
if isinstance(_value, list):
|
||||
raise ValueError(_('which must not be a list').format(_value,
|
||||
self.impl_get_display_name(subconfig)),
|
||||
)
|
||||
raise ValueError(_("which must not be a list"))
|
||||
if isinstance(_value, Calculation) and not subconfig:
|
||||
return
|
||||
# option validation
|
||||
if check_error:
|
||||
self.validate(_value)
|
||||
self.validate_with_option(_value,
|
||||
subconfig,
|
||||
loaded=loaded,
|
||||
)
|
||||
self.validate_with_option(
|
||||
_value,
|
||||
subconfig,
|
||||
loaded=loaded,
|
||||
)
|
||||
# second level validation
|
||||
if (check_error and not is_warnings_only) or (not check_error and is_warnings_only):
|
||||
if (check_error and not is_warnings_only) or (
|
||||
not check_error and is_warnings_only
|
||||
):
|
||||
try:
|
||||
self.second_level_validation(_value,
|
||||
is_warnings_only)
|
||||
self.second_level_validation(_value, is_warnings_only)
|
||||
except ValueError as err:
|
||||
if is_warnings_only:
|
||||
warnings.warn_explicit(ValueWarning(subconfig,
|
||||
_value,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(err),
|
||||
_index),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
warnings.warn_explicit(
|
||||
ValueWarning(
|
||||
subconfig,
|
||||
_value,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(err),
|
||||
_index,
|
||||
),
|
||||
ValueWarning,
|
||||
self.__class__.__name__,
|
||||
0,
|
||||
)
|
||||
else:
|
||||
raise err from err
|
||||
# ?
|
||||
if not loaded:
|
||||
calculation_validator(_value,
|
||||
_index,
|
||||
)
|
||||
calculation_validator(
|
||||
_value,
|
||||
_index,
|
||||
)
|
||||
|
||||
val = value
|
||||
err_index = force_index
|
||||
try:
|
||||
if not self.impl_is_multi():
|
||||
do_validation(val,
|
||||
None,
|
||||
)
|
||||
do_validation(
|
||||
val,
|
||||
None,
|
||||
)
|
||||
elif force_index is not None:
|
||||
if self.impl_is_submulti():
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_('which must be a list'))
|
||||
raise ValueError(_("which must be a list"))
|
||||
for val in value:
|
||||
do_validation(val,
|
||||
force_index,
|
||||
)
|
||||
do_validation(
|
||||
val,
|
||||
force_index,
|
||||
)
|
||||
_is_not_unique(value)
|
||||
else:
|
||||
do_validation(val,
|
||||
force_index,
|
||||
)
|
||||
do_validation(
|
||||
val,
|
||||
force_index,
|
||||
)
|
||||
elif isinstance(value, Calculation) and not subconfig:
|
||||
pass
|
||||
elif self.impl_is_submulti():
|
||||
|
@ -369,83 +420,79 @@ class Option(BaseOption):
|
|||
if isinstance(lval, Calculation):
|
||||
continue
|
||||
if not isinstance(lval, list):
|
||||
raise ValueError(_('which "{}" must be a list of list'
|
||||
'').format(lval))
|
||||
raise ValueError(
|
||||
_('which "{}" must be a list of list' "").format(lval)
|
||||
)
|
||||
for val in lval:
|
||||
do_validation(val,
|
||||
err_index)
|
||||
do_validation(val, err_index)
|
||||
_is_not_unique(lval)
|
||||
elif not isinstance(value, list):
|
||||
raise ValueError(_('which must be a list'))
|
||||
raise ValueError(_("which must be a list"))
|
||||
else:
|
||||
# FIXME suboptimal, not several time for whole=True!
|
||||
for err_index, val in enumerate(value):
|
||||
do_validation(val,
|
||||
err_index,
|
||||
)
|
||||
do_validation(
|
||||
val,
|
||||
err_index,
|
||||
)
|
||||
_is_not_unique(value)
|
||||
except ValueError as err:
|
||||
if not subconfig or \
|
||||
'demoting_error_warning' not in subconfig.config_bag.properties:
|
||||
raise ValueOptionError(subconfig,
|
||||
val,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(err),
|
||||
err_index) from err
|
||||
warnings.warn_explicit(ValueErrorWarning(subconfig,
|
||||
val,
|
||||
_(self.get_type()),
|
||||
self,
|
||||
str(err),
|
||||
err_index),
|
||||
ValueErrorWarning,
|
||||
self.__class__.__name__, 0)
|
||||
if (
|
||||
not subconfig
|
||||
or "demoting_error_warning" not in subconfig.config_bag.properties
|
||||
):
|
||||
raise ValueOptionError(
|
||||
subconfig, val, _(self.get_type()), self, str(err), err_index
|
||||
) from err
|
||||
warnings.warn_explicit(
|
||||
ValueErrorWarning(
|
||||
subconfig, val, _(self.get_type()), self, str(err), err_index
|
||||
),
|
||||
ValueErrorWarning,
|
||||
self.__class__.__name__,
|
||||
0,
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
def validate_with_option(self,
|
||||
value: Any,
|
||||
subconfig: "SubConfig",
|
||||
*,
|
||||
loaded: bool,
|
||||
) -> None:
|
||||
"""validation function with option
|
||||
"""
|
||||
def validate_with_option(
|
||||
self,
|
||||
value: Any,
|
||||
subconfig: "SubConfig",
|
||||
*,
|
||||
loaded: bool,
|
||||
) -> None:
|
||||
"""validation function with option"""
|
||||
|
||||
def second_level_validation(self,
|
||||
value: Any,
|
||||
warnings_only: bool,
|
||||
) -> None:
|
||||
"""less import validation function
|
||||
"""
|
||||
def second_level_validation(
|
||||
self,
|
||||
value: Any,
|
||||
warnings_only: bool,
|
||||
) -> None:
|
||||
"""less import validation function"""
|
||||
|
||||
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()
|
||||
if leadership is None:
|
||||
return False
|
||||
return leadership.is_leader(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()
|
||||
if leadership is None:
|
||||
return False
|
||||
return not leadership.is_leader(self)
|
||||
|
||||
def impl_get_leadership(self):
|
||||
"""get leadership
|
||||
"""
|
||||
leadership = getattr(self, '_leadership', None)
|
||||
"""get leadership"""
|
||||
leadership = getattr(self, "_leadership", None)
|
||||
if leadership is None:
|
||||
return leadership
|
||||
#pylint: disable=not-callable
|
||||
# pylint: disable=not-callable
|
||||
return leadership()
|
||||
|
||||
def validate(self, value: Any):
|
||||
"""option needs a validate function
|
||||
"""
|
||||
"""option needs a validate function"""
|
||||
raise NotImplementedError()
|
||||
|
|
|
@ -27,33 +27,34 @@ from typing import Optional, Iterator, Union, List, Dict
|
|||
from ..i18n import _
|
||||
from ..setting import ConfigBag, groups, undefined, owners, Undefined
|
||||
from .baseoption import BaseOption
|
||||
|
||||
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
|
||||
from ..error import ConfigError, ConflictError
|
||||
|
||||
|
||||
class CacheOptionDescription(BaseOption):
|
||||
"""manage cache for option description
|
||||
"""
|
||||
__slots__ = ('_cache_force_store_values',
|
||||
'_cache_dependencies_information',
|
||||
)
|
||||
"""manage cache for option description"""
|
||||
|
||||
__slots__ = (
|
||||
"_cache_force_store_values",
|
||||
"_cache_dependencies_information",
|
||||
)
|
||||
|
||||
def impl_already_build_caches(self) -> bool:
|
||||
"""is a readonly option?
|
||||
"""
|
||||
"""is a readonly option?"""
|
||||
return self.impl_is_readonly()
|
||||
|
||||
def _build_cache(self,
|
||||
display_name,
|
||||
_consistencies=None,
|
||||
_consistencies_id=0,
|
||||
currpath: List[str]=None,
|
||||
cache_option=None,
|
||||
force_store_values=None,
|
||||
dependencies_information=None,
|
||||
) -> None:
|
||||
"""validate options and set option has readonly option
|
||||
"""
|
||||
def _build_cache(
|
||||
self,
|
||||
display_name,
|
||||
_consistencies=None,
|
||||
_consistencies_id=0,
|
||||
currpath: List[str] = None,
|
||||
cache_option=None,
|
||||
force_store_values=None,
|
||||
dependencies_information=None,
|
||||
) -> None:
|
||||
"""validate options and set option has readonly option"""
|
||||
# pylint: disable=too-many-branches,too-many-arguments
|
||||
# _consistencies is None only when we start to build cache
|
||||
if _consistencies is None:
|
||||
|
@ -69,112 +70,137 @@ class CacheOptionDescription(BaseOption):
|
|||
|
||||
if self.impl_is_readonly():
|
||||
# cache already set
|
||||
raise ConfigError(_('option description seems to be part of an other '
|
||||
'config'))
|
||||
raise ConfigError(
|
||||
_("option description seems to be part of an other " "config")
|
||||
)
|
||||
for option in self.get_children():
|
||||
if __debug__:
|
||||
cache_option.append(option)
|
||||
sub_currpath = currpath + [option.impl_getname()]
|
||||
subpath = '.'.join(sub_currpath)
|
||||
subpath = ".".join(sub_currpath)
|
||||
if isinstance(option, OptionDescription):
|
||||
# pylint: disable=protected-access
|
||||
option._build_cache(display_name,
|
||||
_consistencies,
|
||||
_consistencies_id,
|
||||
sub_currpath,
|
||||
cache_option,
|
||||
force_store_values,
|
||||
dependencies_information,
|
||||
)
|
||||
option._build_cache(
|
||||
display_name,
|
||||
_consistencies,
|
||||
_consistencies_id,
|
||||
sub_currpath,
|
||||
cache_option,
|
||||
force_store_values,
|
||||
dependencies_information,
|
||||
)
|
||||
elif not option.impl_is_symlinkoption():
|
||||
informations = option.get_dependencies_information()
|
||||
if informations:
|
||||
for param in informations.pop(None):
|
||||
del param.self_option
|
||||
for information, options in option.get_dependencies_information().items():
|
||||
for (
|
||||
information,
|
||||
options,
|
||||
) in option.get_dependencies_information().items():
|
||||
if None in options:
|
||||
dependencies_information.setdefault(information, []).append(option)
|
||||
dependencies_information.setdefault(information, []).append(
|
||||
option
|
||||
)
|
||||
properties = option.impl_getproperties()
|
||||
if 'force_store_value' in properties:
|
||||
if "force_store_value" in properties:
|
||||
force_store_values.append(option)
|
||||
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:
|
||||
option._display_name_function = display_name # pylint: disable=protected-access
|
||||
option._display_name_function = (
|
||||
display_name # pylint: disable=protected-access
|
||||
)
|
||||
option._path = subpath # pylint: disable=protected-access
|
||||
option._set_readonly() # pylint: disable=protected-access
|
||||
if init:
|
||||
self._cache_force_store_values = force_store_values # pylint: disable=attribute-defined-outside-init
|
||||
self._cache_force_store_values = (
|
||||
force_store_values # pylint: disable=attribute-defined-outside-init
|
||||
)
|
||||
self._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init
|
||||
self._path = None # pylint: disable=attribute-defined-outside-init,no-member
|
||||
self._path = (
|
||||
None # pylint: disable=attribute-defined-outside-init,no-member
|
||||
)
|
||||
self._set_readonly()
|
||||
|
||||
def impl_build_force_store_values(self,
|
||||
config_bag: ConfigBag,
|
||||
) -> None:
|
||||
"""set value to force_store_values option
|
||||
"""
|
||||
def impl_build_force_store_values(
|
||||
self,
|
||||
config_bag: ConfigBag,
|
||||
) -> None:
|
||||
"""set value to force_store_values option"""
|
||||
# pylint: disable=too-many-branches
|
||||
context = config_bag.context
|
||||
if 'force_store_value' not in config_bag.properties:
|
||||
if "force_store_value" not in config_bag.properties:
|
||||
return
|
||||
|
||||
values = config_bag.context.get_values()
|
||||
for option in self._cache_force_store_values:
|
||||
if option.issubdyn():
|
||||
paths = option.impl_getpath().split('.')
|
||||
paths = option.impl_getpath().split(".")
|
||||
parents = [config_bag.context.get_root(config_bag)]
|
||||
for name in paths:
|
||||
new_parents = []
|
||||
for parent in parents:
|
||||
doption = parent.option.get_child(name,
|
||||
config_bag,
|
||||
parent,
|
||||
allow_dynoption=True,
|
||||
)
|
||||
doption = parent.option.get_child(
|
||||
name,
|
||||
config_bag,
|
||||
parent,
|
||||
allow_dynoption=True,
|
||||
)
|
||||
if doption.impl_is_dynoptiondescription():
|
||||
new_parents.extend(parent.dyn_to_subconfig(doption,
|
||||
True,
|
||||
)
|
||||
)
|
||||
new_parents.extend(
|
||||
parent.dyn_to_subconfig(
|
||||
doption,
|
||||
True,
|
||||
)
|
||||
)
|
||||
else:
|
||||
new_parents.append(parent.get_child(doption,
|
||||
None,
|
||||
True,
|
||||
name=name,
|
||||
))
|
||||
new_parents.append(
|
||||
parent.get_child(
|
||||
doption,
|
||||
None,
|
||||
True,
|
||||
name=name,
|
||||
)
|
||||
)
|
||||
parents = new_parents
|
||||
subconfigs = new_parents
|
||||
else:
|
||||
subconfigs = [context.get_sub_config(config_bag,
|
||||
option.impl_getpath(),
|
||||
None,
|
||||
properties=None,
|
||||
validate_properties=False,
|
||||
)]
|
||||
subconfigs = [
|
||||
context.get_sub_config(
|
||||
config_bag,
|
||||
option.impl_getpath(),
|
||||
None,
|
||||
properties=None,
|
||||
validate_properties=False,
|
||||
)
|
||||
]
|
||||
|
||||
if option.impl_is_follower():
|
||||
for follower_subconfig in subconfigs:
|
||||
parent = follower_subconfig.parent
|
||||
follower_len = parent.get_length_leadership()
|
||||
for index in range(follower_len):
|
||||
if values.hasvalue(follower_subconfig.path,
|
||||
index=index,
|
||||
):
|
||||
if values.hasvalue(
|
||||
follower_subconfig.path,
|
||||
index=index,
|
||||
):
|
||||
continue
|
||||
idx_follower_subconfig = parent.get_child(follower_subconfig.option,
|
||||
index,
|
||||
validate_properties=False,
|
||||
)
|
||||
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,
|
||||
)
|
||||
values.set_storage_value(
|
||||
follower_subconfig.path,
|
||||
index,
|
||||
value,
|
||||
owners.forced,
|
||||
)
|
||||
else:
|
||||
for subconfig in subconfigs:
|
||||
subconfig.properties = frozenset()
|
||||
|
@ -183,106 +209,108 @@ class CacheOptionDescription(BaseOption):
|
|||
continue
|
||||
if values.hasvalue(subconfig.path):
|
||||
continue
|
||||
values.set_storage_value(subconfig.path,
|
||||
None,
|
||||
value,
|
||||
owners.forced,
|
||||
)
|
||||
values.set_storage_value(
|
||||
subconfig.path,
|
||||
None,
|
||||
value,
|
||||
owners.forced,
|
||||
)
|
||||
|
||||
|
||||
class OptionDescriptionWalk(CacheOptionDescription):
|
||||
"""get child of option description
|
||||
"""
|
||||
__slots__ = ('_children',)
|
||||
"""get child of option description"""
|
||||
|
||||
def get_path(self,
|
||||
config_bag,
|
||||
):
|
||||
if config_bag is undefined or \
|
||||
config_bag.context.get_description() == self:
|
||||
return ''
|
||||
__slots__ = ("_children",)
|
||||
|
||||
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_child_not_dynamic(self,
|
||||
name,
|
||||
allow_dynoption,
|
||||
):
|
||||
def get_child_not_dynamic(
|
||||
self,
|
||||
name,
|
||||
allow_dynoption,
|
||||
):
|
||||
if name in self._children[0]: # pylint: disable=no-member
|
||||
option = self._children[1][self._children[0].index(name)] # pylint: disable=no-member
|
||||
option = self._children[1][
|
||||
self._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)"
|
||||
))
|
||||
raise AttributeError(
|
||||
_(
|
||||
'unknown option "{0}" in root optiondescription (it\'s a dynamic option)'
|
||||
).format(name)
|
||||
)
|
||||
return option
|
||||
|
||||
def get_child(self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
parent: 'SubConfig',
|
||||
*,
|
||||
with_suffix: bool=False,
|
||||
allow_dynoption: bool=False,
|
||||
) -> Union[BaseOption]:
|
||||
"""get a child
|
||||
"""
|
||||
def get_child(
|
||||
self,
|
||||
name: str,
|
||||
config_bag: ConfigBag,
|
||||
parent: "SubConfig",
|
||||
*,
|
||||
with_identifier: bool = False,
|
||||
allow_dynoption: bool = False,
|
||||
) -> Union[BaseOption]:
|
||||
"""get a child"""
|
||||
# if not dyn
|
||||
option = self.get_child_not_dynamic(name,
|
||||
allow_dynoption,
|
||||
)
|
||||
option = self.get_child_not_dynamic(
|
||||
name,
|
||||
allow_dynoption,
|
||||
)
|
||||
if option:
|
||||
return option
|
||||
# if dyn
|
||||
for child in self._children[1]: # pylint: disable=no-member
|
||||
if not child.impl_is_dynoptiondescription():
|
||||
continue
|
||||
for suffix in child.get_suffixes(parent):
|
||||
if name != child.impl_getname(suffix):
|
||||
for identifier in child.get_identifiers(parent):
|
||||
if name != child.impl_getname(identifier):
|
||||
continue
|
||||
if not with_suffix:
|
||||
if not with_identifier:
|
||||
return child
|
||||
return suffix, child
|
||||
return identifier, child
|
||||
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
|
||||
raise AttributeError(_(f'unknown option "{name}" '
|
||||
'in root optiondescription'
|
||||
))
|
||||
raise AttributeError(_(f'unknown option "{name}" '
|
||||
f'in optiondescription "{self.impl_get_display_name(parent)}"'
|
||||
))
|
||||
raise AttributeError(
|
||||
_('unknown option "{0}" in root optiondescription').format(name)
|
||||
)
|
||||
raise AttributeError(
|
||||
_('unknown option "{0}" in optiondescription {1}').format(
|
||||
name, self.impl_get_display_name(parent, with_quote=True)
|
||||
)
|
||||
)
|
||||
|
||||
def get_children(self) -> List[BaseOption]:
|
||||
"""get children
|
||||
"""
|
||||
"""get children"""
|
||||
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(self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption=None,
|
||||
*,
|
||||
option_suffixes: Optional[list]=None
|
||||
) -> Iterator[Union[BaseOption]]:
|
||||
"""get children recursively
|
||||
"""
|
||||
def get_children_recursively(
|
||||
self,
|
||||
bytype: Optional[BaseOption],
|
||||
byname: Optional[str],
|
||||
config_bag: ConfigBag,
|
||||
self_opt: BaseOption = None,
|
||||
*,
|
||||
option_identifiers: Optional[list] = None,
|
||||
) -> Iterator[Union[BaseOption]]:
|
||||
"""get children recursively"""
|
||||
if self_opt is None:
|
||||
self_opt = self
|
||||
for option in self_opt.get_children():
|
||||
if option.impl_is_optiondescription():
|
||||
for subopt in option.get_children_recursively(bytype,
|
||||
byname,
|
||||
config_bag,
|
||||
):
|
||||
for subopt in option.get_children_recursively(
|
||||
bytype,
|
||||
byname,
|
||||
config_bag,
|
||||
):
|
||||
yield subopt
|
||||
elif (byname is None or option.impl_getname() == byname) and \
|
||||
(bytype is None or isinstance(option, bytype)):
|
||||
elif (byname is None or option.impl_getname() == byname) and (
|
||||
bytype is None or isinstance(option, bytype)
|
||||
):
|
||||
yield option
|
||||
|
||||
|
||||
|
@ -290,27 +318,32 @@ class OptionDescription(OptionDescriptionWalk):
|
|||
"""Config's schema (organisation, group) and container of Options
|
||||
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
||||
"""
|
||||
__slots__ = ('_group_type',)
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
children: List[BaseOption],
|
||||
*,
|
||||
properties=None,
|
||||
informations: Optional[Dict]=None,
|
||||
) -> None:
|
||||
__slots__ = ("_group_type",)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
children: List[BaseOption],
|
||||
*,
|
||||
properties=None,
|
||||
informations: Optional[Dict] = None,
|
||||
group_type: Optional[groups.GroupType] = groups.default,
|
||||
) -> None:
|
||||
"""
|
||||
:param children: a list of options (including optiondescriptions)
|
||||
|
||||
"""
|
||||
assert isinstance(children, list), _('children in optiondescription "{}" '
|
||||
'must be a list').format(name)
|
||||
super().__init__(name,
|
||||
doc,
|
||||
informations,
|
||||
properties=properties,
|
||||
)
|
||||
assert isinstance(children, list), _(
|
||||
'children in optiondescription "{}" ' "must be a list"
|
||||
).format(name)
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
informations,
|
||||
properties=properties,
|
||||
)
|
||||
child_names = []
|
||||
if __debug__:
|
||||
dynopt_names = []
|
||||
|
@ -329,83 +362,72 @@ class OptionDescription(OptionDescriptionWalk):
|
|||
old = None
|
||||
for child in child_names:
|
||||
if child == old:
|
||||
raise ConflictError(_('duplicate option name: '
|
||||
'"{0}"').format(child))
|
||||
raise ConflictError(
|
||||
_("duplicate option name: " '"{0}"').format(child)
|
||||
)
|
||||
if dynopt_names:
|
||||
for dynopt in dynopt_names:
|
||||
if child != dynopt and child.startswith(dynopt):
|
||||
raise ConflictError(_(f'the option\'s name "{child}" start as '
|
||||
f'the dynoptiondescription\'s name "{dynopt}"'))
|
||||
raise ConflictError(
|
||||
_(
|
||||
'the option\'s name "{0}" start as the dynoptiondescription\'s name "{1}"'
|
||||
).format(child, dynopt)
|
||||
)
|
||||
old = child
|
||||
self._children = children_
|
||||
# the group_type is useful for filtering OptionDescriptions in a config
|
||||
self._group_type = groups.default
|
||||
self._group_type = None
|
||||
self.impl_set_group_type(group_type)
|
||||
|
||||
def _setsubdyn(self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
def _setsubdyn(
|
||||
self,
|
||||
subdyn,
|
||||
) -> None:
|
||||
for child in self._children[1]:
|
||||
child._setsubdyn(subdyn)
|
||||
super()._setsubdyn(subdyn)
|
||||
|
||||
def impl_is_optiondescription(self) -> bool:
|
||||
"""the option is an option description
|
||||
"""
|
||||
"""the option is an option description"""
|
||||
return True
|
||||
|
||||
def impl_is_dynoptiondescription(self) -> bool:
|
||||
"""the option is not dynamic
|
||||
"""
|
||||
"""the option is not dynamic"""
|
||||
return False
|
||||
|
||||
def impl_is_leadership(self) -> bool:
|
||||
"""the option is not a leadership
|
||||
"""
|
||||
"""the option is not a leadership"""
|
||||
return False
|
||||
|
||||
# ____________________________________________________________
|
||||
def impl_set_group_type(self,
|
||||
group_type: groups.GroupType,
|
||||
) -> None:
|
||||
def impl_set_group_type(
|
||||
self,
|
||||
group_type: groups.GroupType,
|
||||
) -> None:
|
||||
"""sets a given group object to an OptionDescription
|
||||
|
||||
:param group_type: an instance of `GroupType` or `LeadershipGroupType`
|
||||
that lives in `setting.groups`
|
||||
"""
|
||||
if __debug__:
|
||||
if self._group_type != groups.default:
|
||||
raise ValueError(_('cannot change group_type if already set '
|
||||
'(old {0}, new {1})').format(self._group_type,
|
||||
group_type))
|
||||
if self._group_type is not None and self._group_type != groups.default:
|
||||
raise ValueError(
|
||||
_(
|
||||
"cannot change group_type if already set " "(old {0}, new {1})"
|
||||
).format(self._group_type, group_type)
|
||||
)
|
||||
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):
|
||||
raise ConfigError('please use Leadership object instead of OptionDescription')
|
||||
raise ConfigError(
|
||||
"please use Leadership object instead of OptionDescription"
|
||||
)
|
||||
self._group_type = group_type
|
||||
|
||||
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
|
||||
#
|
||||
# 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:
|
||||
"""option is not a dyn symlink option
|
||||
"""
|
||||
"""option is not a dyn symlink option"""
|
||||
return False
|
||||
|
|
|
@ -22,11 +22,39 @@
|
|||
"""
|
||||
|
||||
from ..i18n import _
|
||||
from ..error import display_list
|
||||
from .stroption import StrOption
|
||||
|
||||
|
||||
class PasswordOption(StrOption):
|
||||
"""represents the choice of a password
|
||||
"""
|
||||
"""represents the choice of a password"""
|
||||
|
||||
__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)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -33,27 +33,25 @@ class PermissionsOption(IntOption):
|
|||
If a fourth digit is present to the setuid bit, the setgid bit and the sticky bit attributes.
|
||||
This option is an integer value.
|
||||
"""
|
||||
|
||||
__slots__ = tuple()
|
||||
perm_re = re.compile(r"^[0-7]{3,4}$")
|
||||
_type = 'unix file permissions'
|
||||
_type = "unix file permissions"
|
||||
|
||||
def __init__(self,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
#do not display intoption attributs
|
||||
super().__init__(*args,
|
||||
**kwargs)
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
# do not display intoption attributs
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
def validate(self, value: str) -> None:
|
||||
super().validate(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
|
||||
str_value = str(value)
|
||||
if len(str_value) == 4:
|
||||
|
@ -62,12 +60,12 @@ class PermissionsOption(IntOption):
|
|||
new_digit = int(digit)
|
||||
if old_digit < new_digit:
|
||||
if idx == 1:
|
||||
old = _('user')
|
||||
new = _('group')
|
||||
old = _("user")
|
||||
new = _("group")
|
||||
else:
|
||||
old = _('group')
|
||||
new = _('other')
|
||||
raise ValueError(_(f'{new} has more right than {old}'))
|
||||
old = _("group")
|
||||
new = _("other")
|
||||
raise ValueError(_("{0} has more right than {1}").format(new, old))
|
||||
old_digit = new_digit
|
||||
if str_value == '777':
|
||||
raise ValueError(_('too weak'))
|
||||
if str_value == "777":
|
||||
raise ValueError(_("too weak"))
|
||||
|
|
|
@ -36,62 +36,64 @@ class PortOption(StrOption):
|
|||
Port number 0 is reserved and can't be used.
|
||||
see: http://en.wikipedia.org/wiki/Port_numbers
|
||||
"""
|
||||
|
||||
__slots__ = tuple()
|
||||
port_re = re.compile(r"^[0-9]*$")
|
||||
_type = 'port'
|
||||
_type = "port"
|
||||
|
||||
def __init__(self,
|
||||
*args,
|
||||
allow_range: bool=False,
|
||||
allow_zero: bool=False,
|
||||
allow_wellknown: bool=True,
|
||||
allow_registred: bool=True,
|
||||
allow_protocol: bool=False,
|
||||
allow_private: bool=False,
|
||||
**kwargs) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
*args,
|
||||
allow_range: bool = False,
|
||||
allow_zero: bool = False,
|
||||
allow_wellknown: bool = True,
|
||||
allow_registred: bool = True,
|
||||
allow_protocol: bool = False,
|
||||
allow_private: bool = False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
|
||||
extra = {'_allow_range': allow_range,
|
||||
'_allow_protocol': allow_protocol,
|
||||
'_min_value': None,
|
||||
'_max_value': None,
|
||||
}
|
||||
extra = {
|
||||
"_allow_range": allow_range,
|
||||
"_allow_protocol": allow_protocol,
|
||||
"_min_value": None,
|
||||
"_max_value": None,
|
||||
}
|
||||
ports_min = [0, 1, 1024, 49152]
|
||||
ports_max = [0, 1023, 49151, 65535]
|
||||
is_finally = False
|
||||
for index, allowed in enumerate([allow_zero,
|
||||
allow_wellknown,
|
||||
allow_registred,
|
||||
allow_private]):
|
||||
if extra['_min_value'] is None:
|
||||
for index, allowed in enumerate(
|
||||
[allow_zero, allow_wellknown, allow_registred, allow_private]
|
||||
):
|
||||
if extra["_min_value"] is None:
|
||||
if allowed:
|
||||
extra['_min_value'] = ports_min[index]
|
||||
extra["_min_value"] = ports_min[index]
|
||||
elif not allowed:
|
||||
is_finally = True
|
||||
elif allowed and is_finally:
|
||||
raise ValueError(_('inconsistency in allowed range'))
|
||||
raise ValueError(_("inconsistency in allowed range"))
|
||||
if allowed:
|
||||
extra['_max_value'] = ports_max[index]
|
||||
extra["_max_value"] = ports_max[index]
|
||||
|
||||
if extra['_max_value'] is None:
|
||||
raise ValueError(_('max value is empty'))
|
||||
if extra["_max_value"] is None:
|
||||
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)
|
||||
if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or
|
||||
value.startswith('udp:')):
|
||||
if self.impl_get_extra("_allow_protocol") and (
|
||||
value.startswith("tcp:") or value.startswith("udp:")
|
||||
):
|
||||
value = [value[4:]]
|
||||
elif self.impl_get_extra('_allow_range') and ":" in str(value):
|
||||
value = value.split(':')
|
||||
elif self.impl_get_extra("_allow_range") and ":" in str(value):
|
||||
value = value.split(":")
|
||||
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]:
|
||||
raise ValueError(_('first port in range must be'
|
||||
' smaller than the second one'))
|
||||
raise ValueError(
|
||||
_("first port in range must be" " smaller than the second one")
|
||||
)
|
||||
else:
|
||||
value = [value]
|
||||
|
||||
|
@ -99,22 +101,29 @@ class PortOption(StrOption):
|
|||
if not self.port_re.search(val):
|
||||
raise ValueError()
|
||||
|
||||
def second_level_validation(self,
|
||||
value: str,
|
||||
warnings_only: bool) -> None:
|
||||
if self.impl_get_extra('_allow_protocol') and (value.startswith('tcp:') or
|
||||
value.startswith('udp:')):
|
||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
||||
if self.impl_get_extra("_allow_protocol") and (
|
||||
value.startswith("tcp:") or value.startswith("udp:")
|
||||
):
|
||||
value = [value[4:]]
|
||||
elif ':' in value:
|
||||
value = value.split(':')
|
||||
elif ":" in value:
|
||||
value = value.split(":")
|
||||
else:
|
||||
value = [value]
|
||||
for val in value:
|
||||
val = int(val)
|
||||
if not self.impl_get_extra('_min_value') <= val <= self.impl_get_extra('_max_value'):
|
||||
if (
|
||||
not self.impl_get_extra("_min_value")
|
||||
<= val
|
||||
<= self.impl_get_extra("_max_value")
|
||||
):
|
||||
if warnings_only:
|
||||
msg = 'should be between {0} and {1}'
|
||||
msg = _("should be between {0} and {1}")
|
||||
else:
|
||||
msg = 'must be between {0} and {1}'
|
||||
raise ValueError(_(msg).format(self.impl_get_extra('_min_value'),
|
||||
self.impl_get_extra('_max_value')))
|
||||
msg = _("must be between {0} and {1}")
|
||||
raise ValueError(
|
||||
msg.format(
|
||||
self.impl_get_extra("_min_value"),
|
||||
self.impl_get_extra("_max_value"),
|
||||
)
|
||||
)
|
||||
|
|
|
@ -27,31 +27,31 @@ from .option import Option
|
|||
|
||||
|
||||
class StrOption(Option):
|
||||
"""represents a string
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = 'string'
|
||||
"""represents a string"""
|
||||
|
||||
def validate(self,
|
||||
value: str,
|
||||
) -> None:
|
||||
"""validation
|
||||
"""
|
||||
__slots__ = tuple()
|
||||
_type = "string"
|
||||
|
||||
def validate(
|
||||
self,
|
||||
value: str,
|
||||
) -> None:
|
||||
"""validation"""
|
||||
if not isinstance(value, str):
|
||||
raise ValueError()
|
||||
|
||||
|
||||
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()
|
||||
|
||||
def validate(self,
|
||||
value: Any,
|
||||
) -> None:
|
||||
def validate(
|
||||
self,
|
||||
value: Any,
|
||||
) -> None:
|
||||
# pylint: disable=no-member
|
||||
"""validation
|
||||
"""
|
||||
"""validation"""
|
||||
super().validate(value)
|
||||
match = self._regexp.search(value)
|
||||
if not match:
|
||||
|
|
|
@ -27,53 +27,66 @@ from ..i18n import _
|
|||
|
||||
|
||||
class SymLinkOption(BaseOption):
|
||||
"""SymLinkOption link to an other option
|
||||
"""
|
||||
__slots__ = ('_opt',)
|
||||
"""SymLinkOption link to an other option"""
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
opt: BaseOption,
|
||||
) -> None:
|
||||
__slots__ = (
|
||||
"_opt",
|
||||
"_leadership",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
opt: BaseOption,
|
||||
) -> None:
|
||||
# pylint: disable=super-init-not-called
|
||||
if not valid_name(name):
|
||||
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||
if not isinstance(opt, BaseOption) or \
|
||||
opt.impl_is_optiondescription() or \
|
||||
opt.impl_is_symlinkoption():
|
||||
raise ValueError(_(f'malformed symlink second parameters must be an option for "{name}", not {opt}'))
|
||||
if (
|
||||
not isinstance(opt, BaseOption)
|
||||
or opt.impl_is_optiondescription()
|
||||
or opt.impl_is_symlinkoption()
|
||||
):
|
||||
raise ValueError(
|
||||
_(
|
||||
'malformed symlink second parameters must be an option for "{0}", not {1}'
|
||||
).format(name, opt)
|
||||
)
|
||||
self._name = name
|
||||
self._opt = opt
|
||||
self._leadership = None
|
||||
opt._add_dependency(self)
|
||||
|
||||
def __getattr__(self,
|
||||
name: str,
|
||||
) -> Any:
|
||||
if name == '_subdyns':
|
||||
def __getattr__(
|
||||
self,
|
||||
name: str,
|
||||
) -> Any:
|
||||
if name == "_subdyns":
|
||||
return None
|
||||
if name == '_path':
|
||||
if name == "_path":
|
||||
raise AttributeError()
|
||||
return getattr(self._opt, name)
|
||||
|
||||
def impl_is_symlinkoption(self) -> bool:
|
||||
"""it's a symlinkoption
|
||||
"""
|
||||
"""it's a symlinkoption"""
|
||||
return True
|
||||
|
||||
def impl_is_leader(self) -> bool:
|
||||
return False
|
||||
|
||||
def impl_is_follower(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:
|
||||
"""get to linked option
|
||||
"""
|
||||
"""get to linked option"""
|
||||
return self._opt
|
||||
|
||||
def impl_is_multi(self) -> bool:
|
||||
"""is it a multi?
|
||||
"""
|
||||
"""is it a multi?"""
|
||||
if self._opt.impl_is_multi():
|
||||
return True
|
||||
if self._opt.issubdyn() or self.issubdyn():
|
||||
|
@ -83,6 +96,5 @@ class SymLinkOption(BaseOption):
|
|||
return False
|
||||
|
||||
def impl_is_submulti(self) -> bool:
|
||||
"""is it a submulti?
|
||||
"""
|
||||
"""is it a submulti?"""
|
||||
return self._opt.impl_is_submulti()
|
||||
|
|
|
@ -32,93 +32,97 @@ from .portoption import PortOption
|
|||
|
||||
|
||||
class URLOption(StrOption):
|
||||
"""URLOption to check url value
|
||||
"""
|
||||
"""URLOption to check url value"""
|
||||
|
||||
__slots__ = tuple()
|
||||
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||
_type = 'URL'
|
||||
_type = "URL"
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
doc: str,
|
||||
*args,
|
||||
allow_ip: bool=False,
|
||||
type: str='domainname',
|
||||
allow_without_dot=False,
|
||||
allow_range: bool=False,
|
||||
allow_zero: bool=False,
|
||||
allow_wellknown: bool=True,
|
||||
allow_registred: bool=True,
|
||||
allow_private: bool=False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
doc: str,
|
||||
*args,
|
||||
allow_ip: bool = False,
|
||||
type: str = "domainname",
|
||||
allow_without_dot=False,
|
||||
allow_range: bool = False,
|
||||
allow_zero: bool = False,
|
||||
allow_wellknown: bool = True,
|
||||
allow_registred: bool = True,
|
||||
allow_private: bool = False,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
|
||||
extra = {'_domainname': DomainnameOption(name,
|
||||
doc,
|
||||
allow_ip=allow_ip,
|
||||
type=type,
|
||||
allow_without_dot=allow_without_dot),
|
||||
'_port': PortOption(name,
|
||||
doc,
|
||||
allow_range=allow_range,
|
||||
allow_zero=allow_zero,
|
||||
allow_wellknown=allow_wellknown,
|
||||
allow_registred=allow_registred,
|
||||
allow_private=allow_private)}
|
||||
super().__init__(name,
|
||||
doc,
|
||||
extra=extra,
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
extra = {
|
||||
"_domainname": DomainnameOption(
|
||||
name,
|
||||
doc,
|
||||
allow_ip=allow_ip,
|
||||
type=type,
|
||||
allow_without_dot=allow_without_dot,
|
||||
),
|
||||
"_port": PortOption(
|
||||
name,
|
||||
doc,
|
||||
allow_range=allow_range,
|
||||
allow_zero=allow_zero,
|
||||
allow_wellknown=allow_wellknown,
|
||||
allow_registred=allow_registred,
|
||||
allow_private=allow_private,
|
||||
),
|
||||
}
|
||||
super().__init__(
|
||||
name,
|
||||
doc,
|
||||
extra=extra,
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def _get_domain_port_files(self,
|
||||
value: str) -> (str, str):
|
||||
if value.startswith('http://'):
|
||||
type_ = 'http'
|
||||
def _get_domain_port_files(self, value: str) -> (str, str):
|
||||
if value.startswith("http://"):
|
||||
type_ = "http"
|
||||
value = value[7:]
|
||||
elif value.startswith('https://'):
|
||||
type_ = 'https'
|
||||
elif value.startswith("https://"):
|
||||
type_ = "https"
|
||||
value = value[8:]
|
||||
else:
|
||||
raise ValueError(_('must start with http:// or '
|
||||
'https://'))
|
||||
raise ValueError(_("must start with http:// or " "https://"))
|
||||
# get domain/files
|
||||
splitted = value.split('/', 1)
|
||||
splitted = value.split("/", 1)
|
||||
if len(splitted) == 1:
|
||||
domain = value
|
||||
files = None
|
||||
else:
|
||||
domain, files = splitted
|
||||
# if port in domain
|
||||
splitted = domain.split(':', 1)
|
||||
splitted = domain.split(":", 1)
|
||||
if len(splitted) == 1:
|
||||
domain = splitted[0]
|
||||
port = {'http': '80',
|
||||
'https': '443'}[type_]
|
||||
port = {"http": "80", "https": "443"}[type_]
|
||||
else:
|
||||
domain, port = splitted
|
||||
return domain, port, files
|
||||
|
||||
def validate(self,
|
||||
value: str) -> None:
|
||||
def validate(self, value: str) -> None:
|
||||
super().validate(value)
|
||||
domain, port, files = self._get_domain_port_files(value)
|
||||
# validate port
|
||||
portoption = self.impl_get_extra('_port')
|
||||
portoption = self.impl_get_extra("_port")
|
||||
portoption.validate(port)
|
||||
# validate domainname
|
||||
domainnameoption = self.impl_get_extra('_domainname')
|
||||
domainnameoption = self.impl_get_extra("_domainname")
|
||||
domainnameoption.validate(domain)
|
||||
# validate files
|
||||
if files is not None and files != '' and not self.path_re.search(files):
|
||||
raise ValueError(_('must ends with a valid resource name'))
|
||||
if files is not None and files != "" and not self.path_re.search(files):
|
||||
raise ValueError(_("must ends with a valid resource name"))
|
||||
|
||||
def second_level_validation(self, value, warnings_only):
|
||||
domain, port, _ = self._get_domain_port_files(value)
|
||||
# validate port
|
||||
portoption = self.impl_get_extra('_port')
|
||||
portoption = self.impl_get_extra("_port")
|
||||
portoption.second_level_validation(port, warnings_only)
|
||||
# validate domainname
|
||||
domainnameoption = self.impl_get_extra('_domainname')
|
||||
domainnameoption = self.impl_get_extra("_domainname")
|
||||
domainnameoption.second_level_validation(domain, warnings_only)
|
||||
|
|
|
@ -27,16 +27,16 @@ from .stroption import RegexpOption
|
|||
|
||||
|
||||
class UsernameOption(RegexpOption):
|
||||
"""UsernameOption to check unix username value
|
||||
"""
|
||||
"""UsernameOption to check unix username value"""
|
||||
|
||||
__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}$")
|
||||
_type = 'unix username'
|
||||
_type = "unix username"
|
||||
|
||||
|
||||
class GroupnameOption(UsernameOption):
|
||||
"""GroupnameOption to check unix group value
|
||||
"""
|
||||
"""GroupnameOption to check unix group value"""
|
||||
|
||||
__slots__ = tuple()
|
||||
_type = 'unix groupname'
|
||||
_type = "unix groupname"
|
||||
|
|
File diff suppressed because it is too large
Load diff
1051
tiramisu/todict.py
1051
tiramisu/todict.py
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