summaryrefslogtreecommitdiff
path: root/monkey/util.py
blob: 6d57d29e825ea663f5b03137500410b06d4f43de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#!/usr/bin/python3

from heapq import heappush, heappop
import itertools

# A simple priority queue based on the heapq class.
class PQueue(object):
    REMOVED = '<removed-task>'      # placeholder for a removed task

    def __init__(self):
        self.pq = []                         # list of entries arranged in a heap
        self.entry_finder = {}               # mapping of tasks to entries
        self.counter = itertools.count()     # unique sequence count
        self.size = 0

    def push(self, task, priority=0):
        'Add a new task or update the priority of an existing task'
        if task in self.entry_finder:
            self.remove(task)
        else:
            self.size += 1
        entry = [priority, next(self.counter), task]
        self.entry_finder[task] = entry
        heappush(self.pq, entry)

    def remove(self, task):
        'Mark an existing task as REMOVED.  Raise KeyError if not found.'
        entry = self.entry_finder.pop(task)
        entry[-1] = self.REMOVED
        self.size -= 1

    def pop(self):
        'Remove and return the lowest priority task. Raise KeyError if empty.'
        while self.pq:
            priority, count, task = heappop(self.pq)
            if task is not self.REMOVED:
                del self.entry_finder[task]
                self.size -= 1
                return task
        return None

    def __len__(self):
        return self.size

# Return [n]th line in [text].
def get_line(text, n):
    lines = text.split('\n')
    if n >= 0 and n < len(lines):
        return lines[n]
    return None

# Indent each line in [text] by [indent] spaces.
def indent(text, indent=2):
    return '\n'.join([' '*indent+line for line in text.split('\n')])