RequirementRecursiveError => RequirementError
Properties in "apply_requires" are now transitive (but only if tested property is in properties list) New requirement option (a boolean), don't touch properties if PropertyError in "apply_requires"
This commit is contained in:
parent
c6c422f472
commit
2751a2694a
4 changed files with 122 additions and 10 deletions
101
test/test_requires.py
Normal file
101
test/test_requires.py
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
# coding: utf-8
|
||||||
|
import autopath
|
||||||
|
from tiramisu import setting
|
||||||
|
setting.expires_time = 1
|
||||||
|
from tiramisu.option import IPOption, OptionDescription, BoolOption
|
||||||
|
from tiramisu.config import Config
|
||||||
|
from tiramisu.error import PropertiesOptionError, RequirementError
|
||||||
|
from py.test import raises
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
b = IPOption('ip_address_service', '',
|
||||||
|
requires=[(a, False, 'disabled')])
|
||||||
|
od = OptionDescription('service', '', [a, b])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.ip_address_service
|
||||||
|
c.activate_service = False
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError, err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['disabled']
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_transitif():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
b = BoolOption('activate_service_web', '', True,
|
||||||
|
requires=[(a, False, 'disabled')])
|
||||||
|
d = IPOption('ip_address_service_web', '',
|
||||||
|
requires=[(b, False, 'disabled')])
|
||||||
|
od = OptionDescription('service', '', [a, b, d])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.activate_service
|
||||||
|
c.activate_service_web
|
||||||
|
c.ip_address_service_web
|
||||||
|
c.activate_service = False
|
||||||
|
#
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.activate_service_web
|
||||||
|
except PropertiesOptionError, err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['disabled']
|
||||||
|
#
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service_web
|
||||||
|
except PropertiesOptionError, err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['disabled']
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_transitif_hidden_disabled():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
b = BoolOption('activate_service_web', '', True,
|
||||||
|
requires=[(a, False, 'hidden')])
|
||||||
|
d = IPOption('ip_address_service_web', '',
|
||||||
|
requires=[(b, False, 'disabled')])
|
||||||
|
od = OptionDescription('service', '', [a, b, d])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.activate_service
|
||||||
|
c.activate_service_web
|
||||||
|
c.ip_address_service_web
|
||||||
|
c.activate_service = False
|
||||||
|
#
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.activate_service_web
|
||||||
|
except PropertiesOptionError, err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['hidden']
|
||||||
|
raises(RequirementError, 'c.ip_address_service_web')
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_not_transitif():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
b = BoolOption('activate_service_web', '', True,
|
||||||
|
requires=[(a, False, 'disabled')])
|
||||||
|
d = IPOption('ip_address_service_web', '',
|
||||||
|
requires=[(b, False, 'disabled', False, False)])
|
||||||
|
od = OptionDescription('service', '', [a, b, d])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.activate_service
|
||||||
|
c.activate_service_web
|
||||||
|
c.ip_address_service_web
|
||||||
|
c.activate_service = False
|
||||||
|
#
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.activate_service_web
|
||||||
|
except PropertiesOptionError, err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['disabled']
|
||||||
|
#
|
||||||
|
c.ip_address_service_web
|
|
@ -44,8 +44,10 @@ class ConflictError(StandardError):
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# miscellaneous exceptions
|
# miscellaneous exceptions
|
||||||
class RequirementRecursionError(StandardError):
|
class RequirementError(StandardError):
|
||||||
"a recursive loop occurs in the requirements tree"
|
"""a recursive loop occurs in the requirements tree
|
||||||
|
requires
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -820,7 +820,7 @@ def validate_requires_arg(requires, name):
|
||||||
if len(req) == 3:
|
if len(req) == 3:
|
||||||
action = req[2]
|
action = req[2]
|
||||||
inverse = False
|
inverse = False
|
||||||
elif len(req) == 4:
|
elif len(req) in [4, 5]:
|
||||||
action = req[2]
|
action = req[2]
|
||||||
inverse = req[3]
|
inverse = req[3]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from time import time
|
from time import time
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from tiramisu.error import RequirementRecursionError, PropertiesOptionError
|
from tiramisu.error import RequirementError, PropertiesOptionError
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ class Setting(object):
|
||||||
else:
|
else:
|
||||||
raise_text = "trying to access to an option named: {0} with properties {1}"
|
raise_text = "trying to access to an option named: {0} with properties {1}"
|
||||||
raise PropertiesOptionError(_(raise_text).format(opt_or_descr._name,
|
raise PropertiesOptionError(_(raise_text).format(opt_or_descr._name,
|
||||||
str(properties)),
|
str(list(properties))),
|
||||||
list(properties))
|
list(properties))
|
||||||
|
|
||||||
def _get_permissive(self, opt=None):
|
def _get_permissive(self, opt=None):
|
||||||
|
@ -355,19 +355,28 @@ def apply_requires(opt, config):
|
||||||
if len(require) == 3:
|
if len(require) == 3:
|
||||||
option, expected, action = require
|
option, expected, action = require
|
||||||
inverse = False
|
inverse = False
|
||||||
|
transitive = True
|
||||||
elif len(require) == 4:
|
elif len(require) == 4:
|
||||||
option, expected, action, inverse = require
|
option, expected, action, inverse = require
|
||||||
|
transitive = True
|
||||||
|
elif len(require) == 5:
|
||||||
|
option, expected, action, inverse, transitive = require
|
||||||
path = descr.impl_get_path_by_opt(option)
|
path = descr.impl_get_path_by_opt(option)
|
||||||
if path == optpath or path.startswith(optpath + '.'):
|
if path == optpath or path.startswith(optpath + '.'):
|
||||||
raise RequirementRecursionError(_("malformed requirements "
|
raise RequirementError(_("malformed requirements "
|
||||||
"imbrication detected for option: '{0}' "
|
"imbrication detected for option: '{0}' "
|
||||||
"with requirement on: '{1}'").format(optpath, path))
|
"with requirement on: '{1}'").format(optpath, path))
|
||||||
try:
|
try:
|
||||||
value = config.cfgimpl_get_context()._getattr(path, force_permissive=True)
|
value = config.cfgimpl_get_context()._getattr(path, force_permissive=True)
|
||||||
except PropertiesOptionError, err:
|
except PropertiesOptionError, err:
|
||||||
|
if not transitive:
|
||||||
|
continue
|
||||||
properties = err.proptype
|
properties = err.proptype
|
||||||
raise PropertiesOptionError(_("option '{0}' has requirement's property error: "
|
if action not in err.proptype:
|
||||||
"{1} {2}").format(opt._name, path, properties), properties)
|
raise RequirementError(_("option '{0}' has requirement's property error: "
|
||||||
|
"{1} {2}").format(opt._name, path, properties), properties)
|
||||||
|
#transitive action, force expected
|
||||||
|
value = expected
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise AttributeError(_("required option not found: "
|
raise AttributeError(_("required option not found: "
|
||||||
"{0}").format(path))
|
"{0}").format(path))
|
||||||
|
|
Loading…
Reference in a new issue