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

Move normalize header functions from _utils.py to _models.py #3382

Merged
merged 2 commits into from
Oct 30, 2024

Conversation

AstralScribe
Copy link
Contributor

Summary

Issue: #3381

This PR refactors the normalize_header_key as an inline method and moves normalize_header_value function to _models.py from _utils.py.

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.

@AstralScribe AstralScribe marked this pull request as draft October 30, 2024 11:29
@AstralScribe AstralScribe marked this pull request as ready for review October 30, 2024 11:29
@tomchristie
Copy link
Member

Thanks. ☺️

I'd suggest we should stay consistent and use _normalize_header_key() and _normalize_header_value() here.
There's perhaps some more cleanup we could do in this particular case, but that's probably the best starting point.

@AstralScribe
Copy link
Contributor Author

I have converted the inline method into a similar function.

@AstralScribe
Copy link
Contributor Author

I have done some more refactoring, but I am not sure if this simplifies or complicates it. I had to add some things due to mypy type checking.

def _convert_mapping_to_sequence(
    mappings: typing.Union[typing.Mapping[str, str], typing.Mapping[bytes, bytes]],
) -> typing.Sequence[typing.Tuple[str | bytes, str | bytes]]:
    return [(k, v) for k, v in mappings.items()]


def _normalize_headers(
    headers: HeaderTypes | None, encoding: str | None
) -> list[tuple[bytes, bytes, bytes]]:
    """
    Coerce str/bytes into a strictly byte-wise HTTP headers.
    """
    if headers is None:
        return []

    if isinstance(headers, Headers):
        return list(headers._list)

    normalized_list: list[tuple[bytes, bytes, bytes]] = []

    if isinstance(headers, typing.Mapping):
        n_headers = _convert_mapping_to_sequence(headers)
    elif isinstance(headers, typing.Sequence):
        n_headers = headers

    for key, value in n_headers:
        if not isinstance(value, (str, bytes)):
            raise TypeError(f"Header value must be str or bytes, not {type(value)}")
        b_key = key if isinstance(key, bytes) else key.encode(encoding or "ascii")
        b_value = (
            value if isinstance(value, bytes) else value.encode(encoding or "ascii")
        )
        normalized_list.append((b_key, b_key.lower(), b_value))

    return normalized_list

It replaces the whole init with:

self._list = _normalize_headers(headers, encoding)

Copy link
Member

@tomchristie tomchristie left a comment

Choose a reason for hiding this comment

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

Exactly like this, yep. 👍
Just helps keep things neat & localised.

@tomchristie tomchristie added the refactor Issues and PRs related to code refactoring label Oct 30, 2024
@tomchristie tomchristie merged commit 83a8518 into encode:master Oct 30, 2024
5 checks passed
@tomchristie
Copy link
Member

Thanks @AstralScribe. 😊

I have done some more refactoring, but I am not sure if this simplifies or complicates it. I had to add some things due to mypy type checking.

Let's take a pass on that particular follow-up. What you've got here is great as it is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
refactor Issues and PRs related to code refactoring
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants