from config import Config from option import (OptionDescription, Option, ChoiceOption, BoolOption, FloatOption, StrOption, IntOption, IPOption, NetmaskOption, ArbitraryOption, group_types, apply_requires) # ____________________________________________________________ # reverse factory # XXX HAAAAAAAAAAAACK (but possibly a good one) def reverse_from_paths(data): "rebuilds a (fake) data structure from an unflatten `make_dict()` result" # ____________________________________________________________ _build_map = { bool: BoolOption, int: IntOption, float: FloatOption, str: StrOption, } def option_factory(name, value): "dummy -> Option('dummy')" if type(value) == list: return _build_map[type(value[0])](name, '', multi=True, default=value) else: return _build_map[type(value)](name, '', default=value) def build_options(data): "config.gc.dummy -> Option('dummy')" for key, value in data.items(): name = key.split('.')[-1] yield (key, option_factory(name, value)) # ____________________________________________________________ def parent(pathname): "config.gc.dummy -> config.gc" if "." in pathname: return ".".join(pathname.split('.')[:-1]) # no parent except rootconfig, naturally returns None def subgroups(pathname): "config.gc.dummy.bool -> [config.gc, config.gc.dummy]" group = parent(pathname) parents =[] while group is not None: parents.append(group) group = parent(group) return parents def build_option_descriptions(data): all_groups = [] for key in data.keys(): for group in subgroups(key): # so group is unique in the list if group not in all_groups: all_groups.append(group) for group in all_groups: name = group.split('.')[-1] yield (group, OptionDescription(name, '', [])) # ____________________________________________________________ descr = OptionDescription('tiramisu', 'fake rebuild structure', []) cfg = Config(descr) # add descrs in cfg def compare(a, b): l1 = a.split(".") l2 = b.split(".") if len(l1) < len(l2): return -1 elif len(l1) > len(l2): return 1 else: return 0 grps = list(build_option_descriptions(data)) groups = dict(grps) grp_paths = [pathname for pathname, opt_descr in grps] grp_paths.sort(compare) for grp in grp_paths: if not "." in grp: cfg._cfgimpl_descr.add_child(groups[grp]) cfg.cfgimpl_update() else: parentdescr = cfg.unwrap_from_path(parent(grp)) parentdescr.add_child(groups[grp]) getattr(cfg, parent(grp)).cfgimpl_update() # add options in descrs for pathname, opt in build_options(data): current_group_name = parent(pathname) if current_group_name == None: cfg._cfgimpl_descr.add_child(opt) cfg.cfgimpl_update() else: curr_grp = groups[current_group_name] curr_grp.add_child(opt) getattr(cfg, current_group_name).cfgimpl_update() return cfg # ____________________________________________________________ # extendable type class extend(type): """ A magic trick for classes, which lets you add methods or attributes to a class """ def extend(cls, extclass): bases = list(extclass.__bases__) bases.append(extclass) for cl in bases: for key, value in cl.__dict__.items(): if key == '__module__': continue setattr(cls, key, value) # ____________________________________________________________