[tor-commits] [stem/master] Dropping direct __dict__ usage

atagar at torproject.org atagar at torproject.org
Sat Feb 2 18:20:49 UTC 2013


commit cc3f1be711665ab203f8a657a8400e2828bb9aef
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Jan 27 13:41:01 2013 -0800

    Dropping direct __dict__ usage
    
    Using an object's __dict__ attribute is generally thought to be a bad idea, and
    indeed it bites us from time to time. Functions like hasattr(), getattr(),
    setattr(), and vars() makes direct __dict__ usage unnecessary. This also fixes
    a python 3 mocking issue...
    
    ======================================================================
    ERROR: test_examples
    ----------------------------------------------------------------------
    Traceback:
      File "/home/atagar/Desktop/stem/test/data/python3/test/unit/descriptor/networkstatus/document_v3.py", line 129, in test_examples
        with support_with(io.StringIO(content)) as consensus_file:
      File "/home/atagar/Desktop/stem/test/data/python3/test/mocking.py", line 303, in support_with
        obj.__dict__["__enter__"] = return_value(obj)
    AttributeError: '_io.StringIO' object has no attribute '__dict__'
---
 stem/util/enum.py                           |    6 ++--
 test/mocking.py                             |   28 ++++++++++++++------------
 test/unit/descriptor/router_status_entry.py |    4 +-
 3 files changed, 20 insertions(+), 18 deletions(-)

diff --git a/stem/util/enum.py b/stem/util/enum.py
index 9614ee8..4f6d59a 100644
--- a/stem/util/enum.py
+++ b/stem/util/enum.py
@@ -80,7 +80,7 @@ class Enum(object):
 
       keys.append(key)
       values.append(val)
-      self.__dict__[key] = val
+      setattr(self, key, val)
 
     self._keys = tuple(keys)
     self._values = tuple(values)
@@ -156,8 +156,8 @@ class Enum(object):
     :raises: **ValueError** if the key doesn't exist
     """
 
-    if item in self.__dict__:
-      return self.__dict__[item]
+    if item in vars(self):
+      return getattr(self, item)
     else:
       keys = ", ".join(self.keys())
       raise ValueError("'%s' isn't among our enumeration keys, which includes: %s" % (item, keys))
diff --git a/test/mocking.py b/test/mocking.py
index c2baffb..ea88992 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -300,8 +300,12 @@ def support_with(obj):
   :returns: input object
   """
 
-  obj.__dict__["__enter__"] = return_value(obj)
-  obj.__dict__["__exit__"] = no_op()
+  if not hasattr(obj, "__enter__"):
+    setattr(obj, "__enter__", return_value(obj))
+
+  if not hasattr(obj, "__exit__"):
+    setattr(obj, "__exit__", no_op())
+
   return obj
 
 
@@ -320,9 +324,9 @@ def mock(target, mock_call, target_module=None):
   :param module target_module: module that this is mocking, this defaults to the inspected value
   """
 
-  if hasattr(target, "__dict__") and "mock_id" in target.__dict__:
+  if hasattr(target, "mock_id"):
     # we're overriding an already mocked function
-    mocking_id = target.__dict__["mock_id"]
+    mocking_id = getattr(target, "mock_id")
     target_module, target_function, _ = MOCK_STATE[mocking_id]
   else:
     # this is a new mocking, save the original state
@@ -332,13 +336,11 @@ def mock(target, mock_call, target_module=None):
     MOCK_STATE[mocking_id] = (target_module, target_function, target)
 
   mock_wrapper = lambda *args, **kwargs: mock_call(*args, **kwargs)
-  mock_wrapper.__dict__["mock_id"] = mocking_id
+  setattr(mock_wrapper, "mock_id", mocking_id)
 
   # mocks the function with this wrapper
-  if hasattr(target, "__dict__"):
-    target_module.__dict__[target_function] = mock_wrapper
-  else:
-    setattr(target_module, target.__name__, mock_call)
+
+  setattr(target_module, target_function, mock_wrapper)
 
 
 def mock_method(target_class, method_name, mock_call):
@@ -371,7 +373,7 @@ def mock_method(target_class, method_name, mock_call):
 
   target_method = getattr(target_class, method_name)
 
-  if "mock_id" in target_method.__dict__:
+  if hasattr(target_method, "mock_id"):
     # we're overriding an already mocked method
     mocking_id = target_method.mock_id
     _, target_method, _ = MOCK_STATE[mocking_id]
@@ -431,8 +433,8 @@ def get_real_function(function):
   :returns: original implementation of the function
   """
 
-  if "mock_id" in function.__dict__:
-    mocking_id = function.__dict__["mock_id"]
+  if hasattr(function, "mock_id"):
+    mocking_id = getattr(function, "mock_id")
     return MOCK_STATE[mocking_id][2]
   else:
     return function
@@ -545,7 +547,7 @@ def get_protocolinfo_response(**attributes):
   stem.response.convert("PROTOCOLINFO", protocolinfo_response)
 
   for attr in attributes:
-    protocolinfo_response.__dict__[attr] = attributes[attr]
+    setattr(protocolinfo_response, attr, attributes[attr])
 
   return protocolinfo_response
 
diff --git a/test/unit/descriptor/router_status_entry.py b/test/unit/descriptor/router_status_entry.py
index 3f27663..21795f2 100644
--- a/test/unit/descriptor/router_status_entry.py
+++ b/test/unit/descriptor/router_status_entry.py
@@ -477,8 +477,8 @@ class TestRouterStatusEntry(unittest.TestCase):
 
     # we need a document that's a vote
     mock_document = lambda x: x  # just need anything with a __dict__
-    mock_document.__dict__["is_vote"] = True
-    mock_document.__dict__["is_consensus"] = False
+    setattr(mock_document, "is_vote", True)
+    setattr(mock_document, "is_consensus", False)
 
     for m_line, expected in test_values.items():
       content = get_router_status_entry_v3({'m': m_line}, content = True)





More information about the tor-commits mailing list