From 798759d2b3974eaa7afbaab7c9678e8f66dc1be6 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 21 Jul 2016 19:49:32 -0700 Subject: fix content view cache invalidation --- mitmproxy/console/flowview.py | 14 ++++++++++---- netlib/http/message.py | 6 ------ netlib/multidict.py | 6 +++--- test/netlib/http/test_message.py | 4 ---- test/netlib/test_multidict.py | 14 +++++++++++++- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/mitmproxy/console/flowview.py b/mitmproxy/console/flowview.py index ac9570ff..789066fc 100644 --- a/mitmproxy/console/flowview.py +++ b/mitmproxy/console/flowview.py @@ -189,15 +189,21 @@ class FlowView(tabs.Tabs): limit = sys.maxsize else: limit = contentviews.VIEW_CUTOFF + + flow_modify_cache_invalidation = hash(( + message.raw_content, + message.headers.fields, + getattr(message, "path", None), + )) return cache.get( - self._get_content_view, + # We move message into this partial function as it is not hashable. + lambda *args: self._get_content_view(message, *args), viewmode, - message, limit, - message # Cache invalidation + flow_modify_cache_invalidation ) - def _get_content_view(self, viewmode, message, max_lines, _): + def _get_content_view(self, message, viewmode, max_lines, _): try: content = message.content diff --git a/netlib/http/message.py b/netlib/http/message.py index 34709f0a..a86e7489 100644 --- a/netlib/http/message.py +++ b/netlib/http/message.py @@ -32,9 +32,6 @@ class MessageData(basetypes.Serializable): def __ne__(self, other): return not self.__eq__(other) - def __hash__(self): - return hash(frozenset(self.__dict__.items())) - def set_state(self, state): for k, v in state.items(): if k == "headers": @@ -77,9 +74,6 @@ class Message(basetypes.Serializable): def __ne__(self, other): return not self.__eq__(other) - def __hash__(self): - return hash(self.data) ^ 1 - def get_state(self): return self.data.get_state() diff --git a/netlib/multidict.py b/netlib/multidict.py index 51053ff6..e9fec155 100644 --- a/netlib/multidict.py +++ b/netlib/multidict.py @@ -79,9 +79,6 @@ class _MultiDict(MutableMapping, basetypes.Serializable): def __ne__(self, other): return not self.__eq__(other) - def __hash__(self): - return hash(self.fields) - def get_all(self, key): """ Return the list of all values for a given key. @@ -241,6 +238,9 @@ class ImmutableMultiDict(MultiDict): __delitem__ = set_all = insert = _immutable + def __hash__(self): + return hash(self.fields) + def with_delitem(self, key): """ Returns: diff --git a/test/netlib/http/test_message.py b/test/netlib/http/test_message.py index deebd6f2..7f93830e 100644 --- a/test/netlib/http/test_message.py +++ b/test/netlib/http/test_message.py @@ -71,10 +71,6 @@ class TestMessage(object): assert resp != 0 - def test_hash(self): - resp = tresp() - assert hash(resp) - def test_serializable(self): resp = tresp() resp2 = http.Response.from_state(resp.get_state()) diff --git a/test/netlib/test_multidict.py b/test/netlib/test_multidict.py index 038441e7..58ae0f98 100644 --- a/test/netlib/test_multidict.py +++ b/test/netlib/test_multidict.py @@ -45,7 +45,7 @@ class TestMultiDict(object): assert md["foo"] == "bar" with tutils.raises(KeyError): - md["bar"] + assert md["bar"] md_multi = TMultiDict( [("foo", "a"), ("foo", "b")] @@ -101,6 +101,15 @@ class TestMultiDict(object): assert TMultiDict() != self._multi() assert TMultiDict() != 42 + def test_hash(self): + """ + If a class defines mutable objects and implements an __eq__() method, + it should not implement __hash__(), since the implementation of hashable + collections requires that a key's hash value is immutable. + """ + with tutils.raises(TypeError): + assert hash(TMultiDict()) + def test_get_all(self): md = self._multi() assert md.get_all("foo") == ["bar"] @@ -197,6 +206,9 @@ class TestImmutableMultiDict(object): with tutils.raises(TypeError): md.add("foo", "bar") + def test_hash(self): + assert hash(TImmutableMultiDict()) + def test_with_delitem(self): md = TImmutableMultiDict([("foo", "bar")]) assert md.with_delitem("foo").fields == () -- cgit v1.2.3