rougail/src/rougail/annotator/variable.py

178 lines
7.8 KiB
Python

"""Annotate variable
"""
from ..utils import normalize_family
CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
'float': dict(opttype="FloatOption", func=float),
'choice': dict(opttype="ChoiceOption"),
'string': dict(opttype="StrOption"),
'password': dict(opttype="PasswordOption"),
'mail': dict(opttype="EmailOption"),
'boolean': dict(opttype="BoolOption"),
'symlink': dict(opttype="SymLinkOption"),
'filename': dict(opttype="FilenameOption"),
'date': dict(opttype="DateOption"),
'unix_user': dict(opttype="UsernameOption"),
'ip': dict(opttype="IPOption", initkwargs={'allow_reserved': True}),
'local_ip': dict(opttype="IPOption", initkwargs={'private_only': True,
'warnings_only': True}),
'netmask': dict(opttype="NetmaskOption"),
'network': dict(opttype="NetworkOption"),
'broadcast': dict(opttype="BroadcastOption"),
'netbios': dict(opttype="DomainnameOption", initkwargs={'type': 'netbios',
'warnings_only': True}),
'domain': dict(opttype="DomainnameOption", initkwargs={'type': 'domainname',
'allow_ip': False}),
'hostname': dict(opttype="DomainnameOption", initkwargs={'type': 'hostname',
'allow_ip': False}),
'web_address': dict(opttype="URLOption", initkwargs={'allow_ip': True,
'allow_without_dot': True}),
'port': dict(opttype="PortOption", initkwargs={'allow_private': True}),
'mac': dict(opttype="MACOption"),
'cidr': dict(opttype="IPOption", initkwargs={'cidr': True}),
'network_cidr': dict(opttype="NetworkOption", initkwargs={'cidr': True}),
}
FORCE_CHOICE = {'schedule': ['none', 'daily', 'weekly', 'monthly'],
'schedulemod': ['pre', 'post'],
}
RENAME_ATTIBUTES = {'description': 'doc'}
class VariableAnnotator: # pylint: disable=R0903
"""Annotate variable
"""
def __init__(self,
objectspace,
):
if not hasattr(objectspace.space, 'variables'):
return
self.objectspace = objectspace
self.convert_variable()
self.convert_test()
def convert_variable(self):
"""convert variable
"""
for families in self.objectspace.space.variables.values():
families.doc = families.name
families.path = families.name
for family in families.family.values():
if not hasattr(family, 'description'):
family.description = family.name
for key, value in RENAME_ATTIBUTES.items():
setattr(family, value, getattr(family, key))
setattr(family, key, None)
family.name = normalize_family(family.name)
if not hasattr(family, 'variable'):
continue
for variable in family.variable.values():
if isinstance(variable, self.objectspace.leadership):
# first variable is a leader, others are follower
variable_type = 'leader'
for follower in variable.variable:
self._convert_variable(families.name,
follower,
variable_type,
)
variable_type = 'follower'
else:
self._convert_variable(families.name,
variable,
'variable',
)
def _convert_variable(self,
namespace: str,
variable,
variable_type: str,
) -> None:
if variable.type != 'symlink' and not hasattr(variable, 'description'):
variable.description = variable.name
if hasattr(variable, 'value'):
value_to_del = []
for idx, value in enumerate(variable.value):
if not hasattr(value, 'type'):
value.type = variable.type
if 'name' not in vars(value):
value_to_del.append(idx)
else:
value.name = CONVERT_OPTION.get(value.type, {}).get('func', str)(value.name)
value_to_del.sort(reverse=True)
for idx in value_to_del:
del variable.value[idx]
if not variable.value:
del variable.value
for key, value in RENAME_ATTIBUTES.items():
setattr(variable, value, getattr(variable, key))
setattr(variable, key, None)
if variable_type == 'follower':
if variable.multi is True:
variable.multi = 'submulti'
else:
variable.multi = True
self._convert_valid_enum(namespace,
variable,
)
def _convert_valid_enum(self,
namespace,
variable,
):
"""some types are, in fact, choices
convert this kind of variables into choice
"""
if variable.type in FORCE_CHOICE:
if not hasattr(self.objectspace.space, 'constraints'):
xmlfiles = variable.xmlfiles
self.objectspace.space.constraints = self.objectspace.constraints(xmlfiles)
self.objectspace.space.constraints.namespace = namespace
if not hasattr(self.objectspace.space.constraints, 'check'):
self.objectspace.space.constraints.check = []
check = self.objectspace.check(variable.xmlfiles)
check.name = 'valid_enum'
check.target = variable.path
check.namespace = namespace
check.param = []
for value in FORCE_CHOICE[variable.type]:
param = self.objectspace.param(variable.xmlfiles)
param.text = value
check.param.append(param)
self.objectspace.space.constraints.check.append(check)
variable.type = 'string'
def convert_test(self):
"""Convert variable tests value
"""
for families in self.objectspace.space.variables.values():
for family in families.family.values():
if not hasattr(family, 'variable'):
continue
for variable in family.variable.values():
if isinstance(variable, self.objectspace.leadership):
for follower in variable.variable:
self._convert_test(follower)
else:
self._convert_test(variable)
def _convert_test(self,
variable,
) -> None:
if hasattr(variable, 'test'):
if not variable.test:
del variable.test
return
values = variable.test.split('|')
new_values = []
for value in values:
if value == '':
value = None
else:
value = CONVERT_OPTION.get(variable.type, {}).get('func', str)(value)
new_values.append(value)
variable.test = tuple(new_values)