diff --git a/CHANGES/862.bugfix.rst b/CHANGES/862.bugfix.rst new file mode 100644 index 000000000..04bff12f5 --- /dev/null +++ b/CHANGES/862.bugfix.rst @@ -0,0 +1 @@ +Stopped dropping trailing slashes in ``URL.joinpath``. diff --git a/tests/test_url.py b/tests/test_url.py index 3b9a5892c..1981b20eb 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -810,6 +810,21 @@ def test_div_with_dots(): "http://example.com/path/to", id="cleanup-query-and-fragment", ), + pytest.param("", ("path/",), "http://example.com/path/", id="trailing-slash"), + pytest.param( + "", ("path/", "to/"), "http://example.com/path/to/", id="duplicate-slash" + ), + pytest.param("", (), "http://example.com", id="empty-segments"), + pytest.param( + "/", ("path/",), "http://example.com/path/", id="base-slash-trailing-slash" + ), + pytest.param( + "/", + ("path/", "to/"), + "http://example.com/path/to/", + id="base-slash-duplicate-slash", + ), + pytest.param("/", (), "http://example.com", id="base-slash-empty-segments"), ], ) def test_joinpath(base, to_join, expected): @@ -824,6 +839,9 @@ def test_joinpath(base, to_join, expected): pytest.param(URL("a"), ("b",), ("a", "b"), id="relative-path"), pytest.param(URL("a"), ("b", "", "c"), ("a", "b", "c"), id="empty-element"), pytest.param(URL("/a"), ("b"), ("/", "a", "b"), id="absolute-path"), + pytest.param(URL(), ("a/",), ("a", ""), id="trailing-slash"), + pytest.param(URL(), ("a/", "b/"), ("a", "b", ""), id="duplicate-slash"), + pytest.param(URL(), (), ("",), id="empty-segments"), ], ) def test_joinpath_relative(url, to_join, expected): diff --git a/yarl/_url.py b/yarl/_url.py index d18a4599d..74190d929 100644 --- a/yarl/_url.py +++ b/yarl/_url.py @@ -713,7 +713,8 @@ def _validate_authority_uri_abs_path(host, path): def _make_child(self, segments, encoded=False): """add segments to self._val.path, accounting for absolute vs relative paths""" - parsed = [] + # keep the trailing slash if the last segment ends with / + parsed = [""] if segments and segments[-1][-1:] == "/" else [] for seg in reversed(segments): if not seg: continue