From e118f07539a51abd176e3975e2e5ddd21c0679ac Mon Sep 17 00:00:00 2001 From: gwen Date: Thu, 6 Dec 2012 18:14:57 +0100 Subject: [PATCH] groupe_types are real types now --- test/test_parsing_group.py | 15 ++++++------ tiramisu/config.py | 20 +++++++++------- tiramisu/option.py | 23 ++++++++++-------- tiramisu/setting.py | 48 ++++++++++++++++++++++++++++++++++---- tiramisu/tool.py | 2 +- 5 files changed, 76 insertions(+), 32 deletions(-) diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index f97f4f6..d9c2e00 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -2,6 +2,7 @@ import autopath from tiramisu.config import * from tiramisu.option import * +from tiramisu.setting import groups from py.test import raises @@ -14,8 +15,6 @@ def make_description(): default=False) mode_conteneur_actif = BoolOption('mode_conteneur_actif', "le serveur est en mode conteneur", default=False) -# hidden (variable cachée) -# mode_conteneur_actif.taint() adresse_serveur_ntp = StrOption('serveur_ntp', "adresse serveur ntp", multi=True) time_zone = ChoiceOption('time_zone', 'fuseau horaire du serveur', ['Paris', 'Londres'], 'Paris') @@ -25,13 +24,13 @@ def make_description(): master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = OptionDescription('interface1', '', [master]) - interface1.set_group_type('family') + interface1.set_group_type(groups.family) general = OptionDescription('general', '', [numero_etab, nom_machine, nombre_interfaces, activer_proxy_client, mode_conteneur_actif, adresse_serveur_ntp, time_zone]) - general.set_group_type('family') + general.set_group_type(groups.family) creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1]) descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole] ) return descr @@ -63,7 +62,7 @@ def test_get_group_type(): def test_iter_on_groups(): descr = make_description() config = Config(descr) - result = list(config.creole.iter_groups(group_type= "family")) + result = list(config.creole.iter_groups(group_type=groups.family)) group_names = [res[0] for res in result] assert group_names == ['general', 'interface1'] @@ -101,7 +100,7 @@ def make_master_group(): nombre_interfaces, activer_proxy_client, mode_conteneur_actif, adresse_serveur_ntp, time_zone]) - general.set_group_type('family') + general.set_group_type(groups.family) creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1]) descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole] ) return descr @@ -127,13 +126,13 @@ def make_master_group2(): master = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = OptionDescription('interface1', '', [master]) - interface1.set_group_type('group', master='interface1') + interface1.set_group_type(groups.group, master='interface1') general = OptionDescription('general', '', [numero_etab, nom_machine, nombre_interfaces, activer_proxy_client, mode_conteneur_actif, adresse_serveur_ntp, time_zone]) - general.set_group_type('family') + general.set_group_type(groups.family) creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1]) descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole] ) return descr diff --git a/tiramisu/config.py b/tiramisu/config.py index e6e976c..1b69006 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -26,7 +26,7 @@ from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError, MandatoryError, MethodCallError, NoValueReturned) from tiramisu.option import (OptionDescription, Option, SymLinkOption, Multi, apply_requires) -from tiramisu.setting import settings, group_types +from tiramisu.setting import settings, groups # ____________________________________________________________ class Config(object): @@ -457,20 +457,24 @@ class Config(object): """iteration on groups objects only. All groups are returned if `group_type` is `None`, otherwise the groups can be filtered by categories (families, or whatever). + :param group_type: if defined, is an instance of `settings.GroupName` + or `settings.MasterGroupName` that lives in + `settings.groups` + """ - if group_type == None: - groups = group_types - else: - if group_type not in group_types: + if group_type is not None: + if not isinstance(group_type, groups.GroupName): raise TypeError("Unknown group_type: {0}".format(group_type)) - groups = [group_type] for child in self._cfgimpl_descr._children: if isinstance(child, OptionDescription): try: - if child.get_group_type() in groups: + if group_type is not None: + if child.get_group_type() == group_type: + yield child._name, getattr(self, child._name) + else: yield child._name, getattr(self, child._name) except: - pass # hidden, disabled option + pass # ______________________________________________________________________ def __str__(self): "Config's string representation" diff --git a/tiramisu/option.py b/tiramisu/option.py index 726b848..b5ca031 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -26,7 +26,7 @@ from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError, RequiresError, RequirementRecursionError, MandatoryError, PropertiesOptionError) from tiramisu.autolib import carry_out_calculation -from tiramisu.setting import settings, group_types, groups_has_master +from tiramisu.setting import settings, groups requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')] @@ -470,9 +470,9 @@ class NetmaskOption(Option): return isinstance(value, str) class OptionDescription(HiddenBaseType, DisabledBaseType): - "Config's schema (organisation) and container of Options" - "the group_type is an attribute useful for iteration on groups in a config" - group_type = 'default' + """Config's schema (organisation, group) and container of Options""" + # the group_type is useful for filtering OptionDescriptions in a config + group_type = groups.default def __init__(self, name, doc, children, requires=None): """ :param children: is a list of option descriptions (including @@ -485,7 +485,7 @@ class OptionDescription(HiddenBaseType, DisabledBaseType): self._build() self.properties = [] # 'hidden', 'disabled'... # if this group is a master group, master is set - # to the master option name + # to the master option name. it's just a ref to a name self.master = None def getdoc(self): @@ -538,10 +538,14 @@ class OptionDescription(HiddenBaseType, DisabledBaseType): return paths # ____________________________________________________________ def set_group_type(self, group_type, master=None): - ":param group_type: string in group_types" - if group_type in group_types: + """sets a given group object to an OptionDescription + + :param group_type: an instance of `GroupName` or `MasterGroupName` + that lives in `setting.groups` + """ + if isinstance(group_type, groups.GroupName): self.group_type = group_type - if group_type in groups_has_master: + if isinstance(group_type, groups.MasterGroupName): if master is None: raise ConfigError('this group type ({0}) needs a master ' 'for OptionDescription {1}'.format(group_type, @@ -553,8 +557,7 @@ class OptionDescription(HiddenBaseType, DisabledBaseType): group_type, self._name)) self.master = master else: - raise ConfigError('not allowed value for group_type : {0}'.format( - group_type)) + raise ConfigError('not allowed group_type : {0}'.format(group_type)) def get_group_type(self): return self.group_type diff --git a/tiramisu/setting.py b/tiramisu/setting.py index c2140a9..2bc3a9f 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -21,11 +21,49 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ -# available group_type values -_group_name = ('default', 'family', 'group') -groups_has_master = ('group', ) -class Group(str): pass -group_types = tuple(Group(i) for i in _group_name) +class _const: + """convenient class that emulates a module + and builds constants (that is, unique group names)""" + class GroupError(TypeError): pass + + def __setattr__(self, name, value): + if self.__dict__.has_key(name): + raise self.GroupError, "Can't rebind group (%s)"%name + self.__dict__[name] = value + + def __delattr__(self, name): + if self.__dict__.has_key(name): + raise self.GroupError, "Can't unbind group (%s)"%name + raise NameError, name + +groups = _const() +def populate_groups(): + "populates the available groups in the appropriate namespaces" + _available_group_names = ('default', 'family', 'group') + _available_groups_with_a_master = ('group', ) + class GroupName(str): + """allowed normal group (OptionDescription) names + *normal* means : groups that are not master + """ + pass + + class MasterGroupName(GroupName): + """allowed normal group (OptionDescription) names + *master* means : groups that have the 'master' attribute set + """ + pass + + groups.GroupName = GroupName + groups.MasterGroupName = MasterGroupName + # populates normal or master groups + for grp in _available_group_names: + if grp in _available_groups_with_a_master: + setattr(groups, grp, MasterGroupName(grp)) + else: + setattr(groups, grp, GroupName(grp)) + +populate_groups() +# ____________________________________________________________ class Setting(): "``Config()``'s configuration options" diff --git a/tiramisu/tool.py b/tiramisu/tool.py index 9f082bf..c2493de 100644 --- a/tiramisu/tool.py +++ b/tiramisu/tool.py @@ -20,7 +20,7 @@ from tiramisu.config import Config from tiramisu.option import (OptionDescription, Option, ChoiceOption, BoolOption, FloatOption, StrOption, IntOption, IPOption, NetmaskOption, - group_types, apply_requires) + apply_requires) # ____________________________________________________________ # reverse factory