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

Extract _make_netloc from URL object #1351

Merged
merged 6 commits into from
Oct 21, 2024
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 47 additions & 47 deletions yarl/_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
None, str, "Mapping[str, QueryVariable]", "Sequence[Tuple[str, QueryVariable]]"
]
_T = TypeVar("_T")
_QUOTER_NO_REQUOTE = _Quoter(requote=False)
bdraco marked this conversation as resolved.
Show resolved Hide resolved

if sys.version_info >= (3, 11):
from typing import Self
Expand Down Expand Up @@ -360,6 +361,40 @@ def _unsplit_result(
return f"{url}#{fragment}" if fragment else url


@lru_cache # match the same size as urlsplit
def _make_netloc(
user: Union[str, None],
password: Union[str, None],
host: Union[str, None],
port: Union[int, None],
encode: bool = False,
) -> str:
"""Make netloc from parts.

The user and password are encoded if encode is True.

The host must already be encoded with _encode_host.
"""
if host is None:
return ""
ret = host
if port is not None:
ret = f"{ret}:{port}"
if user is None and password is None:
return ret
if password is not None:
if not user:
user = ""
elif encode:
user = _QUOTER_NO_REQUOTE(user)
if encode:
password = _QUOTER_NO_REQUOTE(password)
user = f"{user}:{password}"
elif user and encode:
user = _QUOTER_NO_REQUOTE(user)
return f"{user}@{ret}" if user else ret


def _query_var(v: QueryVariable) -> str:
cls = type(v)
if cls is int: # Fast path for non-subclassed int
Expand Down Expand Up @@ -458,7 +493,7 @@ class URL:
# absolute-URI = scheme ":" hier-part [ "?" query ]
__slots__ = ("_cache", "_val")

_QUOTER = _Quoter(requote=False)
_QUOTER = _QUOTER_NO_REQUOTE
bdraco marked this conversation as resolved.
Show resolved Hide resolved
_REQUOTER = _Quoter()
_PATH_QUOTER = _Quoter(safe="@:", protected="/+", requote=False)
_PATH_REQUOTER = _Quoter(safe="@:", protected="/+")
Expand Down Expand Up @@ -534,7 +569,7 @@ def __new__(
else:
raw_user = cls._REQUOTER(username) if username else username
raw_password = cls._REQUOTER(password) if password else password
netloc = cls._make_netloc(raw_user, raw_password, host, port)
netloc = _make_netloc(raw_user, raw_password, host, port)
cache["raw_user"] = raw_user
cache["raw_password"] = raw_password

Expand Down Expand Up @@ -623,7 +658,7 @@ def build(
if user is None and password is None:
netloc = host if port is None else f"{host}:{port}"
else:
netloc = cls._make_netloc(user, password, host, port)
netloc = _make_netloc(user, password, host, port)
else:
netloc = ""
else: # not encoded
Expand All @@ -642,7 +677,7 @@ def build(
if user is None and password is None:
netloc = _host if port is None else f"{_host}:{port}"
else:
netloc = cls._make_netloc(user, password, _host, port, True)
netloc = _make_netloc(user, password, _host, port, True)

path = cls._PATH_QUOTER(path) if path else path
if path and netloc:
Expand Down Expand Up @@ -695,7 +730,7 @@ def __str__(self) -> str:
# port normalization - using None for default ports to remove from rendering
# https://datatracker.ietf.org/doc/html/rfc3986.html#section-6.2.3
host = self.host_subcomponent
netloc = self._make_netloc(self.raw_user, self.raw_password, host, None)
netloc = _make_netloc(self.raw_user, self.raw_password, host, None)
return _unsplit_result(scheme, netloc, path, query, fragment)

def __repr__(self) -> str:
Expand Down Expand Up @@ -828,7 +863,7 @@ def _origin(self) -> "URL":
raise ValueError("URL should have scheme")
if "@" in netloc:
encoded_host = self.host_subcomponent
netloc = self._make_netloc(None, None, encoded_host, self.explicit_port)
netloc = _make_netloc(None, None, encoded_host, self.explicit_port)
elif not path and not query and not fragment:
return self
return self._from_tup((scheme, netloc, "", "", ""))
Expand Down Expand Up @@ -888,7 +923,7 @@ def authority(self) -> str:
Empty string for relative URLs.

"""
return self._make_netloc(self.user, self.password, self.host, self.port)
return _make_netloc(self.user, self.password, self.host, self.port)

@cached_property
def raw_user(self) -> Union[str, None]:
Expand Down Expand Up @@ -1231,41 +1266,6 @@ def _normalize_path(path: str) -> str:
segments = path.split("/")
return prefix + "/".join(_normalize_path_segments(segments))

@classmethod
@lru_cache # match the same size as urlsplit
def _make_netloc(
cls,
user: Union[str, None],
password: Union[str, None],
host: Union[str, None],
port: Union[int, None],
encode: bool = False,
) -> str:
"""Make netloc from parts.

The user and password are encoded if encode is True.

The host must already be encoded with _encode_host.
"""
if host is None:
return ""
ret = host
if port is not None:
ret = f"{ret}:{port}"
if user is None and password is None:
return ret
if password is not None:
if not user:
user = ""
elif encode:
user = cls._QUOTER(user)
if encode:
password = cls._QUOTER(password)
user = f"{user}:{password}"
elif user and encode:
user = cls._QUOTER(user)
return f"{user}@{ret}" if user else ret

def with_scheme(self, scheme: str) -> "URL":
"""Return a new URL with scheme replaced."""
# N.B. doesn't cleanup query/fragment
Expand Down Expand Up @@ -1301,7 +1301,7 @@ def with_user(self, user: Union[str, None]) -> "URL":
if not netloc:
raise ValueError("user replacement is not allowed for relative URLs")
encoded_host = self.host_subcomponent or ""
netloc = self._make_netloc(user, password, encoded_host, self.explicit_port)
netloc = _make_netloc(user, password, encoded_host, self.explicit_port)
return self._from_tup((scheme, netloc, path, query, fragment))

def with_password(self, password: Union[str, None]) -> "URL":
Expand All @@ -1324,7 +1324,7 @@ def with_password(self, password: Union[str, None]) -> "URL":
raise ValueError("password replacement is not allowed for relative URLs")
encoded_host = self.host_subcomponent or ""
port = self.explicit_port
netloc = self._make_netloc(self.raw_user, password, encoded_host, port)
netloc = _make_netloc(self.raw_user, password, encoded_host, port)
return self._from_tup((scheme, netloc, path, query, fragment))

def with_host(self, host: str) -> "URL":
Expand All @@ -1346,7 +1346,7 @@ def with_host(self, host: str) -> "URL":
raise ValueError("host removing is not allowed")
encoded_host = _encode_host(host, validate_host=True) if host else ""
port = self.explicit_port
netloc = self._make_netloc(self.raw_user, self.raw_password, encoded_host, port)
netloc = _make_netloc(self.raw_user, self.raw_password, encoded_host, port)
return self._from_tup((scheme, netloc, path, query, fragment))

def with_port(self, port: Union[int, None]) -> "URL":
Expand All @@ -1365,7 +1365,7 @@ def with_port(self, port: Union[int, None]) -> "URL":
if not netloc:
raise ValueError("port replacement is not allowed for relative URLs")
encoded_host = self.host_subcomponent or ""
netloc = self._make_netloc(self.raw_user, self.raw_password, encoded_host, port)
netloc = _make_netloc(self.raw_user, self.raw_password, encoded_host, port)
return self._from_tup((scheme, netloc, path, query, fragment))

def with_path(self, path: str, *, encoded: bool = False) -> "URL":
Expand Down Expand Up @@ -1719,7 +1719,7 @@ def human_repr(self) -> str:
fragment = _human_quote(self.fragment, "")
if TYPE_CHECKING:
assert fragment is not None
netloc = self._make_netloc(user, password, host, self.explicit_port)
netloc = _make_netloc(user, password, host, self.explicit_port)
scheme = self._val.scheme
return _unsplit_result(scheme, netloc, path, query_string, fragment)

Expand Down
Loading