aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/addons/view.py50
-rw-r--r--test/mitmproxy/addons/test_view.py21
2 files changed, 55 insertions, 16 deletions
diff --git a/mitmproxy/addons/view.py b/mitmproxy/addons/view.py
index 99481376..b5682b7a 100644
--- a/mitmproxy/addons/view.py
+++ b/mitmproxy/addons/view.py
@@ -34,7 +34,7 @@ class View(collections.Sequence):
self._store = {}
self.filter = matchall
self.order_key = key_request_start
- self.order_reverse = False
+ self.order_reversed = False
self._view = sortedcontainers.SortedListWithKey(key = self.order_key)
# These signals broadcast events that affect the view. That is, an
@@ -46,13 +46,42 @@ class View(collections.Sequence):
# Signals that the view should be refreshed completely
self.sig_refresh = blinker.Signal()
+ def _rev(self, idx: int) -> int:
+ """
+ Reverses an index, if needed
+ """
+ if self.order_reversed:
+ if idx < 0:
+ idx = -idx - 1
+ else:
+ idx = len(self._view) - idx - 1
+ if idx < 0:
+ raise IndexError
+ return idx
+
def __len__(self):
return len(self._view)
def __getitem__(self, offset) -> flow.Flow:
- if self.order_reverse:
- offset = -offset - 1
- return self._view[offset]
+ return self._view[self._rev(offset)]
+
+ # Reflect some methods to the efficient underlying implementation
+
+ def bisect(self, f: flow.Flow) -> int:
+ v = self._view.bisect(f)
+ # Bisect returns an item to the RIGHT of the existing entries.
+ if v == 0:
+ return v
+ return self._rev(v - 1) + 1
+
+ def index(self, f: flow.Flow) -> int:
+ return self._rev(self._view.index(f))
+
+ # API
+
+ def toggle_reversed(self):
+ self.order_reversed = not self.order_reversed
+ self.sig_refresh.send(self)
def set_order(self, order_key: typing.Callable):
"""
@@ -122,14 +151,8 @@ class View(collections.Sequence):
# The value was not in the view
pass
- # Reflect some methods to the efficient underlying implementation
- def bisect(self, f: flow.Flow) -> int:
- return self._view.bisect(f)
-
- def index(self, f: flow.Flow) -> int:
- return self._view.index(f)
-
# Event handlers
+
def request(self, f):
self.add(f)
@@ -186,9 +209,8 @@ class Focus:
def _sig_refresh(self, view):
if len(view) == 0:
self.focusflow = None
- else:
- if self.focusflow not in view:
- self.focusflow = view[0]
+ elif self.focusflow not in view:
+ self.focusflow = view[0]
def _sig_add(self, view, flow):
# We only have to act if we don't have a focus element
diff --git a/test/mitmproxy/addons/test_view.py b/test/mitmproxy/addons/test_view.py
index 527464ad..1ab7e8f4 100644
--- a/test/mitmproxy/addons/test_view.py
+++ b/test/mitmproxy/addons/test_view.py
@@ -62,16 +62,33 @@ def test_order():
v.set_order(view.key_request_method)
assert [i.request.method for i in v] == ["GET", "GET", "PUT", "PUT"]
- v.order_reverse = True
+ v.toggle_reversed()
assert [i.request.method for i in v] == ["PUT", "PUT", "GET", "GET"]
v.set_order(view.key_request_start)
assert [i.request.timestamp_start for i in v] == [4, 3, 2, 1]
- v.order_reverse = False
+ v.toggle_reversed()
assert [i.request.timestamp_start for i in v] == [1, 2, 3, 4]
+def test_reversed():
+ v = view.View()
+ v.request(tft(start=1))
+ v.request(tft(start=2))
+ v.request(tft(start=3))
+ v.toggle_reversed()
+
+ assert v[0].request.timestamp_start == 3
+ assert v[-1].request.timestamp_start == 1
+ assert v[2].request.timestamp_start == 1
+ tutils.raises(IndexError, v.__getitem__, 5)
+ tutils.raises(IndexError, v.__getitem__, -5)
+
+ assert v.bisect(v[0]) == 1
+ assert v.bisect(v[2]) == 3
+
+
def test_update():
v = view.View()
flt = flowfilter.parse("~m get")