Sfoglia il codice sorgente

Adding BoundList, BoundSet, BoundDict

tags/1.0.1
Rocketsoup 4 anni fa
parent
commit
e4b0e8e133
2 ha cambiato i file con 139 aggiunte e 1 eliminazioni
  1. 1
    1
      cogs/crosspostcog.py
  2. 138
    0
      rscollections.py

+ 1
- 1
cogs/crosspostcog.py Vedi File

@@ -39,7 +39,7 @@ class CrossPostCog(BaseCog):
39 39
 			if count >= self.messages_per_user:
40 40
 				spamming_members.add(message.author)
41 41
 		for member in spamming_members:
42
-			context = self.__spam_context_for_user(member)
42
+			context = self.__spam_context_for_user(member, True)
43 43
 
44 44
 	def __spam_context_for_user(self,
45 45
 			member: Member,

+ 138
- 0
rscollections.py Vedi File

@@ -0,0 +1,138 @@
1
+"""
2
+Subclasses of list, set, and dict with maximum sizes.
3
+"""
4
+
5
+class BoundList(list):
6
+	"""
7
+	Subclass of `list` that enforces a maximum size.
8
+
9
+	If the number of elements following a mutating operation exceeds
10
+	`self.max_element_count`, then each element will be tested for its "age,"
11
+	and the "oldest" elements will be removed until the total size is back
12
+	within the limit. "Age" is determined via a provided lambda function. It is
13
+	a value with arbitrary numeric value that is used comparitively to find
14
+	the element with the smallest value. If no `age_test` is provided, the
15
+	default is to remove elem 0.
16
+
17
+	The age lambda takes two arguments: the element index and the element value.
18
+	It must return an int or float.
19
+
20
+	`self.age_test` and `self.max_element_count` can be modified at runtime,
21
+	however elements will only be discarded following the next mutating operation.
22
+	"""
23
+	def __init__(self, max_element_count = 10, age_test = (lambda index, elem: index), *args, **kwargs):
24
+		super().__init__(*args, **kwargs)
25
+		self.age_test = age_test
26
+		self.max_element_count = max_element_count
27
+
28
+	def __cull_old_elements(self):
29
+		while len(self) > self.max_element_count:
30
+			oldest_age = None
31
+			oldest_index = -1
32
+			for i in range(len(self)):
33
+				elem = self[i]
34
+				age = self.age_test(i, elem)
35
+				if oldest_age is None or age < oldest_age:
36
+					oldest_age = age
37
+					oldest_index = i
38
+			self.pop(oldest_index)
39
+
40
+	# Passthrough methods
41
+
42
+	def __add__(self, *args):
43
+		ret_val = super().__add__(*args)
44
+		self.__cull_old_elements()
45
+		return ret_val
46
+	def __iadd__(self, *args):
47
+		ret_val = super().__iadd__(*args)
48
+		self.__cull_old_elements()
49
+		return ret_val
50
+	def append(self, *args):
51
+		ret_val = super().append(*args)
52
+		self.__cull_old_elements()
53
+		return ret_val
54
+	def copy(self):
55
+		return BoundList(self.max_element_count, self.age_test, super())
56
+	def extend(self, *args):
57
+		ret_val = super().extend(*args)
58
+		self.__cull_old_elements()
59
+		return ret_val
60
+	def insert(self, *args):
61
+		ret_val = super().insert(*args)
62
+		self.__cull_old_elements()
63
+		return ret_val
64
+
65
+class BoundSet(set):
66
+	"""
67
+	Subclass of `set` that enforces a maximum size.
68
+
69
+	Same behavior as `BoundList`.
70
+
71
+	`age_test` lambda function takes one argument, the element value.
72
+	"""
73
+	def __init__(self, max_element_count = 10, age_test = (lambda elem: float(elem)), *args, **kwargs):
74
+		super().__init__(*args, **kwargs)
75
+		self.age_test = age_test
76
+		self.max_element_count = max_element_count
77
+
78
+	def __cull_old_elements(self):
79
+		while len(self) > self.max_element_count:
80
+			oldest_age = None
81
+			oldest_elem = None
82
+			for elem in self:
83
+				age = self.age_test(elem)
84
+				if oldest_age is None or age < oldest_age:
85
+					oldest_age = age
86
+					oldest_elem = elem
87
+			self.remove(oldest_elem)
88
+
89
+	def add(self, *args):
90
+		ret_val = super().add(*args)
91
+		self.__cull_old_elements()
92
+		return ret_val
93
+	def copy(self):
94
+		return BoundSet(self.max_element_count, self.age_test, super())
95
+	def update(self, *args):
96
+		ret_val = super().update(*args)
97
+		self.__cull_old_elements()
98
+		return ret_val
99
+
100
+class BoundDict(dict):
101
+	"""
102
+	Subclass of `dict` that enforces a maximum size.
103
+
104
+	Same behavior as `BoundList`.
105
+
106
+	`age_test` lambda takes two arguments: the key and the value of a pair.
107
+	"""
108
+	def __init__(self, max_element_count = 10, age_test = (lambda key, value: float(key)), *args, **kwargs):
109
+		super().__init__(*args, **kwargs)
110
+		self.age_test = age_test
111
+		self.max_element_count = max_element_count
112
+
113
+	def __cull_old_elements(self):
114
+		while len(self) > self.max_element_count:
115
+			oldest_age = None
116
+			oldest_key = None
117
+			for key, value in self.items():
118
+				age = self.age_test(key, value)
119
+				if oldest_age is None or age < oldest_age:
120
+					oldest_age = age
121
+					oldest_key = key
122
+			del self[oldest_key]
123
+	def __ior__(self, *args):
124
+		ret_val = super().__ior__(*args)
125
+		self.__cull_old_elements()
126
+		return ret_val
127
+	def __setitem__(self, *args):
128
+		super().__setitem__(*args)
129
+		self.__cull_old_elements()
130
+	def copy(self):
131
+		return BoundDict(self.max_element_count, self.age_test, super())
132
+	@classmethod
133
+	def fromkeys(cls, iter, value=None):
134
+		raise RuntimeError('fromkeys not available')
135
+	def update(self, *args):
136
+		ret_val = super().update(*args)
137
+		self.__cull_old_elements()
138
+		return ret_val

Loading…
Annulla
Salva