Skip to content

Should Headers.keys be a set-like keys view? #899

Closed

Description

@obataku

Checklist

  • I searched the HTTPX documentation but couldn't find what I'm looking for.
  • I looked through similar issues on GitHub, but didn't find anything.
  • I looked up "How to do ... in HTTPX" on a search engine and didn't find any information.
  • I asked the community chat for help but didn't get an answer.

Question

presently Headers.keys returns a typing.List[str] rather than a (set-like) typing.KeysView[str], which appears to violate the Mapping protocol: https://docs.python.org/3/library/collections.abc.html#collections.abc.KeysView

this breaks code that expects set-like operations with Headers.keys, e.g.

    dst: Dict[str, str] = ...
    headers: httpx.Headers = ...
    keys: Set[str] = {"set-cookie", "set-cookie2"}
    dst.update({k: headers[k] for k in keys & headers.keys()})

is this an intentional design choice or simply an oversight?

Activity

  1. added
    questionFurther information is requested
    user-experienceEnsuring that users have a good experience using the library
    on Apr 9, 2020
  2. florimondmanca commented on Apr 9, 2020

    @florimondmanca
    Contributor

    Not necessarily intentional, no. Any idea how we could return such a keyview object? I don't know how we can construct one from something that's not a dict.

  3. florimondmanca commented on Apr 9, 2020

    @florimondmanca
    Contributor

    Okay I found it — we can use typing.KeysView(<dict>), typing.ValuesView(<dict>), etc.

    Thinking about this more, I think this was an intentional choice, basically to keep the scope down a bit.

    Eg one reason why we cannot very easily implement these interfaces (eg building a dict and returning the result of calling .keys() on it) is because duplicate headers are not forbidden by the HTTP spec. Set-Cookie is a prime example of this.

    That doesn't mean we can't implement the KeysView/ValuesView/ItemsView protocols, though, but we'd need to implement our own subclasses, and basically end up with what multidict is doing. Making that work with type hints etc would be a significant chunk of code and work.

    Don't think we're ready to make that move yet… But I'd personally be interested in seeing what making this work would take.

  4. obataku commented on Apr 9, 2020

    @obataku
    Author

    I think the easiest way would likely be something similar to how aiolibs multidict does it, yeah; using the default KeysView, ValuesView wouldn't work well for the reasons you mention although it's worth pointing out that the XView constructors accept general mappings (and using stale dict snapshots to implement the views would violate the protocol anyway).

  5. florimondmanca commented on Apr 11, 2020

    @florimondmanca
    Contributor

    So, switching to multidict is not as simple unfortunately, and probably not possible, because we already have some subtle behavior differences between our QueryParams and Headers models, and how multidict behaves.

    Eg:

    • Currently params[key] returns the first value in the list of items for key, while multidict returns the last.
    • multidict doesn't allow efficiently iterating over key-unique items (like a dict), so we have to do dict(md).keys() to get unique keys for queryparams (while multikeys is what headers expect).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    user-experienceEnsuring that users have a good experience using the library

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions