Forking what is left of ZeroNet and hopefully adding an AT Proto Frontend/Proxy
at main 122 lines 3.5 kB view raw
1import bisect 2from collections.abc import MutableSequence 3 4 5class CustomSortedList(MutableSequence): 6 def __init__(self): 7 super().__init__() 8 self.items = [] # (priority, added index, actual value) 9 self.logging = False 10 11 def __repr__(self): 12 return "<{0} {1}>".format(self.__class__.__name__, self.items) 13 14 def __len__(self): 15 return len(self.items) 16 17 def __getitem__(self, index): 18 if type(index) is int: 19 return self.items[index][2] 20 else: 21 return [item[2] for item in self.items[index]] 22 23 def __delitem__(self, index): 24 del self.items[index] 25 26 def __setitem__(self, index, value): 27 self.items[index] = self.valueToItem(value) 28 29 def __str__(self): 30 return str(self[:]) 31 32 def insert(self, index, value): 33 self.append(value) 34 35 def append(self, value): 36 bisect.insort(self.items, self.valueToItem(value)) 37 38 def updateItem(self, value, update_key=None, update_value=None): 39 self.remove(value) 40 if update_key is not None: 41 value[update_key] = update_value 42 self.append(value) 43 44 def sort(self, *args, **kwargs): 45 raise Exception("Sorted list can't be sorted") 46 47 def valueToItem(self, value): 48 return (self.getPriority(value), self.getId(value), value) 49 50 def getPriority(self, value): 51 return value 52 53 def getId(self, value): 54 return id(value) 55 56 def indexSlow(self, value): 57 for pos, item in enumerate(self.items): 58 if item[2] == value: 59 return pos 60 return None 61 62 def index(self, value): 63 item = (self.getPriority(value), self.getId(value), value) 64 bisect_pos = bisect.bisect(self.items, item) - 1 65 if bisect_pos >= 0 and self.items[bisect_pos][2] == value: 66 return bisect_pos 67 68 # Item probably changed since added, switch to slow iteration 69 pos = self.indexSlow(value) 70 71 if self.logging: 72 print("Slow index for %s in pos %s bisect: %s" % (item[2], pos, bisect_pos)) 73 74 if pos is None: 75 raise ValueError("%r not in list" % value) 76 else: 77 return pos 78 79 def __contains__(self, value): 80 try: 81 self.index(value) 82 return True 83 except ValueError: 84 return False 85 86 87class WorkerTaskManager(CustomSortedList): 88 def __init__(self): 89 super().__init__() 90 self.inner_paths = {} 91 92 def getPriority(self, value): 93 return 0 - (value["priority"] - value["workers_num"] * 10) 94 95 def getId(self, value): 96 return value["id"] 97 98 def __contains__(self, value): 99 return value["inner_path"] in self.inner_paths 100 101 def __delitem__(self, index): 102 # Remove from inner path cache 103 del self.inner_paths[self.items[index][2]["inner_path"]] 104 super().__delitem__(index) 105 106 # Fast task search by inner_path 107 108 def append(self, task): 109 if task["inner_path"] in self.inner_paths: 110 raise ValueError("File %s already has a task" % task["inner_path"]) 111 super().append(task) 112 # Create inner path cache for faster lookup by filename 113 self.inner_paths[task["inner_path"]] = task 114 115 def remove(self, task): 116 if task not in self: 117 raise ValueError("%r not in list" % task) 118 else: 119 super().remove(task) 120 121 def findTask(self, inner_path): 122 return self.inner_paths.get(inner_path, None)