key is now always path and change opt by path dictionary storage
authorEmmanuel Garette <egarette@cadoles.com>
Wed, 21 Aug 2013 20:21:50 +0000 (22:21 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Wed, 21 Aug 2013 20:21:50 +0000 (22:21 +0200)
12 files changed:
test/test_cache.py
test/test_config.py
test/test_metaconfig.py
test/test_option_calculation.py
test/test_option_setting.py
test/test_permissive.py
tiramisu/config.py
tiramisu/setting.py
tiramisu/storage/dictionary/setting.py
tiramisu/storage/dictionary/storage.py
tiramisu/storage/dictionary/value.py
tiramisu/value.py

index 61eb8f4..ec51455 100644 (file)
@@ -20,13 +20,13 @@ def test_cache():
     values = c.cfgimpl_get_values()
     settings = c.cfgimpl_get_settings()
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u2
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
-    assert od1.u2 in values._p_.get_cached('value', c)
-    assert od1.u2 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
+    assert 'u2' in values._p_.get_cached('value', c)
+    assert 'u2' in settings._p_.get_cached('property', c)
 
 
 def test_cache_reset():
@@ -36,44 +36,44 @@ def test_cache_reset():
     settings = c.cfgimpl_get_settings()
     #when change a value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u2 = 1
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when remove a value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     del(c.u2)
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when add/del property
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_get_settings()[od1.u2].append('test')
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_get_settings()[od1.u2].remove('test')
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when enable/disabled property
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_get_settings().append('test')
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_get_settings().remove('test')
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
 
 
 def test_cache_reset_multi():
@@ -83,32 +83,32 @@ def test_cache_reset_multi():
     settings = c.cfgimpl_get_settings()
     #when change a value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u3 = [1]
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when append value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u3.append(1)
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when pop value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u3.pop(1)
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     #when remove a value
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     del(c.u3)
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
 
 
 def test_reset_cache():
@@ -117,23 +117,23 @@ def test_reset_cache():
     values = c.cfgimpl_get_values()
     settings = c.cfgimpl_get_settings()
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache()
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
     c.u1
     sleep(1)
     c.u2
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
-    assert od1.u2 in values._p_.get_cached('value', c)
-    assert od1.u2 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
+    assert 'u2' in values._p_.get_cached('value', c)
+    assert 'u2' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache()
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
-    assert od1.u2 not in values._p_.get_cached('value', c)
-    assert od1.u2 not in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
+    assert 'u2' not in values._p_.get_cached('value', c)
+    assert 'u2' not in settings._p_.get_cached('property', c)
 
 
 def test_reset_cache_only_expired():
@@ -142,22 +142,22 @@ def test_reset_cache_only_expired():
     values = c.cfgimpl_get_values()
     settings = c.cfgimpl_get_settings()
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache(True)
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     sleep(1)
     c.u2
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
-    assert od1.u2 in values._p_.get_cached('value', c)
-    assert od1.u2 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
+    assert 'u2' in values._p_.get_cached('value', c)
+    assert 'u2' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache(True)
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
-    assert od1.u2 in values._p_.get_cached('value', c)
-    assert od1.u2 in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
+    assert 'u2' in values._p_.get_cached('value', c)
+    assert 'u2' in settings._p_.get_cached('property', c)
 
 
 def test_reset_cache_only():
@@ -166,14 +166,14 @@ def test_reset_cache_only():
     values = c.cfgimpl_get_values()
     settings = c.cfgimpl_get_settings()
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache(only=('values',))
-    assert od1.u1 not in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' not in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.u1
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' in settings._p_.get_cached('property', c)
     c.cfgimpl_reset_cache(only=('settings',))
-    assert od1.u1 in values._p_.get_cached('value', c)
-    assert od1.u1 not in settings._p_.get_cached('property', c)
+    assert 'u1' in values._p_.get_cached('value', c)
+    assert 'u1' not in settings._p_.get_cached('property', c)
index 61ec52b..02e0341 100644 (file)
@@ -39,6 +39,22 @@ def test_base_config():
     assert dm._name == 'dummy'
 
 
+def test_base_path():
+    gcdummy = BoolOption('dummy', 'dummy', default=False)
+    descr = OptionDescription('tiramisu', '', [gcdummy])
+    cfg = Config(descr)
+    assert cfg._impl_path is None
+    base = OptionDescription('config', '', [descr])
+    cfg = Config(base)
+    assert cfg._impl_path is None
+    assert cfg.tiramisu._impl_path == 'tiramisu'
+    nbase = OptionDescription('baseconfig', '', [base])
+    cfg = Config(nbase)
+    assert cfg._impl_path is None
+    assert cfg.config._impl_path == 'config'
+    assert cfg.config.tiramisu._impl_path == 'config.tiramisu'
+
+
 def test_reset_value():
     descr = make_description()
     cfg = Config(descr)
index f20f4dd..304d227 100644 (file)
@@ -164,3 +164,9 @@ def test_not_meta():
     meta.set_contexts('od1.i1', 7)
     assert conf1.od1.i1 == conf2.od1.i1 == 7
     assert conf1.getowner('od1.i1') is conf2.getowner('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 4dc37e8..0266855 100644 (file)
@@ -494,7 +494,7 @@ def test_callback_hidden():
     od2 = OptionDescription('od2', '', [opt2])
     maconfig = OptionDescription('rootconfig', '', [od1, od2])
     cfg = Config(maconfig)
-    cfg.cfgimpl_get_settings().set_permissive(('hidden',))
+    cfg.cfgimpl_get_settings().setpermissive(('hidden',))
     cfg.read_write()
     raises(PropertiesOptionError, 'cfg.od1.opt1')
     cfg.od2.opt2
index 979a79e..70332d2 100644 (file)
@@ -333,15 +333,15 @@ def test_reset_properties():
     setting.reset()
     assert setting._p_.get_properties(cfg) == {}
     setting[option].append('test')
-    assert setting._p_.get_properties(cfg) == {option: set(('test',))}
+    assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
     setting.reset()
-    assert setting._p_.get_properties(cfg) == {option: set(('test',))}
+    assert setting._p_.get_properties(cfg) == {'gc.dummy': set(('test',))}
     setting.append('frozen')
-    assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))}
+    assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), 'gc.dummy': set(('test',))}
     setting.reset(option)
     assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator'))}
     setting[option].append('test')
-    assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), option: set(('test',))}
+    assert setting._p_.get_properties(cfg) == {None: set(('frozen', 'expire', 'validator')), 'gc.dummy': set(('test',))}
     setting.reset(all_properties=True)
     assert setting._p_.get_properties(cfg) == {}
     raises(ValueError, 'setting.reset(all_properties=True, opt=option)')
index 783afde..cd9b434 100644 (file)
@@ -21,7 +21,7 @@ def test_permissive():
     except PropertiesOptionError, err:
         props = err.proptype
     assert props == ['disabled']
-    setting.set_permissive(('disabled',))
+    setting.setpermissive(('disabled',))
     props = []
     try:
         config.u1
@@ -50,7 +50,7 @@ def test_permissive_mandatory():
     except PropertiesOptionError, err:
         props = err.proptype
     assert props == ['disabled', 'mandatory']
-    setting.set_permissive(('mandatory', 'disabled',))
+    setting.setpermissive(('mandatory', 'disabled',))
     setting.append('permissive')
     config.u1
     setting.remove('permissive')
@@ -66,7 +66,7 @@ def test_permissive_frozen():
     config = Config(descr)
     setting = config.cfgimpl_get_settings()
     config.read_write()
-    setting.set_permissive(('frozen', 'disabled',))
+    setting.setpermissive(('frozen', 'disabled',))
     try:
         config.u1 = 1
     except PropertiesOptionError, err:
index abfaa01..269493e 100644 (file)
@@ -35,15 +35,16 @@ def gen_id(config):
 
 class SubConfig(BaseInformation):
     "sub configuration management entry"
-    __slots__ = ('_impl_context', '_impl_descr')
+    __slots__ = ('_impl_context', '_impl_descr', '_impl_path')
 
-    def __init__(self, descr, context):
+    def __init__(self, descr, context, subpath=None):
         """ Configuration option management master class
 
         :param descr: describes the configuration schema
         :type descr: an instance of ``option.OptionDescription``
         :param context: the current root config
         :type context: `Config`
+        :type subpath: `str` with the path name
         """
         # main option description
         if not isinstance(descr, OptionDescription):
@@ -54,6 +55,7 @@ class SubConfig(BaseInformation):
         if not isinstance(context, SubConfig):
             raise ValueError('context must be a SubConfig')
         self._impl_context = context
+        self._impl_path = subpath
 
     def cfgimpl_reset_cache(self, only_expired=False, only=('values',
                                                             'settings')):
@@ -183,7 +185,11 @@ class SubConfig(BaseInformation):
             return homeconfig.__setattr__(name, value)
         child = getattr(self.cfgimpl_get_description(), name)
         if not isinstance(child, SymLinkOption):
-            self.cfgimpl_get_values().setitem(child, value,
+            if self._impl_path is None:
+                path = name
+            else:
+                path = self._impl_path + '.' + name
+            self.cfgimpl_get_values().setitem(child, value, path,
                                               force_permissive=force_permissive)
         else:
             context = self.cfgimpl_get_context()
@@ -193,7 +199,7 @@ class SubConfig(BaseInformation):
 
     def __delattr__(self, name):
         child = getattr(self.cfgimpl_get_description(), name)
-        del(self.cfgimpl_get_values()[child])
+        self.cfgimpl_get_values().__delitem__(child)
 
     def __getattr__(self, name):
         return self._getattr(name)
@@ -222,6 +228,10 @@ class SubConfig(BaseInformation):
             return object.__getattribute__(self, name)
         opt_or_descr = getattr(self.cfgimpl_get_description(), name)
         # symlink options
+        if self._impl_path is None:
+            subpath = name
+        else:
+            subpath = self._impl_path + '.' + name
         if isinstance(opt_or_descr, SymLinkOption):
             context = self.cfgimpl_get_context()
             path = context.cfgimpl_get_description().impl_get_path_by_opt(
@@ -231,12 +241,13 @@ class SubConfig(BaseInformation):
                                     force_permissive=force_permissive)
         elif isinstance(opt_or_descr, OptionDescription):
             self.cfgimpl_get_settings().validate_properties(
-                opt_or_descr, True, False, force_permissive=force_permissive,
+                opt_or_descr, True, False, path=subpath,
+                force_permissive=force_permissive,
                 force_properties=force_properties)
-            return SubConfig(opt_or_descr, self.cfgimpl_get_context())
+            return SubConfig(opt_or_descr, self.cfgimpl_get_context(), subpath)
         else:
             return self.cfgimpl_get_values().getitem(
-                opt_or_descr,
+                opt_or_descr, path=subpath,
                 validate=validate,
                 force_properties=force_properties,
                 force_permissive=force_permissive)
@@ -555,6 +566,7 @@ class MetaConfig(CommonConfig):
         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):
index f0e4d84..0b87fbe 100644 (file)
@@ -152,24 +152,25 @@ populate_multitypes()
 
 class Property(object):
     "a property is responsible of the option's value access rules"
-    __slots__ = ('_setting', '_properties', '_opt')
+    __slots__ = ('_setting', '_properties', '_opt', '_path')
 
-    def __init__(self, setting, prop, opt=None):
+    def __init__(self, setting, prop, opt=None, path=None):
         self._opt = opt
+        self._path = path
         self._setting = setting
         self._properties = prop
 
     def append(self, propname):
         self._properties.add(propname)
-        self._setting._setproperties(self._properties, self._opt)
+        self._setting._setproperties(self._properties, self._opt, self._path)
 
     def remove(self, propname):
         if propname in self._properties:
             self._properties.remove(propname)
-            self._setting._setproperties(self._properties, self._opt)
+            self._setting._setproperties(self._properties, self._opt, self._path)
 
     def reset(self):
-        self._setting.reset(opt=self._opt)
+        self._setting.reset(path=self._path)
 
     def __contains__(self, propname):
         return propname in self._properties
@@ -200,15 +201,6 @@ class Settings(object):
         self._p_ = __import__(import_lib, globals(), locals(), ['Settings'],
                               -1).Settings(storage)
 
-    def _getkey(self, opt):
-        if self._p_.key_is_path:
-            if opt is None:
-                return '_none'
-            else:
-                return self._get_opt_path(opt)
-        else:
-            return opt
-
     #____________________________________________________________
     # properties methods
     def __contains__(self, propname):
@@ -219,7 +211,14 @@ class Settings(object):
         return str(list(self._getproperties()))
 
     def __getitem__(self, opt):
-        return Property(self, self._getproperties(opt), opt)
+        if opt is None:
+            path = None
+        else:
+            path = self._get_opt_path(opt)
+        return self._getitem(opt, path)
+
+    def _getitem(self, opt, path):
+        return Property(self, self._getproperties(opt, path), opt, path)
 
     def __setitem__(self, opt, value):
         raise ValueError('you must only append/remove properties')
@@ -231,26 +230,32 @@ class Settings(object):
         if all_properties:
             self._p_.reset_all_propertives()
         else:
-            self._p_.reset_properties(self._getkey(opt))
+            if opt is None:
+                path = None
+            else:
+                path = self._get_opt_path(opt)
+            self._p_.reset_properties(path)
         self.context.cfgimpl_reset_cache()
 
-    def _getproperties(self, opt=None, is_apply_req=True):
+    def _getproperties(self, opt=None, path=None, is_apply_req=True):
         if opt is None:
-            props = self._p_.getproperties(self._getkey(opt), default_properties)
+            props = self._p_.getproperties(path, default_properties)
         else:
+            if path is None:
+                raise ValueError(_('if opt is not None, path should not be None in _getproperties'))
             ntime = None
-            if self._p_.hascache('property', self._getkey(opt)):
+            if self._p_.hascache('property', path):
                 ntime = time()
-                is_cached, props = self._p_.getcache('property', self._getkey(opt), ntime)
+                is_cached, props = self._p_.getcache('property', path, ntime)
                 if is_cached:
                     return props
             if is_apply_req:
-                self.apply_requires(opt)
-            props = self._p_.getproperties(self._getkey(opt), opt._properties)
+                self.apply_requires(opt, path)
+            props = self._p_.getproperties(path, opt._properties)
             if 'expire' in self:
                 if ntime is None:
                     ntime = time()
-                self._p_.setcache('property', self._getkey(opt), props, ntime + expires_time)
+                self._p_.setcache('property', path, props, ntime + expires_time)
         return props
 
     def append(self, propname):
@@ -261,21 +266,21 @@ class Settings(object):
         "deletes property propname in the Config's properties attribute"
         Property(self, self._getproperties()).remove(propname)
 
-    def _setproperties(self, properties, opt=None):
+    def _setproperties(self, properties, opt, path):
         """save properties for specified opt
         (never save properties if same has option properties)
         """
         if opt is None:
-            self._p_.setproperties(self._getkey(opt), properties)
+            self._p_.setproperties(path, properties)
         else:
             if set(opt._properties) == properties:
-                self._p_.reset_properties(self._getkey(opt))
+                self._p_.reset_properties(path)
             else:
-                self._p_.setproperties(self._getkey(opt), properties)
+                self._p_.setproperties(path, properties)
         self.context.cfgimpl_reset_cache()
 
     #____________________________________________________________
-    def validate_properties(self, opt_or_descr, is_descr, is_write,
+    def validate_properties(self, opt_or_descr, is_descr, is_write, path,
                             value=None, force_permissive=False,
                             force_properties=None):
         """
@@ -291,9 +296,9 @@ class Settings(object):
                          property)
         """
         # opt properties
-        properties = copy(self._getproperties(opt_or_descr))
+        properties = copy(self._getproperties(opt_or_descr, path))
         # remove opt permissive
-        properties -= self._p_.getpermissive(self._getkey(opt_or_descr))
+        properties -= self._p_.getpermissive(path)
         # remove global permissive if need
         self_properties = copy(self._getproperties())
         if force_permissive is True or 'permissive' in self_properties:
@@ -332,11 +337,10 @@ class Settings(object):
                                               "").format(opt_or_descr._name,
                                                          str(props)), props)
 
-    # XXX should rename it to setpermissive, but kept for retro compatibility
-    def set_permissive(self, permissive, opt=None):
+    def setpermissive(self, permissive, path=None):
         if not isinstance(permissive, tuple):
             raise TypeError(_('permissive must be a tuple'))
-        self._p_.setpermissive(self._getkey(opt), permissive)
+        self._p_.setpermissive(path, permissive)
 
     #____________________________________________________________
     def setowner(self, owner):
@@ -369,28 +373,27 @@ class Settings(object):
         else:
             self._p_.reset_all_cache('property')
 
-    def apply_requires(self, opt):
+    def apply_requires(self, opt, path):
         "carries out the jit (just in time requirements between options"
         if opt._requires is None:
             return
 
         # filters the callbacks
-        setting = Property(self, self._getproperties(opt, False), opt)
+        setting = Property(self, self._getproperties(opt, path, False), opt, path=path)
         descr = self.context.cfgimpl_get_description()
-        optpath = descr.impl_get_path_by_opt(opt)
         for requires in opt._requires:
             matches = False
             for require in requires:
                 option, expected, action, inverse, \
                     transitive, same_action = require
-                path = descr.impl_get_path_by_opt(option)
-                if path == optpath or path.startswith(optpath + '.'):
+                reqpath = self._get_opt_path(option)
+                if reqpath == path or reqpath.startswith(path + '.'):
                     raise RequirementError(_("malformed requirements "
                                              "imbrication detected for option:"
                                              " '{0}' with requirement on: "
-                                             "'{1}'").format(optpath, path))
+                                             "'{1}'").format(path, reqpath))
                 try:
-                    value = self.context._getattr(path, force_permissive=True)
+                    value = self.context._getattr(reqpath, force_permissive=True)
                 except PropertiesOptionError, err:
                     if not transitive:
                         continue
@@ -400,14 +403,14 @@ class Settings(object):
                                                  "requirement's property "
                                                  "error: "
                                                  "{1} {2}").format(opt._name,
-                                                                   path,
+                                                                   reqpath,
                                                                    properties))
                     # transitive action, force expected
                     value = expected[0]
                     inverse = False
                 except AttributeError:
                     raise AttributeError(_("required option not found: "
-                                           "{0}").format(path))
+                                           "{0}").format(reqpath))
                 if (not inverse and
                         value in expected or
                         inverse and value not in expected):
index 519c844..68a144f 100644 (file)
@@ -32,21 +32,21 @@ class Settings(Cache):
         super(Settings, self).__init__()
 
     # propertives
-    def setproperties(self, opt, properties):
-        self._properties[opt] = properties
+    def setproperties(self, path, properties):
+        self._properties[path] = properties
 
-    def getproperties(self, opt, default_properties):
-        return self._properties.get(opt, set(default_properties))
+    def getproperties(self, path, default_properties):
+        return self._properties.get(path, set(default_properties))
 
-    def hasproperties(self, opt):
-        return opt in self._properties
+    def hasproperties(self, path):
+        return path in self._properties
 
     def reset_all_propertives(self):
         self._properties.clear()
 
-    def reset_properties(self, opt):
+    def reset_properties(self, path):
         try:
-            del(self._properties[opt])
+            del(self._properties[path])
         except KeyError:
             pass
 
@@ -54,8 +54,8 @@ class Settings(Cache):
         return self._properties
 
     # permissive
-    def setpermissive(self, opt, permissive):
-        self._permissives[opt] = frozenset(permissive)
+    def setpermissive(self, path, permissive):
+        self._permissives[path] = frozenset(permissive)
 
-    def getpermissive(self, opt=None):
-        return self._permissives.get(opt, frozenset())
+    def getpermissive(self, path=None):
+        return self._permissives.get(path, frozenset())
index 09caf05..a7a135a 100644 (file)
@@ -36,22 +36,22 @@ class Cache(object):
     def __init__(self):
         self._cache = {}
 
-    def setcache(self, cache_type, opt, val, time):
-        self._cache[opt] = (val, time)
+    def setcache(self, cache_type, path, val, time):
+        self._cache[path] = (val, time)
 
-    def getcache(self, cache_type, opt, exp):
-        value, created = self._cache[opt]
+    def getcache(self, cache_type, path, exp):
+        value, created = self._cache[path]
         if exp < created:
             return True, value
         return False, None
 
-    def hascache(self, cache_type, opt):
-        """ option is in the cache
+    def hascache(self, cache_type, path):
+        """ path is in the cache
 
         :param cache_type: value | property
-        :param opt: the key (typically, the option object)
+        :param path: the path's option
         """
-        return opt in self._cache
+        return path in self._cache
 
     def reset_expired_cache(self, cache_type, exp):
         keys = self._cache.keys()
@@ -66,6 +66,6 @@ class Cache(object):
 
     def get_cached(self, cache_type, context):
         """return all values in a dictionary
-        example: {option1: ('value1', 'time1'), option2: ('value2', 'time2')}
+        example: {'path1': ('value1', 'time1'), 'path2': ('value2', 'time2')}
         """
         return self._cache
index 0f80f73..713473e 100644 (file)
@@ -32,43 +32,43 @@ class Values(Cache):
         super(Values, self).__init__()
 
     # value
-    def setvalue(self, opt, value, owner):
-        """set value for an option
+    def setvalue(self, path, value, owner):
+        """set value for a path
         a specified value must be associated to an owner
         """
-        self._values[opt] = (owner, value)
+        self._values[path] = (owner, value)
 
-    def getvalue(self, opt):
-        """get value for an option
+    def getvalue(self, path):
+        """get value for a path
         return: only value, not the owner
         """
-        return self._values[opt][1]
+        return self._values[path][1]
 
-    def hasvalue(self, opt):
-        """if opt has a value
+    def hasvalue(self, path):
+        """if path has a value
         return: boolean
         """
-        return opt in self._values
+        return path in self._values
 
-    def resetvalue(self, opt):
+    def resetvalue(self, path):
         """remove value means delete value in storage
         """
-        del(self._values[opt])
+        del(self._values[path])
 
     def get_modified_values(self):
         """return all values in a dictionary
-        example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
+        example: {'path1': (owner, 'value1'), 'path2': (owner, 'value2')}
         """
         return self._values
 
     # owner
-    def setowner(self, opt, owner):
-        """change owner for an option
+    def setowner(self, path, owner):
+        """change owner for a path
         """
-        self._values[opt] = (owner, self._values[opt][1])
+        self._values[path] = (owner, self._values[path][1])
 
-    def getowner(self, opt, default):
-        """get owner for an option
+    def getowner(self, path, default):
+        """get owner for a path
         return: owner object
         """
-        return self._values.get(opt, (default, None))[0]
+        return self._values.get(path, (default, None))[0]
index 99d6d7f..f2cbdf3 100644 (file)
@@ -46,15 +46,6 @@ class Values(object):
         self._p_ = __import__(import_lib, globals(), locals(), ['Values'],
                               -1).Values(storage)
 
-    def _getkey(self, opt):
-        """depends on the storage utility.
-        typically, the option's path in the parent `Config` or `SubConfig`
-        """
-        if self._p_.key_is_path:
-            return self._get_opt_path(opt)
-        else:
-            return opt
-
     def _getdefault(self, opt):
         """
         actually retrieves the default value
@@ -71,24 +62,23 @@ class Values(object):
         else:
             return value
 
-    def _getvalue(self, opt, validate=True):
+    def _getvalue(self, opt, path, validate=True):
         """actually retrieves the value
 
         :param opt: the `option.Option()` object
         :returns: the option's value (or the default value if not set)
         """
-        key = self._getkey(opt)
-        if not self._p_.hasvalue(key):
+        if not self._p_.hasvalue(path):
             # if there is no value
             value = self._getdefault(opt)
             if opt.impl_is_multi():
-                value = Multi(value, self.context, opt, validate)
+                value = Multi(value, self.context, opt, path, validate)
         else:
             # if there is a value
-            value = self._p_.getvalue(key)
+            value = self._p_.getvalue(path)
             if opt.impl_is_multi() and not isinstance(value, Multi):
                 # load value so don't need to validate if is not a Multi
-                value = Multi(value, self.context, opt, validate=False)
+                value = Multi(value, self.context, opt, path, validate=False)
         return value
 
     def get_modified_values(self):
@@ -101,15 +91,20 @@ class Values(object):
 
         :param opt: the `option.Option()` object
         """
-        return self._p_.hasvalue('value', self._getkey(opt))
+        path = self._get_opt_path(opt)
+        self._contains(path)
+
+    def _contains(self, path):
+        return self._p_.hasvalue('value', path)
 
     def __delitem__(self, opt):
         """overrides the builtins `del()` instructions"""
         self.reset(opt)
 
-    def reset(self, opt):
-        key = self._getkey(opt)
-        if self._p_.hasvalue(key):
+    def reset(self, opt, path=None):
+        if path is None:
+            path = self._get_opt_path(opt)
+        if self._p_.hasvalue(path):
             setting = self.context.cfgimpl_get_settings()
             opt.impl_validate(opt.impl_getdefault(), self.context,
                               'validator' in setting)
@@ -118,7 +113,7 @@ class Values(object):
                     opt.impl_get_multitype() == multitypes.master):
                 for slave in opt.impl_get_master_slaves():
                     self.reset(slave)
-            self._p_.resetvalue(key)
+            self._p_.resetvalue(path)
 
     def _isempty(self, opt, value):
         "convenience method to know if an option is empty"
@@ -150,30 +145,31 @@ class Values(object):
         "enables us to use the pythonic dictionnary-like access to values"
         return self.getitem(opt)
 
-    def getitem(self, opt, validate=True, force_permissive=False,
+    def getitem(self, opt, path=None, validate=True, force_permissive=False,
                 force_properties=None, validate_properties=True):
         ntime = None
-        key = self._getkey(opt)
-        if self._p_.hascache('value', self._getkey(opt)):
+        if path is None:
+            path = self._get_opt_path(opt)
+        if self._p_.hascache('value', path):
             ntime = time()
-            is_cached, value = self._p_.getcache('value', key, ntime)
+            is_cached, value = self._p_.getcache('value', path, ntime)
             if is_cached:
                 if opt.impl_is_multi() and not isinstance(value, Multi):
                     #load value so don't need to validate if is not a Multi
-                    value = Multi(value, self.context, opt, validate=False)
+                    value = Multi(value, self.context, opt, path, validate=False)
                 return value
-        val = self._getitem(opt, validate, force_permissive, force_properties,
+        val = self._getitem(opt, path, validate, force_permissive, force_properties,
                             validate_properties)
         if 'expire' in self.context.cfgimpl_get_settings() and validate and \
                 validate_properties and force_permissive is False and \
                 force_properties is None:
             if ntime is None:
                 ntime = time()
-            self._p_.setcache('value', key, val, ntime + expires_time)
+            self._p_.setcache('value', path, val, ntime + expires_time)
 
         return val
 
-    def _getitem(self, opt, validate, force_permissive, force_properties,
+    def _getitem(self, opt, path, validate, force_permissive, force_properties,
                  validate_properties):
         # options with callbacks
         setting = self.context.cfgimpl_get_settings()
@@ -181,7 +177,7 @@ class Values(object):
         # if value is callback and is not set
         # or frozen with force_default_on_freeze
         if opt.impl_has_callback() and (
-                self.is_default_owner(opt) or
+                self._is_default_owner(path) or
                 (is_frozen and 'force_default_on_freeze' in setting[opt])):
             no_value_slave = False
             if (opt.impl_is_multi() and
@@ -200,53 +196,55 @@ class Values(object):
                     if not isinstance(value, list):
                         value = [value for i in range(lenmaster)]
             if opt.impl_is_multi():
-                value = Multi(value, self.context, opt, validate)
+                value = Multi(value, self.context, opt, path, validate)
             # suppress value if already set
-            self.reset(opt)
+            self.reset(opt, path)
         # frozen and force default
         elif is_frozen and 'force_default_on_freeze' in setting[opt]:
             value = self._getdefault(opt)
             if opt.impl_is_multi():
-                value = Multi(value, self.context, opt, validate)
+                value = Multi(value, self.context, opt, path, validate)
         else:
-            value = self._getvalue(opt, validate)
+            value = self._getvalue(opt, path, validate)
         if validate:
             opt.impl_validate(value, self.context, 'validator' in setting)
-        if self.is_default_owner(opt) and \
+        if self._is_default_owner(path) and \
                 'force_store_value' in setting[opt]:
-            self.setitem(opt, value, is_write=False)
+            self.setitem(opt, value, path, is_write=False)
         if validate_properties:
-            setting.validate_properties(opt, False, False, value=value,
+            setting.validate_properties(opt, False, False, value=value, path=path,
                                         force_permissive=force_permissive,
                                         force_properties=force_properties)
         return value
 
     def __setitem__(self, opt, value):
-        self.setitem(opt, value)
+        path = self._get_opt_path(opt)
+        self.setitem(opt, value, path)
 
-    def setitem(self, opt, value, force_permissive=False, is_write=True):
+    def setitem(self, opt, value, path, force_permissive=False,
+                is_write=True):
         # is_write is, for example, used with "force_store_value"
         # user didn't change value, so not write
         # valid opt
         opt.impl_validate(value, self.context,
                           'validator' in self.context.cfgimpl_get_settings())
         if opt.impl_is_multi() and not isinstance(value, Multi):
-            value = Multi(value, self.context, opt)
-        self._setvalue(opt, value, force_permissive=force_permissive,
+            value = Multi(value, self.context, opt, path)
+        self._setvalue(opt, path, value, force_permissive=force_permissive,
                        is_write=is_write)
 
-    def _setvalue(self, opt, value, force_permissive=False,
+    def _setvalue(self, opt, path, value, force_permissive=False,
                   force_properties=None,
                   is_write=True, validate_properties=True):
         self.context.cfgimpl_reset_cache()
         if validate_properties:
             setting = self.context.cfgimpl_get_settings()
             setting.validate_properties(opt, False, is_write,
-                                        value=value,
+                                        value=value, path=path,
                                         force_permissive=force_permissive,
                                         force_properties=force_properties)
         owner = self.context.cfgimpl_get_settings().getowner()
-        self._p_.setvalue(self._getkey(opt), value, owner)
+        self._p_.setvalue(path, value, owner)
 
     def getowner(self, opt):
         """
@@ -257,10 +255,14 @@ class Values(object):
         """
         if isinstance(opt, SymLinkOption):
             opt = opt._opt
-        owner = self._p_.getowner(self._getkey(opt), owners.default)
+        path = self._get_opt_path(opt)
+        return self._getowner(path)
+
+    def _getowner(self, path):
+        owner = self._p_.getowner(path, owners.default)
         meta = self.context.cfgimpl_get_meta()
         if owner is owners.default and meta is not None:
-            owner = meta.cfgimpl_get_values().getowner(opt)
+            owner = meta.cfgimpl_get_values()._getowner(path)
         return owner
 
     def setowner(self, opt, owner):
@@ -272,10 +274,15 @@ class Values(object):
         """
         if not isinstance(owner, owners.Owner):
             raise TypeError(_("invalid generic owner {0}").format(str(owner)))
-        if self.getowner(opt) == owners.default:
+
+        path = self._get_opt_path(opt)
+        self._setowner(path, owner)
+
+    def _setowner(self, path, owner):
+        if self._getowner(path) == owners.default:
             raise ConfigError(_('no value for {0} cannot change owner to {1}'
-                                '').format(opt._name, owner))
-        self._p_.setowner(self._getkey(opt), owner)
+                                '').format(path, owner))
+        self._p_.setowner(path, owner)
 
     def is_default_owner(self, opt):
         """
@@ -283,7 +290,11 @@ class Values(object):
                        (not the toplevel config)
         :return: boolean
         """
-        return self.getowner(opt) == owners.default
+        path = self._get_opt_path(opt)
+        return self._is_default_owner(path)
+
+    def _is_default_owner(self, path):
+        return self._getowner(path) == owners.default
 
     def reset_cache(self, only_expired):
         """
@@ -310,15 +321,16 @@ class Values(object):
 class Multi(list):
     """multi options values container
     that support item notation for the values of multi options"""
-    __slots__ = ('opt', 'context')
+    __slots__ = ('opt', 'path', 'context')
 
-    def __init__(self, value, context, opt, validate=True):
+    def __init__(self, value, context, opt, path, validate=True):
         """
         :param value: the Multi wraps a list value
         :param context: the home config that has the values
         :param opt: the option object that have this Multi value
         """
         self.opt = opt
+        self.path = path
         self.context = context
         if not isinstance(value, list):
             value = [value]
@@ -337,7 +349,7 @@ class Multi(list):
         valuelen = len(value)
         if valuelen > masterlen or (valuelen < masterlen and
                                     not self.context.cfgimpl_get_values(
-                                    ).is_default_owner(self.opt)):
+                                    )._is_default_owner(self.path)):
             raise SlaveError(_("invalid len for the slave: {0}"
                                " which has {1} as master").format(
                                    self.opt._name, masterp))
@@ -351,8 +363,9 @@ class Multi(list):
         masterlen = len(value)
         values = self.context.cfgimpl_get_values()
         for slave in self.opt._master_slaves:
-            if not values.is_default_owner(slave):
-                value_slave = values._getvalue(slave)
+            path = values._get_opt_path(slave)
+            if not values._is_default_owner(path):
+                value_slave = values._getvalue(slave, path)
                 if len(value_slave) > masterlen:
                     raise SlaveError(_("invalid len for the master: {0}"
                                        " which has {1} as slave with"
@@ -363,11 +376,11 @@ class Multi(list):
                         value_slave.append(slave.impl_getdefault_multi(),
                                            force=True)
 
-    def __setitem__(self, key, value):
+    def __setitem__(self, path, value):
         self._validate(value)
         #assume not checking mandatory property
-        super(Multi, self).__setitem__(key, value)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self)
+        super(Multi, self).__setitem__(path, value)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, path, self)
 
     def append(self, value, force=False):
         """the list value can be updated (appened)
@@ -386,21 +399,26 @@ class Multi(list):
                         value = None
         self._validate(value)
         super(Multi, self).append(value)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
         if not force and self.opt.impl_get_multitype() == multitypes.master:
             for slave in self.opt.impl_get_master_slaves():
-                if not values.is_default_owner(slave):
+                path = values._get_opt_path(slave)
+                if not values._is_default_owner(path):
                     if slave.impl_has_callback():
                         index = self.__len__() - 1
                         dvalue = values._getcallback_value(slave, index=index)
                     else:
                         dvalue = slave.impl_getdefault_multi()
-                    old_value = values.getitem(slave, validate_properties=False)
+                    old_value = values.getitem(slave, path,
+                                               validate_properties=False)
                     if len(old_value) < self.__len__():
-                        values.getitem(slave, validate_properties=False).append(
-                            dvalue, force=True)
+                        values.getitem(slave, path,
+                                       validate_properties=False).append(
+                                           dvalue, force=True)
                     else:
-                        values.getitem(slave, validate_properties=False)[index] = dvalue
+                        values.getitem(slave, path,
+                                       validate_properties=False)[
+                                           index] = dvalue
 
     def sort(self, cmp=None, key=None, reverse=False):
         if self.opt.impl_get_multitype() in [multitypes.slave,
@@ -408,7 +426,7 @@ class Multi(list):
             raise SlaveError(_("cannot sort multi option {0} if master or slave"
                                "").format(self.opt._name))
         super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
 
     def reverse(self):
         if self.opt.impl_get_multitype() in [multitypes.slave,
@@ -416,7 +434,7 @@ class Multi(list):
             raise SlaveError(_("cannot reverse multi option {0} if master or "
                                "slave").format(self.opt._name))
         super(Multi, self).reverse()
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
 
     def insert(self, index, obj):
         if self.opt.impl_get_multitype() in [multitypes.slave,
@@ -424,7 +442,7 @@ class Multi(list):
             raise SlaveError(_("cannot insert multi option {0} if master or "
                                "slave").format(self.opt._name))
         super(Multi, self).insert(index, obj)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
 
     def extend(self, iterable):
         if self.opt.impl_get_multitype() in [multitypes.slave,
@@ -432,7 +450,7 @@ class Multi(list):
             raise SlaveError(_("cannot extend multi option {0} if master or "
                                "slave").format(self.opt._name))
         super(Multi, self).extend(iterable)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self)
 
     def _validate(self, value):
         if value is not None:
@@ -465,5 +483,5 @@ class Multi(list):
                                        ).pop(key, force=True)
         #set value without valid properties
         ret = super(Multi, self).pop(key)
-        self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
+        self.context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
         return ret