
commit cc3f1be711665ab203f8a657a8400e2828bb9aef Author: Damian Johnson <atagar@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)