Skip to content

Commit

Permalink
Small speed up to normalizing the path (#1137)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Sep 9, 2024
1 parent 07c4e03 commit 1e969ab
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGES/1137.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improved performance of normalizing paths -- by :user:`bdraco`.
2 changes: 2 additions & 0 deletions tests/test_normalize_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
("/", "/"),
("//", "//"),
("///", "///"),
("path", "path"),
# Single-dot
("path/to", "path/to"),
("././path/to", "path/to"),
("path/./to", "path/to"),
("path/././to", "path/to"),
("path/to/.", "path/to/"),
("path/to/./.", "path/to/"),
("/path/to/.", "/path/to/"),
# Double-dots
("../path/to", "path/to"),
("path/../to", "to"),
Expand Down
29 changes: 29 additions & 0 deletions tests/test_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,35 @@ def test_joinpath_path_starting_from_slash_is_forbidden():
assert url.joinpath("/to/others")


PATHS = [
# No dots
("", ""),
("path", "path"),
# Single-dot
("path/to", "path/to"),
("././path/to", "path/to"),
("path/./to", "path/to"),
("path/././to", "path/to"),
("path/to/.", "path/to/"),
("path/to/./.", "path/to/"),
# Double-dots
("../path/to", "path/to"),
("path/../to", "to"),
("path/../../to", "to"),
# Non-ASCII characters
("μονοπάτι/../../να/ᴜɴɪ/ᴄᴏᴅᴇ", "να/ᴜɴɪ/ᴄᴏᴅᴇ"),
("μονοπάτι/../../να/𝕦𝕟𝕚/𝕔𝕠𝕕𝕖/.", "να/𝕦𝕟𝕚/𝕔𝕠𝕕𝕖/"),
]


@pytest.mark.parametrize("original,expected", PATHS)
def test_join_path_normalized(original: str, expected: str) -> None:
"""Test that joinpath normalizes paths."""
base_url = URL("http://example.com")
new_url = base_url.joinpath(original)
assert new_url.path == f"/{expected}"


# with_path


Expand Down
5 changes: 4 additions & 1 deletion yarl/_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,9 +899,12 @@ def _make_child(self, paths: "Sequence[str]", encoded: bool = False) -> "URL":
@classmethod
def _normalize_path(cls, path: str) -> str:
# Drop '.' and '..' from str path
if "." not in path:
# No need to normalize if there are no '.' or '..' segments
return path

prefix = ""
if path.startswith("/"):
if path and path[0] == "/":
# preserve the "/" root element of absolute paths, copying it to the
# normalised output as per sections 5.2.4 and 6.2.2.3 of rfc3986.
prefix = "/"
Expand Down

0 comments on commit 1e969ab

Please sign in to comment.