浏览代码

disallow setting unknown attributes, use StableDict as .as_dict() result

Thomas Waldmann 9 年之前
父节点
当前提交
e6cf4ee627
共有 2 个文件被更改,包括 14 次插入1 次删除
  1. 5 1
      borg/item.py
  2. 9 0
      borg/testsuite/item.py

+ 5 - 1
borg/item.py

@@ -17,6 +17,8 @@ class PropDict:
     """
     VALID_KEYS = None  # override with <set of str> in child class
 
+    __slots__ = ("_dict", )  # avoid setting attributes not supported by properties
+
     def __init__(self, data_dict=None, **kw):
         if data_dict is None:
             data = kw
@@ -39,7 +41,7 @@ class PropDict:
 
     def as_dict(self):
         """return the internal dictionary"""
-        return self._dict  # XXX use StableDict?
+        return StableDict(self._dict)
 
     def _check_key(self, key):
         """make sure key is of type str and known"""
@@ -108,6 +110,8 @@ class Item(PropDict):
 
     VALID_KEYS = set(key.decode() for key in ITEM_KEYS)  # we want str-typed keys
 
+    __slots__ = ("_dict", )  # avoid setting attributes not supported by properties
+
     # properties statically defined, so that IDEs can know their names:
 
     path = PropDict._make_property('path', str, 'surrogate-escaped str', encode=safe_encode, decode=safe_decode)

+ 9 - 0
borg/testsuite/item.py

@@ -136,3 +136,12 @@ def test_item_dict_property():
     item.xattrs['bar'] = 'baz'
     assert item.xattrs == StableDict({'foo': 'bar', 'bar': 'baz'})
     assert item.as_dict() == {'xattrs': {'foo': 'bar', 'bar': 'baz'}}
+
+
+def test_unknown_property():
+    # we do not want the user to be able to set unknown attributes -
+    # they won't get into the .as_dict() result dictionary.
+    # also they might be just typos of known attributes.
+    item = Item()
+    with pytest.raises(AttributeError):
+        item.unknown_attribute = None