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 headers.get and headers.getlist #180

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Julien00859
Copy link

@Julien00859 Julien00859 commented Jan 9, 2025

Hello there, first time contributing :)

I wanted to access a header value with little code, like req.headers[b"content-type"] but since the headers are implemented as a Sequence there are no easy way beside iterating all the headers to find the one that interest me.

I am not challenging the internal data-structure, list(tuple(bytes, bytes, bytes)) is kinda the only sane structure because of headers like Set-Cookie.

In this work I add two helpers get(name) -> bytes and getlist(name) -> list[bytes] that searches the headers for me, so I don't have to write this next(generator, None) everywhere 😄 The two method names at coined at the Headers class of werkzeug. We might also add the type= parameter for total symmetry, you tell me.

The implementation is simple stupid, it iterates over the headers looking for one that matches the name.

I did experiment with another implementation, as follow (didn't test it):

     def __init__(self, full_items: List[Tuple[bytes, bytes, bytes]]) -> None:
         self._full_items = full_items
+        self._index = {}
+        for idx, (_, name, value) in enumerate(full_items):
+            self._index.setdefault(name, []).append(idx)
 
     def __bool__(self) -> bool:
         return bool(self._full_items)
@@ -118,6 +133,15 @@ class Headers(Sequence[Tuple[bytes, bytes]]):
         _, name, value = self._full_items[idx]
         return (name, value)
 
+    def get(self, name: bytes, default: T = None) -> Union[bytes, T]:
+        try:
+            self[self._index[name][0]][1]
+        except KeyError:
+            return default
+
+    def getlist(self, name: bytes) -> List[bytes]:
+        return [self[idx][1] for idx in self._index.get(name, ())]

But I don't think it deserves an index. I think the O(n) search is fine.

@@ -1,5 +1,5 @@
import re
from typing import AnyStr, cast, List, overload, Sequence, Tuple, TYPE_CHECKING, Union
from typing import List, overload, Sequence, Tuple, TYPE_CHECKING, TypeVar, Union
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My IDE was telling me AnyStr and cast were not used, I used the opportunity of changing the line to remove them

@Julien00859 Julien00859 force-pushed the Julien00859/headers-get branch 7 times, most recently from df7c10c to 5721bc4 Compare January 9, 2025 18:59
@Julien00859 Julien00859 force-pushed the Julien00859/headers-get branch from 5721bc4 to 00a2524 Compare January 9, 2025 19:30
@Julien00859 Julien00859 marked this pull request as ready for review January 9, 2025 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant