diff --git a/CHANGES.rst b/CHANGES.rst index 8a3e3b6f..0862d58b 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -18,6 +18,8 @@ CHANGES * Fix quoting of plus in path by pure python version (#339) +* Don't create a new URL if fragment is unchanged (#292) + 1.3.0 (2018-12-11) ------------------ diff --git a/setup.cfg b/setup.cfg index c8d13489..13ac0a90 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,7 +12,7 @@ junit_suite_name = yarl_test_suite [flake8] -ignore = E301,E302,E704,W503,W504 +ignore = E301,E302,E704,W503,W504,F811 max-line-length = 88 [mypy] diff --git a/tests/test_url.py b/tests/test_url.py index b139f95f..100fce52 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -668,6 +668,18 @@ def test_with_fragment_None(): assert str(url2) == "http://example.com/path" +def test_with_fragment_None_matching(): + url = URL("http://example.com/path") + url2 = url.with_fragment(None) + assert url is url2 + + +def test_with_fragment_matching(): + url = URL("http://example.com/path#frag") + url2 = url.with_fragment("frag") + assert url is url2 + + def test_with_fragment_bad_type(): url = URL("http://example.com") with pytest.raises(TypeError): diff --git a/yarl/__init__.py b/yarl/__init__.py index 05968735..62f81056 100644 --- a/yarl/__init__.py +++ b/yarl/__init__.py @@ -913,12 +913,14 @@ def with_fragment(self, fragment): """ # N.B. doesn't cleanup query/fragment if fragment is None: - fragment = "" + raw_fragment = "" elif not isinstance(fragment, str): raise TypeError("Invalid fragment type") - return URL( - self._val._replace(fragment=self._FRAGMENT_QUOTER(fragment)), encoded=True - ) + else: + raw_fragment = self._FRAGMENT_QUOTER(fragment) + if self.raw_fragment == raw_fragment: + return self + return URL(self._val._replace(fragment=raw_fragment), encoded=True) def with_name(self, name): """Return a new URL with name (last part of path) replaced. diff --git a/yarl/__init__.pyi b/yarl/__init__.pyi index f3a1da35..69e4a66f 100644 --- a/yarl/__init__.pyi +++ b/yarl/__init__.pyi @@ -68,11 +68,11 @@ class URL: def with_path(self, path: str, *, encoded: bool = ...) -> URL: ... @overload def with_query(self, query: Query) -> URL: ... - @overload # noqa: F811 + @overload def with_query(self, **kwargs: QueryVariable) -> URL: ... @overload def update_query(self, query: Query) -> URL: ... - @overload # noqa: F811 + @overload def update_query(self, **kwargs: QueryVariable) -> URL: ... def with_fragment(self, fragment: Optional[str]) -> URL: ... def with_name(self, name: str) -> URL: ...