Skip to content

Commit 4011c84

Browse files
committed
add type annotations
1 parent a64b888 commit 4011c84

File tree

8 files changed

+103
-55
lines changed

8 files changed

+103
-55
lines changed

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ graft visualizer
55
graft examples
66
prune docs/build
77
recursive-include *.py
8-
include README.rst LICENSE CONTRIBUTORS.rst HISTORY.rst tox.ini Makefile
8+
include README.rst LICENSE CONTRIBUTORS.rst HISTORY.rst tox.ini Makefile src/priority/py.typed
99
global-exclude *.pyc *.pyo *.swo *.swp *.map *.yml *.DS_Store

docs/source/conf.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import sys
1515
import re
1616

17+
from typing import List
18+
1719
sys.path.insert(0, os.path.abspath('../..'))
1820

1921
PROJECT_ROOT = os.path.dirname(__file__)
@@ -22,6 +24,7 @@
2224
with open(os.path.join(PROJECT_ROOT, '../../', 'src/priority/__init__.py')) as file_:
2325
text = file_.read()
2426
match = re.search(version_regex, text)
27+
assert match
2528
version = match.group(1)
2629

2730

@@ -51,7 +54,7 @@
5154

5255
# List of patterns, relative to source directory, that match files and
5356
# directories to ignore when looking for source files.
54-
exclude_patterns = []
57+
exclude_patterns = [] # type: List[str]
5558

5659
# Example configuration for intersphinx: refer to the Python standard library.
5760
intersphinx_mapping = {'http://docs.python.org/': None}

mypy.ini

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[mypy]
2+
strict=true
3+
warn_unused_configs=true
4+
show_error_codes=true
5+
6+
[mypy-test_priority]
7+
allow_untyped_defs=true
8+
check_untyped_defs=false
9+
10+
[mypy-conftest]
11+
allow_untyped_defs=true
12+
check_untyped_defs=false

setup.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import re
55

6-
from setuptools import setup, find_packages
6+
from setuptools import setup, find_packages # type: ignore[import]
77

88

99
PROJECT_ROOT = os.path.dirname(__file__)
@@ -59,4 +59,7 @@
5959
'Programming Language :: Python :: Implementation :: CPython',
6060
'Programming Language :: Python :: Implementation :: PyPy',
6161
],
62+
extras_require={
63+
"mypy": ["mypy>=0.812"],
64+
},
6265
)

src/priority/priority.py

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import heapq
1010

11+
from typing import List, Tuple, Optional
12+
1113

1214
class 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__()

src/priority/py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)