mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 10:16:27 +00:00
addons.View: better order reversal
Deal with some subtleties in order reversal, add a toggle method that emits refresh.
This commit is contained in:
parent
12a70d03ad
commit
90e7142b5c
@ -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,8 +209,7 @@ class Focus:
|
||||
def _sig_refresh(self, view):
|
||||
if len(view) == 0:
|
||||
self.focusflow = None
|
||||
else:
|
||||
if self.focusflow not in view:
|
||||
elif self.focusflow not in view:
|
||||
self.focusflow = view[0]
|
||||
|
||||
def _sig_add(self, view, flow):
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user