diff --git a/docs/source/release-notes/unreleased.rst b/docs/source/release-notes/unreleased.rst index 09b03b4..a094250 100644 --- a/docs/source/release-notes/unreleased.rst +++ b/docs/source/release-notes/unreleased.rst @@ -1,6 +1,7 @@ 2.x.y - 202z-aa-bb ------------------ -- *Add Items here* +- Fix ``ParseResultBytes.unsplit()`` raising ``AttributeError`` for + references without an authority, such as ``/a`` or ``mailto:x``. .. links below here diff --git a/src/rfc3986/parseresult.py b/src/rfc3986/parseresult.py index 551d1c6..168045f 100644 --- a/src/rfc3986/parseresult.py +++ b/src/rfc3986/parseresult.py @@ -404,9 +404,12 @@ def from_string( ) @property - def authority(self) -> bytes: + def authority(self) -> t.Optional[bytes]: """Return the normalized authority.""" - return self.reference.authority.encode(self.encoding) + authority = self.reference.authority + if authority is None: + return None + return authority.encode(self.encoding) def copy_with( self, diff --git a/tests/test_parseresult.py b/tests/test_parseresult.py index 5788448..3217898 100644 --- a/tests/test_parseresult.py +++ b/tests/test_parseresult.py @@ -166,6 +166,18 @@ def test_unsplit(self): idna_encoded = SNOWMAN_IDNA_HOST.encode("utf-8") + b"/path" assert uri.unsplit(use_idna=True) == idna_encoded + @pytest.mark.parametrize( + "reference", [b"/a", b"a", b"mailto:x", b"?q", b"#f"] + ) + def test_unsplit_reference_without_authority(self, reference): + uri = pr.ParseResultBytes.from_string(reference) + assert uri.authority is None + assert uri.unsplit() == reference + assert ( + pr.ParseResult.from_string(reference.decode()).unsplit() + == reference.decode() + ) + def test_eager_normalization_from_string(self): uri = pr.ParseResultBytes.from_string( b"http://" + SNOWMAN + b".com/path",