def test_dllist_for(self): ll = DLList("4") ll.push("2") ll_iter = iter(ll) for i in ll_iter: assert i == "4" or i == "2" with pytest.raises(StopIteration): next(ll_iter)
def test_dllist_insert_after(self): ll = DLList(14) ll.push(15) ll.push(17) ll.insert(16, after_node=ll.tail.prev) assert len(ll) == 4 _assert_order_and_values(ll, [14, 15, 16, 17])
def test_dllist_insert_before(self): ll = DLList(14) ll.push(16) ll.push(17) ll.insert(15, before_node=ll.head.next) assert len(ll) == 4 _assert_order_and_values(ll, [14, 15, 16, 17])
def test_dllist_insert_exception(self): ll = DLList(13) ll.push(15) with pytest.raises(ValueError): ll.insert(14)
def test_dllist_complicated_case(self): ll3 = DLList(13) ll3.push(14) ll3.shift(12) ll3.push(15) assert ll3.unshift() == 12 assert ll3.pop() == 15 assert ll3.unshift() == 13 assert ll3.pop() == 14 with pytest.raises(Exception): ll3.pop()
def test_dllist_len(self): ll = DLList((1, 2)) assert len(ll) == 1 ll.shift((2, 3)) assert len(ll) == 2 ll.push((3, 4)) assert len(ll) == 3 ll.pop() assert len(ll) == 2 ll.unshift() assert len(ll) == 1 ll.pop() assert len(ll) == 0
def test_dllist_unshift(self): ll = DLList("k") assert ll.unshift() == "k" with pytest.raises(Exception): ll.unshift()
def test_dllist_pop(self): ll = DLList(12) assert ll.pop() == 12 with pytest.raises(Exception): ll.pop()
def test_dllist_init(self): with pytest.raises(TypeError): DLList()
def test_dllist_iter(self): ll = DLList(4) dlli = iter(ll) assert dlli.__next__() is ll.unshift()
def __init__(self, buffer_size: int = 40, check_time: int = 50) -> None: self.buffer_size = buffer_size self.check_time = check_time self.stream_sequence = 0 self.buffers = DLList(PercentileBuffer(buffer_size, buffer_size * 2))
class StreamMetrics: """ Stream metrics has 100 buckets for storing values (percentiles). Inner stream_sequence for delete oldest values and buckets. """ max_number_of_buffer = 100 def __init__(self, buffer_size: int = 40, check_time: int = 50) -> None: self.buffer_size = buffer_size self.check_time = check_time self.stream_sequence = 0 self.buffers = DLList(PercentileBuffer(buffer_size, buffer_size * 2)) def append(self, val: StreamValue) -> None: if self.stream_sequence > 0: if self.buffers.head.val.metrics.min > val.value: self.buffers.head.val.insert(val, self.stream_sequence) elif self.buffers.tail.val.metrics.max < val.value: self.buffers.tail.val.insert(val, self.stream_sequence) prev_buffer = None for buffer in self.buffers: if val.value in buffer.metrics: if len(self.buffers) != self.max_number_of_buffer: if not buffer.is_full(): buffer.append(val, self.stream_sequence) else: self.split_buffer(buffer) elif (prev_buffer and prev_buffer.metrics.max < val.value < buffer.metrics.min): if len(prev_buffer) <= len(buffer): prev_buffer.insert(val, self.stream_sequence) else: buffer.insert(val, self.stream_sequence) prev_buffer = buffer else: self.buffers.head.val.append(val, self.stream_sequence) self.stream_sequence += 1 def split_buffer(self, buffer_for_split: PercentileBuffer) -> None: node = [ b for b in self.buffers.iter_over_nodes() if b.val == buffer_for_split ][0] new_buffer = buffer_for_split.split_buffer() self.buffers.insert(new_buffer, before_node=node) def rebuild(self) -> None: buffer_to_number = {buffer: i for i, buffer in enumerate(self.buffers)} seq_to_buffer = { buffer.max_sequence(): buffer for buffer in self.buffers } split_candidate_buffer = seq_to_buffer[max(seq_to_buffer.keys())] merge_candidate_buffer = seq_to_buffer[min(seq_to_buffer.keys())] if buffer_to_number[split_candidate_buffer] - buffer_to_number[ merge_candidate_buffer] < 2: pass def current_metrics(self) -> Dict[int, Union[int, float]]: if self.stream_sequence < self.max_number_of_buffer * self.buffer_size: raise Exception("Not enough data") percentiles = {} for i, buffer in enumerate(self.buffers): if i == 24: percentiles[25] = buffer.metrics.max elif i == 49: percentiles[50] = buffer.metrics.max elif i == 74: percentiles[75] = buffer.metrics.max return percentiles