Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add union operators to MutableHeaders #1240

Merged
merged 6 commits into from Feb 16, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 14 additions & 1 deletion starlette/datastructures.py
Expand Up @@ -615,6 +615,19 @@ def __delitem__(self, key: str) -> None:
for idx in reversed(pop_indexes):
del self._list[idx]

def __ior__(self, other: typing.Mapping) -> "MutableHeaders":
if not isinstance(other, typing.Mapping):
raise TypeError(f"Expected a mapping but got {other.__class__.__name__})
tomchristie marked this conversation as resolved.
Show resolved Hide resolved
self.update(other)
return self

def __or__(self, other: typing.Mapping) -> "MutableHeaders":
if not isinstance(other, typing.Mapping):
raise TypeError(f"Expected a mapping but got {other.__class__.__name__})
tomchristie marked this conversation as resolved.
Show resolved Hide resolved
new = self.mutablecopy()
new.update(other)
return new

@property
def raw(self) -> typing.List[typing.Tuple[bytes, bytes]]:
return self._list
Expand All @@ -633,7 +646,7 @@ def setdefault(self, key: str, value: str) -> str:
self._list.append((set_key, set_value))
return value

def update(self, other: dict) -> None:
def update(self, other: typing.Mapping) -> None:
for key, val in other.items():
self[key] = val

Expand Down
44 changes: 44 additions & 0 deletions tests/test_datastructures.py
Expand Up @@ -162,6 +162,50 @@ def test_mutable_headers():
assert h.raw == [(b"b", b"4")]


def test_mutable_headers_merge():
h = MutableHeaders()
h = h | MutableHeaders({"a": "1"})
assert isinstance(h, MutableHeaders)
assert dict(h) == {"a": "1"}
assert h.items() == [("a", "1")]
assert h.raw == [(b"a", b"1")]


def test_mutable_headers_merge_dict():
h = MutableHeaders()
h = h | {"a": "1"}
assert isinstance(h, MutableHeaders)
assert dict(h) == {"a": "1"}
assert h.items() == [("a", "1")]
assert h.raw == [(b"a", b"1")]


def test_mutable_headers_update():
h = MutableHeaders()
h |= MutableHeaders({"a": "1"})
assert isinstance(h, MutableHeaders)
assert dict(h) == {"a": "1"}
assert h.items() == [("a", "1")]
assert h.raw == [(b"a", b"1")]


def test_mutable_headers_update_dict():
h = MutableHeaders()
h |= {"a": "1"}
assert isinstance(h, MutableHeaders)
assert dict(h) == {"a": "1"}
assert h.items() == [("a", "1")]
assert h.raw == [(b"a", b"1")]


def test_mutable_headers_merge_not_mapping():
h = MutableHeaders()
with pytest.raises(TypeError):
h |= {"not_mapping"} # type: ignore
with pytest.raises(TypeError):
h | {"not_mapping"} # type: ignore


def test_headers_mutablecopy():
h = Headers(raw=[(b"a", b"123"), (b"a", b"456"), (b"b", b"789")])
c = h.mutablecopy()
Expand Down