88
99import heapq
1010
11+ from typing import List , Tuple , Optional
12+
1113
1214class PriorityError (Exception ):
1315 """
@@ -79,22 +81,22 @@ class Stream:
7981 :param stream_id: The stream ID for the new stream.
8082 :param weight: (optional) The stream weight. Defaults to 16.
8183 """
82- def __init__ (self , stream_id , weight = 16 ):
84+ def __init__ (self , stream_id , weight = 16 ): # type: (int, int) -> None
8385 self .stream_id = stream_id
8486 self .weight = weight
85- self .children = []
86- self .parent = None
87- self .child_queue = []
87+ self .children = [] # type: List[Stream]
88+ self .parent = None # type: Optional[Stream]
89+ self .child_queue = [] # type: List[Tuple[int, Stream]]
8890 self .active = True
8991 self .last_weight = 0
9092 self ._deficit = 0
9193
9294 @property
93- def weight (self ):
95+ def weight (self ): # type: () -> int
9496 return self ._weight
9597
9698 @weight .setter
97- def weight (self , value ):
99+ def weight (self , value ): # type: (int) -> None
98100 # RFC 7540 § 5.3.2: "All dependent streams are allocated an integer
99101 # weight between 1 and 256 (inclusive)."
100102 if not isinstance (value , int ):
@@ -104,7 +106,7 @@ def weight(self, value):
104106 "Stream weight must be between 1 and 256 (inclusive)" )
105107 self ._weight = value
106108
107- def add_child (self , child ):
109+ def add_child (self , child ): # type: (Stream) -> None
108110 """
109111 Add a stream that depends on this one.
110112
@@ -114,7 +116,7 @@ def add_child(self, child):
114116 self .children .append (child )
115117 heapq .heappush (self .child_queue , (self .last_weight , child ))
116118
117- def add_child_exclusive (self , child ):
119+ def add_child_exclusive (self , child ): # type: (Stream) -> None
118120 """
119121 Add a stream that exclusively depends on this one.
120122
@@ -129,7 +131,12 @@ def add_child_exclusive(self, child):
129131 for old_child in old_children :
130132 child .add_child (old_child )
131133
132- def remove_child (self , child , strip_children = True ):
134+ def remove_child (
135+ self ,
136+ child , # type: Stream
137+ strip_children = True , # type: bool
138+ ):
139+ # type: (...) -> None
133140 """
134141 Removes a child stream from this stream. This is a potentially somewhat
135142 expensive operation.
@@ -145,7 +152,7 @@ def remove_child(self, child, strip_children=True):
145152 # it in the old one
146153 self .children .remove (child )
147154
148- new_queue = []
155+ new_queue = [] # type: List[Tuple[int, Stream]]
149156
150157 while self .child_queue :
151158 level , stream = heapq .heappop (self .child_queue )
@@ -160,7 +167,7 @@ def remove_child(self, child, strip_children=True):
160167 for new_child in child .children :
161168 self .add_child (new_child )
162169
163- def schedule (self ):
170+ def schedule (self ): # type: () -> int
164171 """
165172 Returns the stream ID of the next child to schedule. Potentially
166173 recurses down the tree of priorities.
@@ -200,45 +207,45 @@ def schedule(self):
200207 return next_stream
201208
202209 # Custom repr
203- def __repr__ (self ):
210+ def __repr__ (self ): # type: () -> str
204211 return "Stream<id=%d, weight=%d>" % (self .stream_id , self .weight )
205212
206213 # Custom comparison
207- def __eq__ (self , other ):
214+ def __eq__ (self , other ): # type: (object) -> bool
208215 if not isinstance (other , Stream ): # pragma: no cover
209216 return False
210217
211218 return self .stream_id == other .stream_id
212219
213- def __ne__ (self , other ):
220+ def __ne__ (self , other ): # type: (object) -> bool
214221 return not self .__eq__ (other )
215222
216- def __lt__ (self , other ):
223+ def __lt__ (self , other ): # type: (Stream) -> bool
217224 if not isinstance (other , Stream ): # pragma: no cover
218225 return NotImplemented
219226
220227 return self .stream_id < other .stream_id
221228
222- def __le__ (self , other ):
229+ def __le__ (self , other ): # type: (Stream) -> bool
223230 if not isinstance (other , Stream ): # pragma: no cover
224231 return NotImplemented
225232
226233 return self .stream_id <= other .stream_id
227234
228- def __gt__ (self , other ):
235+ def __gt__ (self , other ): # type: (Stream) -> bool
229236 if not isinstance (other , Stream ): # pragma: no cover
230237 return NotImplemented
231238
232239 return self .stream_id > other .stream_id
233240
234- def __ge__ (self , other ):
241+ def __ge__ (self , other ): # type: (Stream) -> bool
235242 if not isinstance (other , Stream ): # pragma: no cover
236243 return NotImplemented
237244
238245 return self .stream_id >= other .stream_id
239246
240247
241- def _stream_cycle (new_parent , current ):
248+ def _stream_cycle (new_parent , current ): # type: (Stream, Stream) -> bool
242249 """
243250 Reports whether the new parent depends on the current stream.
244251 """
@@ -248,7 +255,7 @@ def _stream_cycle(new_parent, current):
248255 # get more than 100 streams deep. This should catch accidental
249256 # tree loops. This is the definition of defensive programming.
250257 for _ in range (100 ):
251- parent = parent .parent
258+ parent = parent .parent # type: ignore[assignment]
252259 if parent .stream_id == current .stream_id :
253260 return True
254261 elif parent .stream_id == 0 :
@@ -284,7 +291,7 @@ class PriorityTree:
284291 default.
285292 :type maximum_streams: ``int``
286293 """
287- def __init__ (self , maximum_streams = 1000 ):
294+ def __init__ (self , maximum_streams = 1000 ): # type: (int) -> None
288295 # This flat array keeps hold of all the streams that are logically
289296 # dependent on stream 0.
290297 self ._root_stream = Stream (stream_id = 0 , weight = 1 )
@@ -297,7 +304,7 @@ def __init__(self, maximum_streams=1000):
297304 raise ValueError ("maximum_streams must be a positive integer." )
298305 self ._maximum_streams = maximum_streams
299306
300- def _get_or_insert_parent (self , parent_stream_id ):
307+ def _get_or_insert_parent (self , parent_stream_id ): # type: (int) -> Stream
301308 """
302309 When inserting or reprioritizing a stream it is possible to make it
303310 dependent on a stream that is no longer in the tree. In this situation,
@@ -311,18 +318,26 @@ def _get_or_insert_parent(self, parent_stream_id):
311318 self .block (parent_stream_id )
312319 return self ._streams [parent_stream_id ]
313320
314- def _exclusive_insert (self , parent_stream , inserted_stream ):
321+ def _exclusive_insert (
322+ self ,
323+ parent_stream , # type: Stream
324+ inserted_stream , # type: Stream
325+ ):
326+ # type: (...) -> None
315327 """
316328 Insert ``inserted_stream`` beneath ``parent_stream``, obeying the
317329 semantics of exclusive insertion.
318330 """
319331 parent_stream .add_child_exclusive (inserted_stream )
320332
321- def insert_stream (self ,
322- stream_id ,
323- depends_on = None ,
324- weight = 16 ,
325- exclusive = False ):
333+ def insert_stream (
334+ self ,
335+ stream_id , # type: int
336+ depends_on = None , # type: Optional[int]
337+ weight = 16 , # type: int
338+ exclusive = False , # type: bool
339+ ):
340+ # type: (...) -> None
326341 """
327342 Insert a stream into the tree.
328343
@@ -363,11 +378,14 @@ def insert_stream(self,
363378 parent .add_child (stream )
364379 self ._streams [stream_id ] = stream
365380
366- def reprioritize (self ,
367- stream_id ,
368- depends_on = None ,
369- weight = 16 ,
370- exclusive = False ):
381+ def reprioritize (
382+ self ,
383+ stream_id , # type: int
384+ depends_on = None , # type: Optional[int]
385+ weight = 16 , # type: int
386+ exclusive = False , # type: bool
387+ ):
388+ # type: (...) -> None
371389 """
372390 Update the priority status of a stream already in the tree.
373391
@@ -410,10 +428,10 @@ def reprioritize(self,
410428 # its parent, and make it a child of our current parent, and then
411429 # continue.
412430 if cycle :
413- new_parent .parent .remove_child (new_parent )
414- current_stream .parent .add_child (new_parent )
431+ new_parent .parent .remove_child (new_parent ) # type: ignore[union-attr]
432+ current_stream .parent .add_child (new_parent ) # type: ignore[union-attr]
415433
416- current_stream .parent .remove_child (
434+ current_stream .parent .remove_child ( # type: ignore[union-attr]
417435 current_stream , strip_children = False
418436 )
419437
@@ -422,7 +440,7 @@ def reprioritize(self,
422440 else :
423441 new_parent .add_child (current_stream )
424442
425- def remove_stream (self , stream_id ):
443+ def remove_stream (self , stream_id ): # type: (int) -> None
426444 """
427445 Removes a stream from the priority tree.
428446
@@ -437,9 +455,10 @@ def remove_stream(self, stream_id):
437455 raise MissingStreamError ("Stream %d not in tree" % stream_id )
438456
439457 parent = child .parent
440- parent .remove_child (child )
458+ parent .remove_child (child ) # type: ignore[union-attr]
459+
441460
442- def block (self , stream_id ):
461+ def block (self , stream_id ): # type: (int) -> None
443462 """
444463 Marks a given stream as blocked, with no data to send.
445464
@@ -453,7 +472,7 @@ def block(self, stream_id):
453472 except KeyError :
454473 raise MissingStreamError ("Stream %d not in tree" % stream_id )
455474
456- def unblock (self , stream_id ):
475+ def unblock (self , stream_id ): # type: (int) -> None
457476 """
458477 Marks a given stream as unblocked, with more data to send.
459478
@@ -468,14 +487,14 @@ def unblock(self, stream_id):
468487 raise MissingStreamError ("Stream %d not in tree" % stream_id )
469488
470489 # The iterator protocol
471- def __iter__ (self ): # pragma: no cover
490+ def __iter__ (self ): # type: () -> PriorityTree # pragma: no cover
472491 return self
473492
474- def __next__ (self ): # pragma: no cover
493+ def __next__ (self ): # type: () -> int # pragma: no cover
475494 try :
476495 return self ._root_stream .schedule ()
477496 except IndexError :
478497 raise DeadlockError ("No unblocked streams to schedule." )
479498
480- def next (self ): # pragma: no cover
499+ def next (self ): # type: () -> int # pragma: no cover
481500 return self .__next__ ()
0 commit comments