diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst --- a/Doc/library/urllib.request.rst +++ b/Doc/library/urllib.request.rst @@ -396,6 +396,12 @@ The original URL passed to the constructor. + .. versionchanged:: 3.4 + + Request.full_url is a property with setter, getter and a deleter. Getting + :attr:`~Request.full_url` returns the original request URL with the + fragment, if it was present. + .. attribute:: Request.type The URI scheme. @@ -482,6 +488,10 @@ Return the URL given in the constructor. + .. versionchanged:: 3.4 + + Returns :attr:`Request.full_url` + .. method:: Request.set_proxy(host, type) diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py --- a/Lib/test/test_urllib2.py +++ b/Lib/test/test_urllib2.py @@ -11,6 +11,7 @@ # The proxy bypass method imported below has logic specific to the OSX # proxy config data structure but is testable on all platforms. from urllib.request import Request, OpenerDirector, _proxy_bypass_macosx_sysconf +from urllib.parse import urlparse import urllib.error # XXX @@ -919,7 +920,13 @@ r = Request('http://example.com') for url in urls: r.full_url = url + parsed = urlparse(url) + self.assertEqual(r.get_full_url(), url) + # full_url setter uses splittag to split into components. + # splittag sets the fragment as None while urlparse sets it to '' + self.assertEqual(r.fragment or '', parsed.fragment) + self.assertEqual(urlparse(r.get_full_url()).query, parsed.query) def test_full_url_deleter(self): r = Request('http://www.example.com') @@ -1537,6 +1544,14 @@ req = Request(url) self.assertEqual(req.get_full_url(), url) + def test_url_fullurl_get_full_url(self): + urls = ['http://docs.python.org', + 'http://docs.python.org/library/urllib2.html#OK', + 'http://www.python.org/?qs=query#fragment=true' ] + for url in urls: + req = Request(url) + self.assertEqual(req.get_full_url(), req.full_url) + def test_main(verbose=None): from test import test_urllib2 support.run_doctest(test_urllib2, verbose) diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -164,6 +164,14 @@ self.assertEqual(res.geturl(), "http://docs.python.org/2/glossary.html#glossary") + def test_redirect_url_withfrag(self): + redirect_url_with_frag = "http://bitly.com/urllibredirecttest" + with support.transient_internet(redirect_url_with_frag): + req = urllib.request.Request(redirect_url_with_frag) + res = urllib.request.urlopen(req) + self.assertEqual(res.geturl(), + "http://docs.python.org/3.4/glossary.html#term-global-interpreter-lock") + def test_custom_headers(self): url = "http://www.example.com" with support.transient_internet(url): diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py --- a/Lib/urllib/request.py +++ b/Lib/urllib/request.py @@ -275,6 +275,8 @@ @property def full_url(self): + if self.fragment: + return '{}#{}'.format(self._full_url, self.fragment) return self._full_url @full_url.setter @@ -326,8 +328,6 @@ return "GET" def get_full_url(self): - if self.fragment: - return '{}#{}'.format(self.full_url, self.fragment) return self.full_url def set_proxy(self, host, type):