From 4e1fd8154a7b9209064cd1fba8a73d026fd87374 Mon Sep 17 00:00:00 2001 From: Miro <200482516+Mirochill@users.noreply.github.com> Date: Tue, 19 May 2026 21:23:00 +0200 Subject: [PATCH] Reject text paths in decoded replace --- src/hyperlink/_url.py | 4 ++++ src/hyperlink/test/test_url.py | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/hyperlink/_url.py b/src/hyperlink/_url.py index 8797b5cc..dccf55e2 100644 --- a/src/hyperlink/_url.py +++ b/src/hyperlink/_url.py @@ -2265,6 +2265,10 @@ def replace( automatically encoded instead of an error being raised. """ if path is not _UNSET: + if isinstance(path, Text): + raise TypeError( + "expected iterable of text for path, not: %r" % (path,) + ) path = tuple(_encode_reserved(p) for p in path) if query is not _UNSET: query = cast( diff --git a/src/hyperlink/test/test_url.py b/src/hyperlink/test/test_url.py index 37c91726..5c00cad3 100644 --- a/src/hyperlink/test/test_url.py +++ b/src/hyperlink/test/test_url.py @@ -1023,6 +1023,18 @@ def test_technicallyTextIsIterableBut(self): "expected iterable of text for path, not: {0}".format(repr("foo")), ) + decoded_url = URL.from_text( + "https://example.com/api/v1/webui" + ).get_decoded_url() + with self.assertRaises(TypeError) as raised: + decoded_url.replace(path="support/woo") + self.assertEqual( + str(raised.exception), + "expected iterable of text for path, not: {0}".format( + repr("support/woo") + ), + ) + def test_netloc(self): # type: () -> None url = URL(scheme="https")