[CalendarServer-changes] [4423] CalendarServer/branches/config-separation/twistedcaldav

source_changes at macosforge.org source_changes at macosforge.org
Thu Jul 2 17:15:00 PDT 2009


Revision: 4423
          http://trac.macosforge.org/projects/calendarserver/changeset/4423
Author:   wsanchez at apple.com
Date:     2009-07-02 17:15:00 -0700 (Thu, 02 Jul 2009)
Log Message:
-----------
Let's better define and test ConfigDict:

 ?\226?\128?\162 It was missing __delattr__; added.
 ?\226?\128?\162 It was calling dict.__getattr__ which apparently doesn't exist; call __getattribute__ instead.
 ?\226?\128?\162 Keys may not start with "_", but attributes can; add more checks.

Tests added for the above.

Modified Paths:
--------------
    CalendarServer/branches/config-separation/twistedcaldav/config.py
    CalendarServer/branches/config-separation/twistedcaldav/test/test_config.py

Modified: CalendarServer/branches/config-separation/twistedcaldav/config.py
===================================================================
--- CalendarServer/branches/config-separation/twistedcaldav/config.py	2009-07-02 22:44:29 UTC (rev 4422)
+++ CalendarServer/branches/config-separation/twistedcaldav/config.py	2009-07-03 00:15:00 UTC (rev 4423)
@@ -31,6 +31,13 @@
     """
 
 class ConfigDict(dict):
+    """
+    Dictionary which can be accessed using attribute syntax, because
+    that reads an writes nicer in code.  For example:
+      C{config.Thingo.Tiny.Tweak}
+    instead of:
+      C{config.["Thingo"]["Tiny"]["Tweak"]}
+    """
     def __init__(self, mapping=None):
         if mapping is not None:
             for key, value in mapping.iteritems():
@@ -40,27 +47,36 @@
         return "*" + dict.__repr__(self)
 
     def __setitem__(self, key, value):
+        if key.startswith("_"):
+            # Names beginning with "_" are reserved for real attributes
+            raise KeyError("Keys may not begin with '_': %s" % (key,))
+
         if isinstance(value, dict) and not isinstance(value, self.__class__):
             dict.__setitem__(self, key, self.__class__(value))
         else:
             dict.__setitem__(self, key, value)
 
     def __setattr__(self, attr, value):
-        if attr[0] == "_":
+        if attr.startswith("_"):
             dict.__setattr__(self, attr, value)
         else:
             self[attr] = value
 
     def __getattr__(self, attr):
-        if attr in self:
+        if not attr.startswith("_") and attr in self:
             return self[attr]
         else:
-            return dict.__getattr__(self, attr)
+            return dict.__getattribute__(self, attr)
 
+    def __delattr__(self, attr):
+        if not attr.startswith("_") and attr in self:
+            del self[attr]
+        else:
+            dict.__delattr__(self, attr)
 
 class ConfigProvider(object):
     """Configuration provider, abstraction for config storage/format/defaults"""
-    
+
     def __init__(self, defaults=None):
         """Create configuration provider with given defaults"""
         self._configFileName = None

Modified: CalendarServer/branches/config-separation/twistedcaldav/test/test_config.py
===================================================================
--- CalendarServer/branches/config-separation/twistedcaldav/test/test_config.py	2009-07-02 22:44:29 UTC (rev 4422)
+++ CalendarServer/branches/config-separation/twistedcaldav/test/test_config.py	2009-07-03 00:15:00 UTC (rev 4423)
@@ -17,7 +17,7 @@
 from twext.python.plistlib import writePlist
 
 from twistedcaldav.log import logLevelForNamespace
-from twistedcaldav.config import config, ConfigProvider
+from twistedcaldav.config import config, ConfigDict, ConfigProvider
 from twistedcaldav.static import CalDAVFile
 from twistedcaldav.stdconfig import DEFAULT_CONFIG, PListConfigProvider
 from twistedcaldav.test.util import TestCase
@@ -248,3 +248,52 @@
 
         self.assertEquals(logLevelForNamespace(None), "warn")
         self.assertEquals(logLevelForNamespace("some.namespace"), "warn")
+
+    def test_ConfigDict(self):
+        configDict = ConfigDict({
+            "a": "A",
+            "b": "B",
+            "c": "C",
+        })
+
+        # Test either syntax inbound
+        configDict["d"] = "D"
+        configDict.e = "E"
+
+        # Test either syntax outbound
+        for key in "abcde":
+            value = key.upper()
+
+            self.assertEquals(configDict[key], value)
+            self.assertEquals(configDict.get(key), value)
+            self.assertEquals(getattr(configDict, key), value)
+
+            self.assertIn(key, configDict)
+            self.assertTrue(hasattr(configDict, key))
+
+        self.assertEquals(configDict.a, "A")
+        self.assertEquals(configDict.d, "D")
+        self.assertEquals(configDict.e, "E")
+
+        # Test either syntax for delete
+        del configDict["d"]
+        delattr(configDict, "e")
+
+        # Test either syntax for absence
+        for key in "de":
+            self.assertNotIn(key, configDict)
+            self.assertFalse(hasattr(configDict, key))
+            self.assertRaises(KeyError, lambda: configDict[key])
+            self.assertRaises(AttributeError, getattr, configDict, key)
+
+        self.assertRaises(AttributeError, lambda: configDict.e)
+        self.assertRaises(AttributeError, lambda: configDict.f)
+
+        # Keys may not begin with "_" in dict syntax
+        def set():
+            configDict["_x"] = "X"
+        self.assertRaises(KeyError, set)
+
+        # But attr syntax is OK
+        configDict._x = "X"
+        self.assertEquals(configDict._x, "X")
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20090702/f8fadde7/attachment-0001.html>


More information about the calendarserver-changes mailing list