add metaconfig
authorEmmanuel Garette <egarette@cadoles.com>
Tue, 17 Sep 2013 07:02:10 +0000 (09:02 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Tue, 17 Sep 2013 07:02:10 +0000 (09:02 +0200)
test/test_metaconfig.py
tiramisu/config.py

index 35d65d5..9214cb4 100644 (file)
-#import autopath
-
-#from py.test import raises
-
-#from tiramisu.setting import owners
-#from tiramisu.config import Config, MetaConfig
-#from tiramisu.option import IntOption, OptionDescription
-#from tiramisu.error import ConfigError
-
-#owners.addowner('meta')
-
-
-#def make_description():
-#    i1 = IntOption('i1', '')
-#    i2 = IntOption('i2', '', default=1)
-#    i3 = IntOption('i3', '')
-#    i4 = IntOption('i4', '', default=2)
-#    od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
-#    od2 = OptionDescription('od2', '', [od1])
-#    conf1 = Config(od2)
-#    conf2 = Config(od2)
-#    meta = MetaConfig([conf1, conf2])
-#    meta.cfgimpl_get_settings().setowner(owners.meta)
-#    return meta
-
-
-##FIXME ne pas mettre 2 meta dans une config
-##FIXME ne pas mettre 2 OD differents dans un meta
-#def test_none():
-#    meta = make_description()
-#    conf1, conf2 = meta._impl_children
-#    assert conf1.od1.i3 is conf2.od1.i3 is None
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
-#    meta.od1.i3 = 3
-#    assert conf1.od1.i3 == conf2.od1.i3 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
-#    meta.od1.i3 = 3
-#    conf1.od1.i3 = 2
-#    assert conf1.od1.i3 == 2
-#    assert conf2.od1.i3 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
-#    meta.od1.i3 = 4
-#    assert conf1.od1.i3 == 2
-#    assert conf2.od1.i3 == 4
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
-#    del(meta.od1.i3)
-#    assert conf1.od1.i3 == 2
-#    assert conf2.od1.i3 is None
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
-#    del(conf1.od1.i3)
-#    assert conf1.od1.i3 is conf2.od1.i3 is None
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
-
-
-#def test_default():
-#    meta = make_description()
-#    conf1, conf2 = meta._impl_children
-#    assert conf1.od1.i2 == conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    meta.od1.i2 = 3
-#    assert conf1.od1.i2 == conf2.od1.i2 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    meta.od1.i2 = 3
-#    conf1.od1.i2 = 2
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    meta.od1.i2 = 4
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 4
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    del(meta.od1.i2)
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    del(conf1.od1.i2)
-#    assert conf1.od1.i2 == conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-
-
-#def test_contexts():
-#    meta = make_description()
-#    conf1, conf2 = meta._impl_children
-#    assert conf1.od1.i2 == conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    meta.set_contexts('od1.i2', 6)
-#    assert meta.od1.i2 == 1
-#    assert conf1.od1.i2 == conf2.od1.i2 == 6
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.user
-
-
-#def test_find():
-#    meta = make_description()
-#    i2 = meta.unwrap_from_path('od1.i2')
-#    assert [i2] == meta.find(byname='i2')
-#    assert i2 == meta.find_first(byname='i2')
-#    assert meta.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None, 'od1.i2': 1}
-
-
-#def test_meta_meta():
-#    meta1 = make_description()
-#    meta2 = MetaConfig([meta1])
-#    meta2.cfgimpl_get_settings().setowner(owners.meta)
-#    conf1, conf2 = meta1._impl_children
-#    assert conf1.od1.i2 == conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    meta2.od1.i2 = 3
-#    assert conf1.od1.i2 == conf2.od1.i2 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    meta2.od1.i2 = 3
-#    conf1.od1.i2 = 2
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 3
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    meta2.od1.i2 = 4
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 4
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-#    del(meta2.od1.i2)
-#    assert conf1.od1.i2 == 2
-#    assert conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
-#    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    del(conf1.od1.i2)
-#    assert conf1.od1.i2 == conf2.od1.i2 == 1
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
-#    meta1.od1.i2 = 6
-#    assert conf1.od1.i2 == conf2.od1.i2 == 6
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
-
-
-#def test_meta_meta_set():
-#    meta1 = make_description()
-#    meta2 = MetaConfig([meta1])
-#    meta2.cfgimpl_get_settings().setowner(owners.meta)
-#    conf1, conf2 = meta1._impl_children
-#    meta2.set_contexts('od1.i1', 7)
-#    assert conf1.od1.i1 == conf2.od1.i1 == 7
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
-#    assert [conf1, conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
-#    conf1.od1.i1 = 8
-#    assert [conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
-#    assert [conf1] == meta2.find_first_contexts(byname='i1', byvalue=8)
-#    raises(AttributeError, "meta2.find_first_contexts(byname='i1', byvalue=10)")
-
-
-#def test_not_meta():
-#    i1 = IntOption('i1', '')
-#    od1 = OptionDescription('od1', '', [i1])
-#    od2 = OptionDescription('od2', '', [od1])
-#    conf1 = Config(od2)
-#    conf2 = Config(od2)
-#    meta = MetaConfig([conf1, conf2], False)
-#    raises(ConfigError, 'meta.od1.i1')
-#    conf1, conf2 = meta._impl_children
-#    meta.set_contexts('od1.i1', 7)
-#    assert conf1.od1.i1 == conf2.od1.i1 == 7
-#    assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
-
-
-#def test_meta_path():
-#    meta = make_description()
-#    assert meta._impl_path is None
-#    assert meta.od1._impl_path == 'od1'
+import autopath
+
+from py.test import raises
+
+from tiramisu.setting import owners
+from tiramisu.config import Config, MetaConfig
+from tiramisu.option import IntOption, OptionDescription
+from tiramisu.error import ConfigError
+
+owners.addowner('meta')
+
+
+def make_description():
+    i1 = IntOption('i1', '')
+    i2 = IntOption('i2', '', default=1)
+    i3 = IntOption('i3', '')
+    i4 = IntOption('i4', '', default=2)
+    od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2)
+    conf2 = Config(od2)
+    meta = MetaConfig([conf1, conf2])
+    meta.cfgimpl_get_settings().setowner(owners.meta)
+    return meta
+
+
+#FIXME ne pas mettre 2 meta dans une config
+#FIXME ne pas mettre 2 OD differents dans un meta
+def test_none():
+    meta = make_description()
+    conf1, conf2 = meta._impl_children
+    assert conf1.od1.i3 is conf2.od1.i3 is None
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
+    meta.od1.i3 = 3
+    assert conf1.od1.i3 == conf2.od1.i3 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
+    meta.od1.i3 = 3
+    conf1.od1.i3 = 2
+    assert conf1.od1.i3 == 2
+    assert conf2.od1.i3 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
+    meta.od1.i3 = 4
+    assert conf1.od1.i3 == 2
+    assert conf2.od1.i3 == 4
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
+    del(meta.od1.i3)
+    assert conf1.od1.i3 == 2
+    assert conf2.od1.i3 is None
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
+    del(conf1.od1.i3)
+    assert conf1.od1.i3 is conf2.od1.i3 is None
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
+
+
+def test_default():
+    meta = make_description()
+    conf1, conf2 = meta._impl_children
+    assert conf1.od1.i2 == conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    meta.od1.i2 = 3
+    assert conf1.od1.i2 == conf2.od1.i2 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    meta.od1.i2 = 3
+    conf1.od1.i2 = 2
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    meta.od1.i2 = 4
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 4
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    del(meta.od1.i2)
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    del(conf1.od1.i2)
+    assert conf1.od1.i2 == conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+
+
+def test_contexts():
+    meta = make_description()
+    conf1, conf2 = meta._impl_children
+    assert conf1.od1.i2 == conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    meta.set_contexts('od1.i2', 6)
+    assert meta.od1.i2 == 1
+    assert conf1.od1.i2 == conf2.od1.i2 == 6
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.user
+
+
+def test_find():
+    meta = make_description()
+    i2 = meta.unwrap_from_path('od1.i2')
+    assert [i2] == meta.find(byname='i2')
+    assert i2 == meta.find_first(byname='i2')
+    assert meta.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None, 'od1.i2': 1}
+
+
+def test_meta_meta():
+    meta1 = make_description()
+    meta2 = MetaConfig([meta1])
+    meta2.cfgimpl_get_settings().setowner(owners.meta)
+    conf1, conf2 = meta1._impl_children
+    assert conf1.od1.i2 == conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    meta2.od1.i2 = 3
+    assert conf1.od1.i2 == conf2.od1.i2 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    meta2.od1.i2 = 3
+    conf1.od1.i2 = 2
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 3
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    meta2.od1.i2 = 4
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 4
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+    del(meta2.od1.i2)
+    assert conf1.od1.i2 == 2
+    assert conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
+    assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    del(conf1.od1.i2)
+    assert conf1.od1.i2 == conf2.od1.i2 == 1
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
+    meta1.od1.i2 = 6
+    assert conf1.od1.i2 == conf2.od1.i2 == 6
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
+
+
+def test_meta_meta_set():
+    meta1 = make_description()
+    meta2 = MetaConfig([meta1])
+    meta2.cfgimpl_get_settings().setowner(owners.meta)
+    conf1, conf2 = meta1._impl_children
+    meta2.set_contexts('od1.i1', 7)
+    assert conf1.od1.i1 == conf2.od1.i1 == 7
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
+    assert [conf1, conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
+    conf1.od1.i1 = 8
+    assert [conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
+    assert [conf1] == meta2.find_first_contexts(byname='i1', byvalue=8)
+    raises(AttributeError, "meta2.find_first_contexts(byname='i1', byvalue=10)")
+
+
+def test_not_meta():
+    i1 = IntOption('i1', '')
+    od1 = OptionDescription('od1', '', [i1])
+    od2 = OptionDescription('od2', '', [od1])
+    conf1 = Config(od2)
+    conf2 = Config(od2)
+    meta = MetaConfig([conf1, conf2], False)
+    raises(ConfigError, 'meta.od1.i1')
+    conf1, conf2 = meta._impl_children
+    meta.set_contexts('od1.i1', 7)
+    assert conf1.od1.i1 == conf2.od1.i1 == 7
+    assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
+
+
+def test_meta_path():
+    meta = make_description()
+    assert meta._impl_path is None
+    assert meta.od1._impl_path == 'od1'
index fac3caf..591eb68 100644 (file)
@@ -43,7 +43,7 @@ class SubConfig(object):
         :type subpath: `str` with the path name
         """
         # main option description
-        if not isinstance(descr, OptionDescription):
+        if descr is not None and not isinstance(descr, OptionDescription):
             raise TypeError(_('descr must be an optiondescription, not {0}'
                               ).format(type(descr)))
         self._impl_descr = descr
@@ -552,99 +552,99 @@ class Config(CommonConfig):
             self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
 
 
-#class MetaConfig(CommonConfig):
-#    __slots__ = ('_impl_children',)
-
-#    def __init__(self, children, meta=True, session_id=None, persistent=False):
-#        if not isinstance(children, list):
-#            raise ValueError(_("metaconfig's children must be a list"))
-#        self._impl_descr = None
-#        self._impl_path = None
-#        if meta:
-#            for child in children:
-#                if not isinstance(child, CommonConfig):
-#                    raise TypeError(_("metaconfig's children "
-#                                      "must be config, not {0}"
-#                                      ).format(type(child)))
-#                if self._impl_descr is None:
-#                    self._impl_descr = child.cfgimpl_get_description()
-#                elif not self._impl_descr is child.cfgimpl_get_description():
-#                    raise ValueError(_('all config in metaconfig must '
-#                                       'have the same optiondescription'))
-#                if child.cfgimpl_get_meta() is not None:
-#                    raise ValueError(_("child has already a metaconfig's"))
-#                child._impl_meta = self
-
-#        self._impl_children = children
-#        settings, values = get_storages(self, session_id, persistent)
-#        self._impl_settings = Settings(self, settings)
-#        self._impl_values = Values(self, values)
-#        self._impl_meta = None
-
-#    def cfgimpl_get_children(self):
-#        return self._impl_children
-
-#    def cfgimpl_get_context(self):
-#        "a meta config is a config wich has a setting, that is itself"
-#        return self
-
-#    def cfgimpl_reset_cache(self,
-#                            only_expired=False,
-#                            only=('values', 'settings')):
-#        if 'values' in only:
-#            self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
-#        if 'settings' in only:
-#            self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
-#        for child in self._impl_children:
-#            child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
-
-#    def set_contexts(self, path, value):
-#        for child in self._impl_children:
-#            try:
-#                if not isinstance(child, MetaConfig):
-#                    setattr(child, path, value)
-#                else:
-#                    child.set_contexts(path, value)
-#            except PropertiesOptionError:
-#                pass
-
-#    def find_first_contexts(self, byname=None, bypath=None, byvalue=None,
-#                            type_='path', display_error=True):
-#        ret = []
-#        try:
-#            if bypath is None and byname is not None and \
-#                    self.cfgimpl_get_description() is not None:
-#                bypath = self._find(bytype=None, byvalue=None, byname=byname,
-#                                    first=True, type_='path',
-#                                    check_properties=False,
-#                                    display_error=display_error)
-#        except ConfigError:
-#            pass
-#        for child in self._impl_children:
-#            try:
-#                if not isinstance(child, MetaConfig):
-#                    if bypath is not None:
-#                        if byvalue is not None:
-#                            if getattr(child, bypath) == byvalue:
-#                                ret.append(child)
-#                        else:
-#                            #not raise
-#                            getattr(child, bypath)
-#                            ret.append(child)
-#                    else:
-#                        ret.append(child.find_first(byname=byname,
-#                                                    byvalue=byvalue,
-#                                                    type_=type_,
-#                                                    display_error=False))
-#                else:
-#                    ret.extend(child.find_first_contexts(byname=byname,
-#                                                         bypath=bypath,
-#                                                         byvalue=byvalue,
-#                                                         type_=type_,
-#                                                         display_error=False))
-#            except AttributeError:
-#                pass
-#        return self._find_return_results(ret, display_error)
+class MetaConfig(CommonConfig):
+    __slots__ = ('_impl_children', '__weakref__')
+
+    def __init__(self, children, meta=True, session_id=None, persistent=False):
+        if not isinstance(children, list):
+            raise ValueError(_("metaconfig's children must be a list"))
+        descr = None
+        if meta:
+            for child in children:
+                if not isinstance(child, CommonConfig):
+                    raise TypeError(_("metaconfig's children "
+                                      "must be config, not {0}"
+                                      ).format(type(child)))
+                if descr is None:
+                    descr = child.cfgimpl_get_description()
+                elif not descr is child.cfgimpl_get_description():
+                    raise ValueError(_('all config in metaconfig must '
+                                       'have the same optiondescription'))
+                if child.cfgimpl_get_meta() is not None:
+                    raise ValueError(_("child has already a metaconfig's"))
+                child._impl_meta = self
+
+        self._impl_children = children
+        settings, values = get_storages(self, session_id, persistent)
+        self._impl_settings = Settings(self, settings)
+        self._impl_values = Values(self, values)
+        super(MetaConfig, self).__init__(descr, weakref.ref(self))
+        self._impl_meta = None
+
+    def cfgimpl_get_children(self):
+        return self._impl_children
+
+    def cfgimpl_get_context(self):
+        "a meta config is a config wich has a setting, that is itself"
+        return self
+
+    def cfgimpl_reset_cache(self,
+                            only_expired=False,
+                            only=('values', 'settings')):
+        if 'values' in only:
+            self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
+        if 'settings' in only:
+            self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
+        for child in self._impl_children:
+            child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
+
+    def set_contexts(self, path, value):
+        for child in self._impl_children:
+            try:
+                if not isinstance(child, MetaConfig):
+                    setattr(child, path, value)
+                else:
+                    child.set_contexts(path, value)
+            except PropertiesOptionError:
+                pass
+
+    def find_first_contexts(self, byname=None, bypath=None, byvalue=None,
+                            type_='path', display_error=True):
+        ret = []
+        try:
+            if bypath is None and byname is not None and \
+                    self.cfgimpl_get_description() is not None:
+                bypath = self._find(bytype=None, byvalue=None, byname=byname,
+                                    first=True, type_='path',
+                                    check_properties=False,
+                                    display_error=display_error)
+        except ConfigError:
+            pass
+        for child in self._impl_children:
+            try:
+                if not isinstance(child, MetaConfig):
+                    if bypath is not None:
+                        if byvalue is not None:
+                            if getattr(child, bypath) == byvalue:
+                                ret.append(child)
+                        else:
+                            #not raise
+                            getattr(child, bypath)
+                            ret.append(child)
+                    else:
+                        ret.append(child.find_first(byname=byname,
+                                                    byvalue=byvalue,
+                                                    type_=type_,
+                                                    display_error=False))
+                else:
+                    ret.extend(child.find_first_contexts(byname=byname,
+                                                         bypath=bypath,
+                                                         byvalue=byvalue,
+                                                         type_=type_,
+                                                         display_error=False))
+            except AttributeError:
+                pass
+        return self._find_return_results(ret, display_error)
 
 
 def mandatory_warnings(config):