Skip to content

Commit 558e4b0

Browse files
authored
Improve performance of path functions on cache miss (#1443)
1 parent 7585a96 commit 558e4b0

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

CHANGES/1443.misc.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improved performances of multiple path method on cache miss -- by :user:`bdraco`.

tests/test_url.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,17 @@ def test_path_safe_with_25():
461461
assert unquoted == "/foo/bar%2Fbaz"
462462

463463

464+
def test_path_safe_with_no_netloc():
465+
"""Path safe should not decode %2F, otherwise it may look like a path separator."""
466+
467+
url = URL("/foo/bar%2fbaz")
468+
assert url.path_safe == "/foo/bar%2Fbaz"
469+
url = URL("")
470+
assert url.path_safe == ""
471+
url = URL("http://example.com")
472+
assert url.path_safe == "/"
473+
474+
464475
@pytest.mark.parametrize(
465476
"original_path",
466477
[
@@ -513,6 +524,12 @@ def test_path_qs():
513524
assert url.path_qs == "/?б=в&ю=к"
514525
url = URL("http://example.com/path?б=в&ю=к")
515526
assert url.path_qs == "/path?б=в&ю=к"
527+
url = URL("/path?б=в&ю=к")
528+
assert url.path_qs == "/path?б=в&ю=к"
529+
url = URL("")
530+
assert url.path_qs == ""
531+
url = URL("http://example.com")
532+
assert url.path_qs == "/"
516533

517534

518535
def test_raw_path_qs():
@@ -524,6 +541,12 @@ def test_raw_path_qs():
524541
assert url.raw_path_qs == "/path?%D0%B1=%D0%B2&%D1%8E=%D0%BA"
525542
url = URL("http://example.com/шлях?a=1&b=2")
526543
assert url.raw_path_qs == "/%D1%88%D0%BB%D1%8F%D1%85?a=1&b=2"
544+
url = URL("/шлях?a=1&b=2")
545+
assert url.raw_path_qs == "/%D1%88%D0%BB%D1%8F%D1%85?a=1&b=2"
546+
url = URL("")
547+
assert url.raw_path_qs == ""
548+
url = URL("http://example.com")
549+
assert url.raw_path_qs == "/"
527550

528551

529552
def test_query_string_spaces():

yarl/_url.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -790,14 +790,14 @@ def host_port_subcomponent(self) -> Union[str, None]:
790790
"""
791791
if (raw := self.raw_host) is None:
792792
return None
793-
port = self.explicit_port
794793
if raw[-1] == ".":
795794
# Remove all trailing dots from the netloc as while
796795
# they are valid FQDNs in DNS, TLS validation fails.
797796
# See https://github.com/aio-libs/aiohttp/issues/3636.
798797
# To avoid string manipulation we only call rstrip if
799798
# the last character is a dot.
800799
raw = raw.rstrip(".")
800+
port = self.explicit_port
801801
if port is None or port == DEFAULT_PORTS.get(self._scheme):
802802
return f"[{raw}]" if ":" in raw else raw
803803
return f"[{raw}]:{port}" if ":" in raw else f"{raw}:{port}"
@@ -831,7 +831,7 @@ def raw_path(self) -> str:
831831
/ for absolute URLs without path part.
832832
833833
"""
834-
return "/" if not self._path and self._netloc else self._path
834+
return self._path if self._path or not self._netloc else "/"
835835

836836
@cached_property
837837
def path(self) -> str:
@@ -840,7 +840,7 @@ def path(self) -> str:
840840
/ for absolute URLs without path part.
841841
842842
"""
843-
return PATH_UNQUOTER(self.raw_path)
843+
return PATH_UNQUOTER(self._path) if self._path else "/" if self._netloc else ""
844844

845845
@cached_property
846846
def path_safe(self) -> str:
@@ -851,7 +851,9 @@ def path_safe(self) -> str:
851851
/ (%2F) and % (%25) are not decoded
852852
853853
"""
854-
return PATH_SAFE_UNQUOTER(self.raw_path)
854+
if self._path:
855+
return PATH_SAFE_UNQUOTER(self._path)
856+
return "/" if self._netloc else ""
855857

856858
@cached_property
857859
def _parsed_query(self) -> list[tuple[str, str]]:
@@ -884,7 +886,7 @@ def query_string(self) -> str:
884886
Empty string if query is missing.
885887
886888
"""
887-
return QS_UNQUOTER(self._query)
889+
return QS_UNQUOTER(self._query) if self._query else ""
888890

889891
@cached_property
890892
def path_qs(self) -> str:
@@ -894,8 +896,9 @@ def path_qs(self) -> str:
894896
@cached_property
895897
def raw_path_qs(self) -> str:
896898
"""Encoded path of URL with query."""
897-
query = self._query
898-
return self.raw_path if not query else f"{self.raw_path}?{query}"
899+
if q := self._query:
900+
return f"{self._path}?{q}" if self._path or not self._netloc else f"/?{q}"
901+
return self._path if self._path or not self._netloc else "/"
899902

900903
@cached_property
901904
def raw_fragment(self) -> str:
@@ -913,7 +916,7 @@ def fragment(self) -> str:
913916
Empty string if fragment is missing.
914917
915918
"""
916-
return UNQUOTER(self._fragment)
919+
return UNQUOTER(self._fragment) if self._fragment else ""
917920

918921
@cached_property
919922
def raw_parts(self) -> tuple[str, ...]:

0 commit comments

Comments
 (0)