New Upstream Release - python-hyperframe
Ready changes
Summary
Merged new upstream version: 6.0.1 (was: 6.0.0).
Resulting package
Built on 2022-12-30T23:58 (took 2m29s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases python3-hyperframe
Lintian Result
Diff
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 37bac4a..da4061c 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,8 +1,16 @@
Release History
===============
+6.0.1 (2021-04-17)
+------------------
+
+**API Changes (Backward-compatible)**
+
+- Added support for Python 3.9.
+- Added type hints.
+
6.0.0 (2020-09-06)
----------
+------------------
**API Changes (Backward-incompatible)**
diff --git a/MANIFEST.in b/MANIFEST.in
index e7c846d..200507a 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,4 +4,5 @@ graft test
prune docs/build
prune test/http2-frame-test-case
include README.rst LICENSE CHANGELOG.rst CONTRIBUTORS.rst tox.ini .gitmodules
+include src/hyperframe/py.typed
global-exclude *.pyc *.pyo *.swo *.swp *.map *.yml *.DS_Store
diff --git a/PKG-INFO b/PKG-INFO
index c82bcad..549b385 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: hyperframe
-Version: 6.0.0
+Version: 6.0.1
Summary: HTTP/2 framing layer for Python
Home-page: https://github.com/python-hyper/hyperframe/
Author: Cory Benfield
diff --git a/debian/changelog b/debian/changelog
index d84e720..16e421f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+python-hyperframe (6.0.1-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 30 Dec 2022 23:56:08 -0000
+
python-hyperframe (6.0.0-1) unstable; urgency=medium
* Maintain within the Python team (Closes: #947013).
diff --git a/setup.cfg b/setup.cfg
index 7cc77fa..26f7720 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,6 +20,11 @@ source =
[flake8]
max-line-length = 120
+[check-manifest]
+ignore =
+ Makefile
+ test/http2-frame-test-case
+
[egg_info]
tag_build =
tag_date = 0
diff --git a/setup.py b/setup.py
index 7a5baa1..165e40b 100644
--- a/setup.py
+++ b/setup.py
@@ -23,11 +23,6 @@ with open(os.path.join(PROJECT_ROOT, 'src/hyperframe/__init__.py')) as file_:
else:
raise RuntimeError("No version number found!")
-# Stealing this from Kenneth Reitz
-if sys.argv[-1] == 'publish':
- os.system('python setup.py sdist upload')
- sys.exit()
-
setup(
name='hyperframe',
version=version,
@@ -38,7 +33,7 @@ setup(
author_email='cory@lukasa.co.uk',
url='https://github.com/python-hyper/hyperframe/',
packages=find_packages(where="src"),
- package_data={'': ['LICENSE', 'README.rst', 'CHANGELOG.rst']},
+ package_data={'': ['LICENSE', 'README.rst', 'CHANGELOG.rst'], "hyperframe": ["py.typed"]},
package_dir={'': 'src'},
python_requires='>=3.6.1',
include_package_data=True,
diff --git a/src/hyperframe.egg-info/PKG-INFO b/src/hyperframe.egg-info/PKG-INFO
index c82bcad..549b385 100644
--- a/src/hyperframe.egg-info/PKG-INFO
+++ b/src/hyperframe.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: hyperframe
-Version: 6.0.0
+Version: 6.0.1
Summary: HTTP/2 framing layer for Python
Home-page: https://github.com/python-hyper/hyperframe/
Author: Cory Benfield
diff --git a/src/hyperframe.egg-info/SOURCES.txt b/src/hyperframe.egg-info/SOURCES.txt
index e0201c8..952449c 100644
--- a/src/hyperframe.egg-info/SOURCES.txt
+++ b/src/hyperframe.egg-info/SOURCES.txt
@@ -17,6 +17,7 @@ src/hyperframe/__init__.py
src/hyperframe/exceptions.py
src/hyperframe/flags.py
src/hyperframe/frame.py
+src/hyperframe/py.typed
src/hyperframe.egg-info/PKG-INFO
src/hyperframe.egg-info/SOURCES.txt
src/hyperframe.egg-info/dependency_links.txt
diff --git a/src/hyperframe/__init__.py b/src/hyperframe/__init__.py
index 885a77e..bf5ba1c 100644
--- a/src/hyperframe/__init__.py
+++ b/src/hyperframe/__init__.py
@@ -5,4 +5,4 @@ hyperframe
A module for providing a pure-Python HTTP/2 framing layer.
"""
-__version__ = '6.0.0'
+__version__ = '6.0.1'
diff --git a/src/hyperframe/exceptions.py b/src/hyperframe/exceptions.py
index 3d41468..d6adab2 100644
--- a/src/hyperframe/exceptions.py
+++ b/src/hyperframe/exceptions.py
@@ -22,14 +22,14 @@ class UnknownFrameError(HyperframeError):
.. versionchanged:: 6.0.0
Changed base class from `ValueError` to :class:`HyperframeError`
"""
- def __init__(self, frame_type, length):
+ def __init__(self, frame_type: int, length: int) -> None:
#: The type byte of the unknown frame that was received.
self.frame_type = frame_type
#: The length of the data portion of the unknown frame.
self.length = length
- def __str__(self):
+ def __str__(self) -> str:
return (
"UnknownFrameError: Unknown frame type 0x%X received, "
"length %d bytes" % (self.frame_type, self.length)
diff --git a/src/hyperframe/flags.py b/src/hyperframe/flags.py
index f3933f8..f00cb99 100644
--- a/src/hyperframe/flags.py
+++ b/src/hyperframe/flags.py
@@ -5,13 +5,16 @@ hyperframe/flags
Defines basic Flag and Flags data structures.
"""
-import collections
from collections.abc import MutableSet
+from typing import NamedTuple, Iterable, Set, Iterator
-Flag = collections.namedtuple("Flag", ["name", "bit"])
+class Flag(NamedTuple):
+ name: str
+ bit: int
-class Flags(MutableSet):
+
+class Flags(MutableSet): # type: ignore
"""
A simple MutableSet implementation that will only accept known flags as
elements.
@@ -19,26 +22,26 @@ class Flags(MutableSet):
Will behave like a regular set(), except that a ValueError will be thrown
when .add()ing unexpected flags.
"""
- def __init__(self, defined_flags):
+ def __init__(self, defined_flags: Iterable[Flag]):
self._valid_flags = set(flag.name for flag in defined_flags)
- self._flags = set()
+ self._flags: Set[str] = set()
- def __repr__(self):
+ def __repr__(self) -> str:
return repr(sorted(list(self._flags)))
- def __contains__(self, x):
+ def __contains__(self, x: object) -> bool:
return self._flags.__contains__(x)
- def __iter__(self):
+ def __iter__(self) -> Iterator[str]:
return self._flags.__iter__()
- def __len__(self):
+ def __len__(self) -> int:
return self._flags.__len__()
- def discard(self, value):
+ def discard(self, value: str) -> None:
return self._flags.discard(value)
- def add(self, value):
+ def add(self, value: str) -> None:
if value not in self._valid_flags:
raise ValueError(
"Unexpected flag: {}. Valid flags are: {}".format(
diff --git a/src/hyperframe/frame.py b/src/hyperframe/frame.py
index d9b3ecf..f4e75e3 100644
--- a/src/hyperframe/frame.py
+++ b/src/hyperframe/frame.py
@@ -14,6 +14,7 @@ from .exceptions import (
UnknownFrameError, InvalidPaddingError, InvalidFrameError, InvalidDataError
)
from .flags import Flag, Flags
+from typing import Optional, Tuple, List, Iterable, Any, Dict, Type
# The maximum initial length of a frame. Some frames have shorter maximum
@@ -43,16 +44,16 @@ class Frame:
The base class for all HTTP/2 frames.
"""
#: The flags defined on this type of frame.
- defined_flags = []
+ defined_flags: List[Flag] = []
#: The byte used to define the type of the frame.
- type = None
+ type: Optional[int] = None
# If 'has-stream', the frame's stream_id must be non-zero. If 'no-stream',
# it must be zero. If 'either', it's not checked.
- stream_association = None
+ stream_association: Optional[str] = None
- def __init__(self, stream_id, flags=()):
+ def __init__(self, stream_id: int, flags: Iterable[str] = ()) -> None:
#: The stream identifier for the stream this frame was received on.
#: Set to 0 for frames sent on the connection (stream-id 0).
self.stream_id = stream_id
@@ -82,7 +83,7 @@ class Frame:
)
)
- def __repr__(self):
+ def __repr__(self) -> str:
return (
"{}(stream_id={}, flags={}): {}"
).format(
@@ -92,13 +93,13 @@ class Frame:
self._body_repr(),
)
- def _body_repr(self):
+ def _body_repr(self) -> str:
# More specific implementation may be provided by subclasses of Frame.
# This fallback shows the serialized (and truncated) body content.
return _raw_data_repr(self.serialize_body())
@staticmethod
- def explain(data):
+ def explain(data: memoryview) -> Tuple["Frame", int]:
"""
Takes a bytestring and tries to parse a single frame and print it.
@@ -115,7 +116,7 @@ class Frame:
return frame, length
@staticmethod
- def parse_frame_header(header, strict=False):
+ def parse_frame_header(header: memoryview, strict: bool = False) -> Tuple["Frame", int]:
"""
Takes a 9-byte frame header and returns a tuple of the appropriate
Frame object and the length that needs to be read from the socket.
@@ -155,14 +156,14 @@ class Frame:
frame.parse_flags(flags)
return (frame, length)
- def parse_flags(self, flag_byte):
+ def parse_flags(self, flag_byte: int) -> Flags:
for flag, flag_bit in self.defined_flags:
if flag_byte & flag_bit:
self.flags.add(flag)
return self.flags
- def serialize(self):
+ def serialize(self) -> bytes:
"""
Convert a frame into a bytestring, representing the serialized form of
the frame.
@@ -188,10 +189,10 @@ class Frame:
return header + body
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
raise NotImplementedError()
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
"""
Given the body of a frame, parses it into frame data. This populates
the non-header parts of the frame: that is, it does not populate the
@@ -210,19 +211,19 @@ class Padding:
Mixin for frames that contain padding. Defines extra fields that can be
used and set by frames that can be padded.
"""
- def __init__(self, stream_id, pad_length=0, **kwargs):
- super().__init__(stream_id, **kwargs)
+ def __init__(self, stream_id: int, pad_length: int = 0, **kwargs: Any) -> None:
+ super().__init__(stream_id, **kwargs) # type: ignore
#: The length of the padding to use.
self.pad_length = pad_length
- def serialize_padding_data(self):
- if 'PADDED' in self.flags:
+ def serialize_padding_data(self) -> bytes:
+ if 'PADDED' in self.flags: # type: ignore
return _STRUCT_B.pack(self.pad_length)
return b''
- def parse_padding_data(self, data):
- if 'PADDED' in self.flags:
+ def parse_padding_data(self, data: memoryview) -> int:
+ if 'PADDED' in self.flags: # type: ignore
try:
self.pad_length = struct.unpack('!B', data[:1])[0]
except struct.error:
@@ -233,7 +234,7 @@ class Padding:
#: .. deprecated:: 5.2.1
#: Use self.pad_length instead.
@property
- def total_padding(self): # pragma: no cover
+ def total_padding(self) -> int: # pragma: no cover
import warnings
warnings.warn(
"total_padding contains the same information as pad_length.",
@@ -248,12 +249,12 @@ class Priority:
be used and set by frames that contain priority data.
"""
def __init__(self,
- stream_id,
- depends_on=0x0,
- stream_weight=0x0,
- exclusive=False,
- **kwargs):
- super().__init__(stream_id, **kwargs)
+ stream_id: int,
+ depends_on: int = 0x0,
+ stream_weight: int = 0x0,
+ exclusive: bool = False,
+ **kwargs: Any) -> None:
+ super().__init__(stream_id, **kwargs) # type: ignore
#: The stream ID of the stream on which this stream depends.
self.depends_on = depends_on
@@ -264,13 +265,13 @@ class Priority:
#: Whether the exclusive bit was set.
self.exclusive = exclusive
- def serialize_priority_data(self):
+ def serialize_priority_data(self) -> bytes:
return _STRUCT_LB.pack(
self.depends_on + (0x80000000 if self.exclusive else 0),
self.stream_weight
)
- def parse_priority_data(self, data):
+ def parse_priority_data(self, data: memoryview) -> int:
try:
self.depends_on, self.stream_weight = _STRUCT_LB.unpack(data[:5])
except struct.error:
@@ -298,20 +299,20 @@ class DataFrame(Padding, Frame):
stream_association = _STREAM_ASSOC_HAS_STREAM
- def __init__(self, stream_id, data=b'', **kwargs):
+ def __init__(self, stream_id: int, data: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The data contained on this frame.
self.data = data
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
padding_data = self.serialize_padding_data()
padding = b'\0' * self.pad_length
if isinstance(self.data, memoryview):
self.data = self.data.tobytes()
return b''.join([padding_data, self.data, padding])
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
padding_data_length = self.parse_padding_data(data)
self.data = (
data[padding_data_length:len(data)-self.pad_length].tobytes()
@@ -322,7 +323,7 @@ class DataFrame(Padding, Frame):
raise InvalidPaddingError("Padding is too long.")
@property
- def flow_controlled_length(self):
+ def flow_controlled_length(self) -> int:
"""
The length of the frame that needs to be accounted for when considering
flow control.
@@ -342,24 +343,24 @@ class PriorityFrame(Priority, Frame):
reprioritisation of existing streams.
"""
#: The flags defined for PRIORITY frames.
- defined_flags = []
+ defined_flags: List[Flag] = []
#: The type byte defined for PRIORITY frames.
type = 0x02
stream_association = _STREAM_ASSOC_HAS_STREAM
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "exclusive={}, depends_on={}, stream_weight={}".format(
self.exclusive,
self.depends_on,
self.stream_weight
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
return self.serialize_priority_data()
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
if len(data) > 5:
raise InvalidFrameError(
"PRIORITY must have 5 byte body: actual length %s." %
@@ -380,28 +381,28 @@ class RstStreamFrame(Frame):
occurred.
"""
#: The flags defined for RST_STREAM frames.
- defined_flags = []
+ defined_flags: List[Flag] = []
#: The type byte defined for RST_STREAM frames.
type = 0x03
stream_association = _STREAM_ASSOC_HAS_STREAM
- def __init__(self, stream_id, error_code=0, **kwargs):
+ def __init__(self, stream_id: int, error_code: int = 0, **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The error code used when resetting the stream.
self.error_code = error_code
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "error_code={}".format(
self.error_code,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
return _STRUCT_L.pack(self.error_code)
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
if len(data) != 4:
raise InvalidFrameError(
"RST_STREAM must have 4 byte body: actual length %s." %
@@ -453,7 +454,7 @@ class SettingsFrame(Frame):
#: The byte that signals SETTINGS_ENABLE_CONNECT_PROTOCOL setting.
ENABLE_CONNECT_PROTOCOL = 0x08
- def __init__(self, stream_id=0, settings=None, **kwargs):
+ def __init__(self, stream_id: int = 0, settings: Optional[Dict[int, int]] = None, **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
if settings and "ACK" in kwargs.get("flags", ()):
@@ -464,16 +465,16 @@ class SettingsFrame(Frame):
#: A dictionary of the setting type byte to the value of the setting.
self.settings = settings or {}
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "settings={}".format(
self.settings,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
return b''.join([_STRUCT_HL.pack(setting & 0xFF, value)
for setting, value in self.settings.items()])
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
if 'ACK' in self.flags and len(data) > 0:
raise InvalidDataError(
"SETTINGS ack frame must not have payload: got %s bytes" %
@@ -509,7 +510,7 @@ class PushPromiseFrame(Padding, Frame):
stream_association = _STREAM_ASSOC_HAS_STREAM
- def __init__(self, stream_id, promised_stream_id=0, data=b'', **kwargs):
+ def __init__(self, stream_id: int, promised_stream_id: int = 0, data: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The stream ID that is promised by this frame.
@@ -519,19 +520,19 @@ class PushPromiseFrame(Padding, Frame):
#: stream.
self.data = data
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "promised_stream_id={}, data={}".format(
self.promised_stream_id,
_raw_data_repr(self.data),
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
padding_data = self.serialize_padding_data()
padding = b'\0' * self.pad_length
data = _STRUCT_L.pack(self.promised_stream_id)
return b''.join([padding_data, data, self.data, padding])
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
padding_data_length = self.parse_padding_data(data)
try:
@@ -570,21 +571,21 @@ class PingFrame(Frame):
stream_association = _STREAM_ASSOC_NO_STREAM
- def __init__(self, stream_id=0, opaque_data=b'', **kwargs):
+ def __init__(self, stream_id: int = 0, opaque_data: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The opaque data sent in this PING frame, as a bytestring.
self.opaque_data = opaque_data
- def _body_repr(self):
- return "opaque_data={}".format(
+ def _body_repr(self) -> str:
+ return "opaque_data={!r}".format(
self.opaque_data,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
if len(self.opaque_data) > 8:
raise InvalidFrameError(
- "PING frame may not have more than 8 bytes of data, got %s" %
+ "PING frame may not have more than 8 bytes of data, got %r" %
self.opaque_data
)
@@ -592,7 +593,7 @@ class PingFrame(Frame):
data += b'\x00' * (8 - len(self.opaque_data))
return data
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
if len(data) != 8:
raise InvalidFrameError(
"PING frame must have 8 byte length: got %s" % len(data)
@@ -610,7 +611,7 @@ class GoAwayFrame(Frame):
connection.
"""
#: The flags defined for GOAWAY frames.
- defined_flags = []
+ defined_flags: List[Flag] = []
#: The type byte defined for GOAWAY frames.
type = 0x07
@@ -618,11 +619,11 @@ class GoAwayFrame(Frame):
stream_association = _STREAM_ASSOC_NO_STREAM
def __init__(self,
- stream_id=0,
- last_stream_id=0,
- error_code=0,
- additional_data=b'',
- **kwargs):
+ stream_id: int = 0,
+ last_stream_id: int = 0,
+ error_code: int = 0,
+ additional_data: bytes = b'',
+ **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The last stream ID definitely seen by the remote peer.
@@ -634,14 +635,14 @@ class GoAwayFrame(Frame):
#: Any additional data sent in the GOAWAY.
self.additional_data = additional_data
- def _body_repr(self):
- return "last_stream_id={}, error_code={}, additional_data={}".format(
+ def _body_repr(self) -> str:
+ return "last_stream_id={}, error_code={}, additional_data={!r}".format(
self.last_stream_id,
self.error_code,
self.additional_data,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
data = _STRUCT_LL.pack(
self.last_stream_id & 0x7FFFFFFF,
self.error_code
@@ -650,7 +651,7 @@ class GoAwayFrame(Frame):
return data
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
try:
self.last_stream_id, self.error_code = _STRUCT_LL.unpack(
data[:8]
@@ -678,28 +679,28 @@ class WindowUpdateFrame(Frame):
original sender.
"""
#: The flags defined for WINDOW_UPDATE frames.
- defined_flags = []
+ defined_flags: List[Flag] = []
#: The type byte defined for WINDOW_UPDATE frames.
type = 0x08
stream_association = _STREAM_ASSOC_EITHER
- def __init__(self, stream_id, window_increment=0, **kwargs):
+ def __init__(self, stream_id: int, window_increment: int = 0, **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The amount the flow control window is to be incremented.
self.window_increment = window_increment
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "window_increment={}".format(
self.window_increment,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
return _STRUCT_L.pack(self.window_increment & 0x7FFFFFFF)
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
if len(data) > 4:
raise InvalidFrameError(
"WINDOW_UPDATE frame must have 4 byte length: got %s" %
@@ -744,13 +745,13 @@ class HeadersFrame(Padding, Priority, Frame):
stream_association = _STREAM_ASSOC_HAS_STREAM
- def __init__(self, stream_id, data=b'', **kwargs):
+ def __init__(self, stream_id: int, data: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The HPACK-encoded header block.
self.data = data
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "exclusive={}, depends_on={}, stream_weight={}, data={}".format(
self.exclusive,
self.depends_on,
@@ -758,7 +759,7 @@ class HeadersFrame(Padding, Priority, Frame):
_raw_data_repr(self.data),
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
padding_data = self.serialize_padding_data()
padding = b'\0' * self.pad_length
@@ -769,7 +770,7 @@ class HeadersFrame(Padding, Priority, Frame):
return b''.join([padding_data, priority_data, self.data, padding])
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
padding_data_length = self.parse_padding_data(data)
data = data[padding_data_length:]
@@ -805,21 +806,21 @@ class ContinuationFrame(Frame):
stream_association = _STREAM_ASSOC_HAS_STREAM
- def __init__(self, stream_id, data=b'', **kwargs):
+ def __init__(self, stream_id: int, data: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
#: The HPACK-encoded header block.
self.data = data
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "data={}".format(
_raw_data_repr(self.data),
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
return self.data
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
self.data = data.tobytes()
self.body_len = len(data)
@@ -843,7 +844,7 @@ class AltSvcFrame(Frame):
stream_association = _STREAM_ASSOC_EITHER
- def __init__(self, stream_id, origin=b'', field=b'', **kwargs):
+ def __init__(self, stream_id: int, origin: bytes = b'', field: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
if not isinstance(origin, bytes):
@@ -853,17 +854,17 @@ class AltSvcFrame(Frame):
self.origin = origin
self.field = field
- def _body_repr(self):
- return "origin={}, field={}".format(
+ def _body_repr(self) -> str:
+ return "origin={!r}, field={!r}".format(
self.origin,
self.field,
)
- def serialize_body(self):
+ def serialize_body(self) -> bytes:
origin_len = _STRUCT_H.pack(len(self.origin))
return b''.join([origin_len, self.origin, self.field])
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
try:
origin_len = _STRUCT_H.unpack(data[0:2])[0]
self.origin = data[2:2+origin_len].tobytes()
@@ -896,30 +897,30 @@ class ExtensionFrame(Frame):
stream_association = _STREAM_ASSOC_EITHER
- def __init__(self, type, stream_id, flag_byte=0x0, body=b'', **kwargs):
+ def __init__(self, type: int, stream_id: int, flag_byte: int = 0x0, body: bytes = b'', **kwargs: Any) -> None:
super().__init__(stream_id, **kwargs)
self.type = type
self.flag_byte = flag_byte
self.body = body
- def _body_repr(self):
+ def _body_repr(self) -> str:
return "type={}, flag_byte={}, body={}".format(
self.type,
self.flag_byte,
_raw_data_repr(self.body),
)
- def parse_flags(self, flag_byte):
+ def parse_flags(self, flag_byte: int) -> None: # type: ignore
"""
For extension frames, we parse the flags by just storing a flag byte.
"""
self.flag_byte = flag_byte
- def parse_body(self, data):
+ def parse_body(self, data: memoryview) -> None:
self.body = data.tobytes()
self.body_len = len(data)
- def serialize(self):
+ def serialize(self) -> bytes:
"""
A broad override of the serialize method that ensures that the data
comes back out exactly as it came in. This should not be used in most
@@ -941,7 +942,7 @@ class ExtensionFrame(Frame):
return header + self.body
-def _raw_data_repr(data):
+def _raw_data_repr(data: Optional[bytes]) -> str:
if not data:
return "None"
r = binascii.hexlify(data).decode('ascii')
@@ -950,7 +951,7 @@ def _raw_data_repr(data):
return "<hex:" + r + ">"
-_FRAME_CLASSES = [
+_FRAME_CLASSES: List[Type[Frame]] = [
DataFrame,
HeadersFrame,
PriorityFrame,
diff --git a/src/hyperframe/py.typed b/src/hyperframe/py.typed
new file mode 100644
index 0000000..e69de29
diff --git a/tox.ini b/tox.ini
index 061e5d4..e9fe970 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,22 +1,23 @@
[tox]
-envlist = py36, py37, py38, pypy3, lint, docs, packaging
+envlist = py36, py37, py38, py39, pypy3, lint, docs, packaging
[gh-actions]
python =
3.6: py36
3.7: py37
3.8: py38, lint, docs, packaging
+ 3.9: py39
pypy3: pypy3
[testenv]
passenv =
GITHUB_*
deps =
- pytest==6.0.1
- pytest-cov==2.10.1
- pytest-xdist==2.1.0
+ pytest>=6.0.1,<7
+ pytest-cov>=2.10.1,<3
+ pytest-xdist>=2.2.1,<3
commands =
- pytest --cov-report=xml --cov-report=term --cov=hyperframe {posargs}
+ pytest --cov-report=xml --cov-report=term --cov=hyperframe {posargs}
[testenv:pypy3]
# temporarily disable coverage testing on PyPy due to performance problems
@@ -25,7 +26,7 @@ commands = pytest {posargs}
[testenv:docs]
basepython = python3.8
deps =
- sphinx==3.2.1
+ sphinx>=3.5.4,<4
whitelist_externals = make
changedir = {toxinidir}/docs
commands =
@@ -35,15 +36,18 @@ commands =
[testenv:lint]
basepython = python3.8
deps =
- flake8==3.8.3
-commands = flake8 --max-complexity 10 src test
+ flake8==3.9.1
+ mypy==0.812
+commands =
+ flake8 --max-complexity 10 src test
+ mypy --strict src/
[testenv:packaging]
basepython = python3.8
deps =
- check-manifest==0.42
- readme-renderer==26.0
- twine==3.2.0
+ check-manifest==0.46
+ readme-renderer==29.0
+ twine==3.4.1
whitelist_externals = rm
commands =
rm -rf dist/
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.1.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.1.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.1.egg-info/top_level.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe/py.typed
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.0.egg-info/PKG-INFO -rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.0.egg-info/dependency_links.txt -rw-r--r-- root/root /usr/lib/python3/dist-packages/hyperframe-6.0.0.egg-info/top_level.txt
No differences were encountered in the control files