From 1816813f9261b1b50bd769eb38f7b648cd6512d8 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Wed, 5 Sep 2018 20:22:16 +0200 Subject: [PATCH] duplicate => copy + add deepcopy --- test/test_duplicate_config.py | 6 +- test/test_metaconfig.py | 54 ++++++++++++++ tiramisu/api.py | 35 ++++----- tiramisu/config.py | 130 +++++++++++++++++++++++----------- 4 files changed, 163 insertions(+), 62 deletions(-) diff --git a/test/test_duplicate_config.py b/test/test_duplicate_config.py index f5e9ab6..4c042fc 100644 --- a/test/test_duplicate_config.py +++ b/test/test_duplicate_config.py @@ -46,9 +46,9 @@ def make_description(): return descr -def test_duplicate(): +def test_copy(): cfg = Config(make_description()) - ncfg = cfg.config.duplicate() + ncfg = cfg.config.copy() assert cfg.option('creole.general.numero_etab').value.get() == None cfg.option('creole.general.numero_etab').value.set('oui') assert cfg.option('creole.general.numero_etab').value.get() == 'oui' @@ -63,7 +63,7 @@ def to_tuple(val): return tuple([tuple(v) for v in val]) -def test_duplicate_force_store_value(): +def test_copy_force_store_value(): descr = make_description() conf = Config(descr) conf2 = Config(descr) diff --git a/test/test_metaconfig.py b/test/test_metaconfig.py index 7615b2a..182d388 100644 --- a/test/test_metaconfig.py +++ b/test/test_metaconfig.py @@ -691,6 +691,60 @@ def test_meta_reset(): assert meta.config('conf2').option('ip_admin_eth0.ip_admin_eth0').value.get() == [] +def test_meta_properties_meta_copy(): + ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1']) + netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, properties=('disabled',)) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + conf1 = Config(interface1, session_id='conf1') + conf2 = Config(interface1, session_id='conf2') + meta = MetaConfig([conf1, conf2]) + meta.property.read_write() + + conf3 = meta.config('conf1').config.copy(session_id='conf3') + meta2 = conf3.config.meta() + assert meta != meta2 + + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + assert meta.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + meta.option('ip_admin_eth0').value.set(['192.168.1.2']) + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.2']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.2']} + assert meta.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.2']} + ret = meta.value.set('ip_admin_eth0', ['192.168.1.3'], force_default_if_same=True) + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.3']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.3']} + assert meta.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.3']} + + +def test_meta_properties_meta_deepcopy(): + ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1']) + netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, + properties=('disabled',)) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + conf1 = Config(interface1, session_id='conf1') + conf2 = Config(interface1, session_id='conf2') + meta = MetaConfig([conf1, conf2]) + meta.permissive.set(frozenset({'hidden'})) + meta.property.read_write() + + meta2 = meta.config('conf1').config.deepcopy('conf3') + assert meta != meta2 + assert meta.permissive.get() == meta2.permissive.get() + + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + assert meta2.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + meta.option('ip_admin_eth0').value.set(['192.168.1.2']) + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.2']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.2']} + assert meta2.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + meta.value.set('ip_admin_eth0', ['192.168.1.3'], force_default_if_same=True) + assert meta.config('conf1').config.dict() == {'ip_admin_eth0': ['192.168.1.3']} + assert meta.config('conf2').config.dict() == {'ip_admin_eth0': ['192.168.1.3']} + assert meta2.config('conf3').config.dict() == {'ip_admin_eth0': ['192.168.1.1']} + + def test_meta_properties_meta_set_value(): ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1']) netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, properties=('disabled',)) diff --git a/tiramisu/api.py b/tiramisu/api.py index 0ff4a77..e53b36a 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -920,10 +920,18 @@ class TiramisuContextConfig(TiramisuContext): def name(self): return self.config_bag.context.impl_getname() - def duplicate(self, + def _c_copy(self, session_id=None): return TiramisuAPI(self.config_bag.context.duplicate(session_id)) + def _c_deepcopy(self, + session_id=None): + return TiramisuAPI(self.config_bag.context.duplicate(session_id, + deep=True)) + + def _c_meta(self): + return TiramisuAPI(self.config_bag.context.cfgimpl_get_meta()) + def _m_new(self, name): return TiramisuAPI(self.config_bag.context.new_config(name)) @@ -942,6 +950,8 @@ class TiramisuContextConfig(TiramisuContext): return getattr(self, '_m_' + name) elif isinstance(self.config_bag.context, KernelGroupConfig): return getattr(self, '_g_' + name) + elif isinstance(self.config_bag.context, KernelConfig): + return getattr(self, '_c_' + name) except APIError: raise APIError(_('{} is unknown').format(name)) raise APIError(_('{} is unknown').format(name)) @@ -981,27 +991,18 @@ class TiramisuAPI(TiramisuHelp): def __getattr__(self, subfunc: str) -> Any: if subfunc == 'forcepermissive': if isinstance(self._config, ConfigBag): - config = self._config.config - force = not self._config.properties + config_bag = self._config.copy() + del config_bag.properties else: - config = self._config - force = None - config_bag = ConfigBag(context=config) + config_bag = ConfigBag(context=self._config) config_bag.set_permissive() - if force is True: - config_bag.properties = frozenset() return TiramisuAPI(config_bag) elif subfunc == 'unrestraint': - #if isinstance(self._config, ConfigBag): - # config = self._config.context - # force = self._config.force_permissive - #else: - config = self._config - #force = None - config_bag = ConfigBag(context=config) + if isinstance(self._config, ConfigBag): + config_bag = self._config.copy() + else: + config_bag = ConfigBag(context=self._config) config_bag.properties = frozenset() - #if force is not None: - #config_bag.force_permissive = force return TiramisuAPI(config_bag) elif subfunc in self.registers: if not isinstance(self._config, ConfigBag): diff --git a/tiramisu/config.py b/tiramisu/config.py index 3afdbf4..7a56a5e 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -684,18 +684,39 @@ class _CommonConfig(SubConfig): session_id=None, force_values=None, force_settings=None, - storage=None): - config = KernelConfig(self._impl_descr, - _duplicate=True, - session_id=session_id, - force_values=force_values, - force_settings=force_settings, - storage=storage) + storage=None, + deep=False): + if isinstance(self, KernelConfig): + config = KernelConfig(self._impl_descr, + _duplicate=True, + session_id=session_id, + force_values=force_values, + force_settings=force_settings, + storage=storage) + elif isinstance(self, KernelMetaConfig): + config = KernelMetaConfig([], + _duplicate=True, + optiondescription=self._impl_descr, + session_id=session_id, + force_values=force_values, + force_settings=force_settings, + storage=storage) + else: + raise Exception('hu?') config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation()) config.cfgimpl_get_settings()._p_.importation(self.cfgimpl_get_settings( )._p_.exportation()) config.cfgimpl_get_settings()._pp_.importation(self.cfgimpl_get_settings( )._pp_.exportation()) + if self._impl_meta: + if deep: + meta = self._impl_meta().duplicate(deep=deep) + meta._impl_children.append(config) + config._impl_meta = weakref.ref(meta) + config = meta + else: + config._impl_meta = self._impl_meta + config._impl_meta()._impl_children.append(config) return config @@ -750,10 +771,10 @@ class KernelConfig(_CommonConfig): permissives) self._impl_values = Values(self, values) - super(KernelConfig, self).__init__(descr, - weakref.ref(self), - ConfigBag(self), - None) + super().__init__(descr, + weakref.ref(self), + ConfigBag(self), + None) if _duplicate is False and (force_settings is None or force_values is None): self._impl_build_all_caches() self._impl_name = session_id @@ -774,7 +795,10 @@ class KernelGroupConfig(_CommonConfig): children, session_id=None, persistent=False, + force_settings=None, + force_values=None, _descr=None, + _duplicate=False, storage=None): if not isinstance(children, list): raise ValueError(_("groupconfig's children must be a list")) @@ -795,19 +819,31 @@ class KernelGroupConfig(_CommonConfig): raise ConflictError(_('config name must be uniq in ' 'groupconfig for "{0}"').format(name)) self._impl_children = children - properties, permissives, values, session_id = get_storages(self, - session_id, - persistent, - storage=storage) - self._impl_settings = Settings(self, - properties, - permissives) - self._impl_values = Values(self, values) + + if force_settings is not None and force_values is not None: + self._impl_settings = Settings(self, + force_settings[0], + force_settings[1]) + self._impl_values = Values(self, + force_values) + else: + properties, permissives, values, session_id = get_storages(self, + session_id, + persistent, + storage=storage) + if not valid_name(session_id): + raise ValueError(_("invalid session ID: {0} for config").format(session_id)) + self._impl_settings = Settings(self, + properties, + permissives) + self._impl_values = Values(self, + values) + self._impl_meta = None - super(KernelGroupConfig, self).__init__(_descr, - weakref.ref(self), - ConfigBag(self), - None) + super().__init__(_descr, + weakref.ref(self), + ConfigBag(self), + None) #undocumented option used only in test script self._impl_name = session_id @@ -820,8 +856,8 @@ class KernelGroupConfig(_CommonConfig): if resetted_opts is None: resetted_opts = [] if isinstance(self, KernelMetaConfig): - super(KernelGroupConfig, self).cfgimpl_reset_cache(option_bag, - resetted_opts=copy(resetted_opts)) + super().cfgimpl_reset_cache(option_bag, + resetted_opts=copy(resetted_opts)) for child in self._impl_children: child.cfgimpl_reset_cache(option_bag, resetted_opts=copy(resetted_opts)) @@ -946,15 +982,22 @@ class KernelMetaConfig(KernelGroupConfig): children, session_id=None, persistent=False, - optiondescription=None): + force_settings=None, + force_values=None, + optiondescription=None, + storage=None, + _duplicate=False): descr = None if optiondescription is not None: - new_children = [] - for child_session_id in children: - new_children.append(KernelConfig(optiondescription, - persistent=persistent, - session_id=child_session_id)) - children = new_children + if not _duplicate: + new_children = [] + for child_session_id in children: + new_children.append(KernelConfig(optiondescription, + persistent=persistent, + session_id=child_session_id)) + children = new_children + else: + descr = optiondescription for child in children: if not isinstance(child, _CommonConfig): try: @@ -972,10 +1015,13 @@ class KernelMetaConfig(KernelGroupConfig): 'have the same optiondescription')) child._impl_meta = weakref.ref(self) - super(KernelMetaConfig, self).__init__(children, - session_id, - persistent, - descr) + super().__init__(children, + session_id, + persistent, + force_settings=force_settings, + force_values=force_values, + storage=storage, + _descr=descr) def set_value(self, path, @@ -995,12 +1041,12 @@ class KernelMetaConfig(KernelGroupConfig): raise ValueError(_('force_default, force_default_if_same or ' 'force_dont_change_value cannot be set with' ' only_config')) - return super(KernelMetaConfig, self).set_value(path, - index, - value, - config_bag, - only_config=only_config, - _commit=_commit) + return super().set_value(path, + index, + value, + config_bag, + only_config=only_config, + _commit=_commit) ret = [] if force_default or force_default_if_same or force_dont_change_value: if force_default and force_dont_change_value: