Add path and query handling to URIBuilder

This commit is contained in:
Ian Cordasco 2017-03-12 20:20:08 -05:00
parent 3936f8a7fd
commit 3f8cb0c4cc
No known key found for this signature in database
GPG Key ID: 656D3395E4A9791A
3 changed files with 187 additions and 0 deletions

View File

@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Module containing the logic for the URIBuilder object."""
from . import compat
from . import normalizers
@ -134,3 +135,115 @@ class URIBuilder(object):
query=self.query,
fragment=self.fragment,
)
def add_port(self, port):
"""Add port to the URI.
.. code-block:: python
>>> URIBuilder().add_port(80)
URIBuilder(scheme=None, userinfo=None, host=None, port='80',
path=None, query=None, fragment=None)
>>> URIBuilder().add_port(443)
URIBuilder(scheme=None, userinfo=None, host=None, port='443',
path=None, query=None, fragment=None)
"""
port_int = int(port)
if port_int < 0:
raise ValueError(
'ports are not allowed to be negative. You provided {}'.format(
port_int,
)
)
if port_int > 65535:
raise ValueError(
'ports are not allowed to be larger than 65535. '
'You provided {}'.format(
port_int,
)
)
return URIBuilder(
scheme=self.scheme,
userinfo=self.userinfo,
host=self.host,
port='{}'.format(port_int),
path=self.path,
query=self.query,
fragment=self.fragment,
)
def add_path(self, path):
"""Add a path to the URI.
.. code-block:: python
>>> URIBuilder().add_path('sigmavirus24/rfc3985')
URIBuilder(scheme=None, userinfo=None, host=None, port=None,
path='/sigmavirus24/rfc3986', query=None, fragment=None)
>>> URIBuilder().add_path('/checkout.php')
URIBuilder(scheme=None, userinfo=None, host=None, port=None,
path='/checkout.php', query=None, fragment=None)
"""
if not path.startswith('/'):
path = '/{}'.format(path)
return URIBuilder(
scheme=self.scheme,
userinfo=self.userinfo,
host=self.host,
port=self.port,
path=path,
query=self.query,
fragment=self.fragment,
)
def add_query_from(self, query_items):
"""Generate and add a query a dictionary or list of tuples.
.. code-block:: python
>>> URIBuilder().add_query_from({'a': 'b c'})
URIBuilder(scheme=None, userinfo=None, host=None, port=None,
path=None, query='a=b+c', fragment=None)
>>> URIBuilder().add_query_from([('a', 'b c')])
URIBuilder(scheme=None, userinfo=None, host=None, port=None,
path=None, query='a=b+c', fragment=None)
"""
query = compat.urlencode(query_items)
return URIBuilder(
scheme=self.scheme,
userinfo=self.userinfo,
host=self.host,
port=self.port,
path=self.path,
query=query,
fragment=self.fragment,
)
def add_query(self, query):
"""Add a pre-formated query string to the URI.
.. code-block:: python
>>> URIBuilder().add_query('a=b&c=d')
URIBuilder(scheme=None, userinfo=None, host=None, port=None,
path=None, query='a=b&c=d', fragment=None)
"""
return URIBuilder(
scheme=self.scheme,
userinfo=self.userinfo,
host=self.host,
port=self.port,
path=self.path,
query=query,
fragment=self.fragment,
)

View File

@ -20,6 +20,11 @@ try:
except ImportError: # Python 2.x
from urllib import quote as urlquote
try:
from urllib.parse import urlencode
except ImportError: # Python 2.x
from urllib import urlencode
__all__ = (
'to_bytes',
'to_str',

View File

@ -77,3 +77,72 @@ def test_add_host(hostname):
"""Verify we normalize hostnames in add_host."""
uribuilder = builder.URIBuilder().add_host(hostname)
assert uribuilder.host == 'google.com'
@pytest.mark.parametrize('port', [
-100,
'-100',
-1,
'-1',
65536,
'65536',
1000000,
'1000000',
'',
'abc',
'0b10',
])
def test_add_invalid_port(port):
"""Verify we raise a ValueError for invalid ports."""
with pytest.raises(ValueError):
builder.URIBuilder().add_port(port)
@pytest.mark.parametrize('port, expected', [
(0, '0'),
('0', '0'),
(1, '1'),
('1', '1'),
(22, '22'),
('22', '22'),
(80, '80'),
('80', '80'),
(443, '443'),
('443', '443'),
(65535, '65535'),
('65535', '65535'),
])
def test_add_port(port, expected):
"""Verify we normalize our port."""
uribuilder = builder.URIBuilder().add_port(port)
assert uribuilder.port == expected
@pytest.mark.parametrize('path', [
'sigmavirus24/rfc3986',
'/sigmavirus24/rfc3986',
])
def test_add_path(path):
"""Verify we normalize our path value."""
uribuilder = builder.URIBuilder().add_path(path)
assert uribuilder.path == '/sigmavirus24/rfc3986'
@pytest.mark.parametrize('query_items, expected', [
({'a': 'b c'}, 'a=b+c'),
({'a': 'b+c'}, 'a=b%2Bc'),
([('a', 'b c')], 'a=b+c'),
([('a', 'b+c')], 'a=b%2Bc'),
([('a', 'b'), ('c', 'd')], 'a=b&c=d'),
([('a', 'b'), ('username', '@d')], 'a=b&username=%40d'),
])
def test_add_query_from(query_items, expected):
"""Verify the behaviour of add_query_from."""
uribuilder = builder.URIBuilder().add_query_from(query_items)
assert uribuilder.query == expected
def test_add_query():
"""Verify we do not modify the provided query string."""
uribuilder = builder.URIBuilder().add_query('username=@foo')
assert uribuilder.query == 'username=@foo'