diff --git a/h11/_headers.py b/h11/_headers.py index 31da3e2..d625ceb 100644 --- a/h11/_headers.py +++ b/h11/_headers.py @@ -116,7 +116,19 @@ def __len__(self) -> int: def __repr__(self) -> str: return "" % repr(list(self)) - def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: # type: ignore[override] + @overload + def __getitem__(self, idx: int) -> Tuple[bytes, bytes]: + ... + + @overload + def __getitem__(self, idx: slice) -> "Headers": + ... + + def __getitem__( + self, idx: Union[int, slice] + ) -> Union[Tuple[bytes, bytes], "Headers"]: + if isinstance(idx, slice): + return Headers(self._full_items[idx]) _, name, value = self._full_items[idx] return (name, value) diff --git a/h11/tests/test_headers.py b/h11/tests/test_headers.py index b57274c..b6f65bd 100644 --- a/h11/tests/test_headers.py +++ b/h11/tests/test_headers.py @@ -11,6 +11,34 @@ from .._util import LocalProtocolError +@pytest.mark.parametrize( + "index", + [ + slice(None, 1), + slice(None, 3), + slice(1, 1), + slice(None, None, -1), + slice(None, None, 2), + ], +) +def test_headers_slicing(index: slice) -> None: + headers = Request( + method="GET", + target="/", + headers=[("Host", "example.org"), ("X-First", "one"), ("X-Second", "two")], + ).headers + items = list(headers) + raw_items = headers.raw_items() + + sliced = headers[index] + + assert isinstance(sliced, Headers) + assert list(sliced) == items[index] + assert sliced.raw_items() == raw_items[index] + assert list(headers) == items + assert headers.raw_items() == raw_items + + def test_normalize_and_validate() -> None: assert normalize_and_validate([("foo", "bar")]) == [(b"foo", b"bar")] assert normalize_and_validate([(b"foo", b"bar")]) == [(b"foo", b"bar")] diff --git a/newsfragments/209.bugfix.rst b/newsfragments/209.bugfix.rst new file mode 100644 index 0000000..8c5f108 --- /dev/null +++ b/newsfragments/209.bugfix.rst @@ -0,0 +1 @@ +Support slicing the header sequence exposed by events, retaining normalized header pairs and original header-name casing.