From f978d5e2682fbd61a11eb7798534f4589d694c15 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Sep 2024 11:09:39 -1000 Subject: [PATCH] Improve performance of handling ports in the URL (#1081) --- CHANGES/1081.misc.rst | 1 + yarl/_url.py | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 CHANGES/1081.misc.rst diff --git a/CHANGES/1081.misc.rst b/CHANGES/1081.misc.rst new file mode 100644 index 000000000..a61cc589f --- /dev/null +++ b/CHANGES/1081.misc.rst @@ -0,0 +1 @@ +Improved performance of handling ports -- by :user:`bdraco`. diff --git a/yarl/_url.py b/yarl/_url.py index 9f5672eec..22d323416 100644 --- a/yarl/_url.py +++ b/yarl/_url.py @@ -262,7 +262,7 @@ def __str__(self): val = self._val if not val.path and self.is_absolute() and (val.query or val.fragment): val = val._replace(path="/") - if (port := self._get_port()) is None: + if (port := self._port_not_default) is None: # port normalization - using None for default ports to remove from rendering # https://datatracker.ietf.org/doc/html/rfc3986.html#section-6.2.3 val = val._replace( @@ -371,7 +371,7 @@ def is_default_port(self): if self.explicit_port is None: # A relative URL does not have an implicit port / default port return self.port is not None - default = self._get_default_port() + default = self._default_port if default is None: return False return self.port == default @@ -421,17 +421,21 @@ def raw_authority(self): """ return self._val.netloc - def _get_default_port(self) -> Union[int, None]: + @cached_property + def _default_port(self) -> Union[int, None]: + """Default port for the scheme or None if not known.""" scheme = self.scheme if not scheme: return None return DEFAULT_PORTS.get(scheme) - def _get_port(self) -> Union[int, None]: - """Port or None if default port""" - if self._get_default_port() == self.port: + @cached_property + def _port_not_default(self) -> Union[int, None]: + """The port part of URL normalized to None if its the default port.""" + port = self.port + if self._default_port == port: return None - return self.port + return port @cached_property def authority(self): @@ -520,9 +524,9 @@ def port(self): scheme without default port substitution. """ - return self._val.port or self._get_default_port() + return self.explicit_port or self._default_port - @property + @cached_property def explicit_port(self): """Port part of URL, without scheme-based fallback. @@ -1142,7 +1146,7 @@ def human_repr(self): user, password, host, - self._val.port, + self.explicit_port, encode_host=False, ), path,