# -*- coding: utf-8 -*- # Copyright (c) 2015 Ian Stapleton Cordasco # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import rfc3986 from rfc3986 import exceptions from rfc3986 import parseresult as pr import pytest from . import base INVALID_PORTS = ['443:80', '443:80:443', 'abcdef', 'port', '43port'] SNOWMAN = b'\xe2\x98\x83' SNOWMAN_IDNA_HOST = 'http://xn--n3h.com' @pytest.mark.parametrize('port', INVALID_PORTS) def test_port_parsing(port): with pytest.raises(exceptions.InvalidPort): rfc3986.urlparse('https://httpbin.org:{0}/get'.format(port)) @pytest.mark.parametrize('parts, unsplit', [ (('https', None, 'httpbin.org'), u'https://httpbin.org'), (('https', 'user', 'httpbin.org'), u'https://user@httpbin.org'), (('https', None, 'httpbin.org', 443, '/get'), u'https://httpbin.org:443/get'), (('HTTPS', None, 'HTTPBIN.ORG'), u'https://httpbin.org'), ]) def test_from_parts(parts, unsplit): uri = pr.ParseResult.from_parts(*parts) assert uri.unsplit() == unsplit @pytest.mark.parametrize('parts, unsplit', [ (('https', None, 'httpbin.org'), b'https://httpbin.org'), (('https', 'user', 'httpbin.org'), b'https://user@httpbin.org'), (('https', None, 'httpbin.org', 443, '/get'), b'https://httpbin.org:443/get'), (('HTTPS', None, 'HTTPBIN.ORG'), b'https://httpbin.org'), ]) def test_bytes_from_parts(parts, unsplit): uri = pr.ParseResultBytes.from_parts(*parts) assert uri.unsplit() == unsplit class TestParseResultParsesURIs(base.BaseTestParsesURIs): test_class = pr.ParseResult class TestParseResultUnsplits(base.BaseTestUnsplits): test_class = pr.ParseResult def test_normalizes_uris_when_using_from_string(uri_to_normalize): """Verify we always get the same thing out as we expect.""" result = pr.ParseResult.from_string(uri_to_normalize, lazy_normalize=False) assert result.scheme == 'https' assert result.host == 'example.com' class TestStdlibShims: def test_uri_with_everything(self, uri_with_everything): uri = pr.ParseResult.from_string(uri_with_everything) assert uri.host == uri.hostname assert uri.netloc == uri.authority assert uri.query == uri.params assert uri.geturl() == uri.unsplit() def test_creates_a_copy_with_a_new_path(uri_with_everything): uri = pr.ParseResult.from_string(uri_with_everything) new_uri = uri.copy_with(path='/parse/result/tests/are/fun') assert new_uri.path == '/parse/result/tests/are/fun' def test_creates_a_copy_with_a_new_port(basic_uri): uri = pr.ParseResult.from_string(basic_uri) new_uri = uri.copy_with(port=443) assert new_uri.port == 443 def test_parse_result_encodes_itself(uri_with_everything): uri = pr.ParseResult.from_string(uri_with_everything) uribytes = uri.encode() encoding = uri.encoding assert uri.scheme.encode(encoding) == uribytes.scheme assert uri.userinfo.encode(encoding) == uribytes.userinfo assert uri.host.encode(encoding) == uribytes.host assert uri.port == uribytes.port assert uri.path.encode(encoding) == uribytes.path assert uri.query.encode(encoding) == uribytes.query assert uri.fragment.encode(encoding) == uribytes.fragment class TestParseResultBytes: def test_handles_uri_with_everything(self, uri_with_everything): uri = pr.ParseResultBytes.from_string(uri_with_everything) assert uri.scheme == b'https' assert uri.path == b'/path/to/resource' assert uri.query == b'key=value' assert uri.fragment == b'fragment' assert uri.userinfo == b'user:pass' assert uri.port == 443 assert isinstance(uri.authority, bytes) is True def test_raises_invalid_authority_for_invalid_uris(self, invalid_uri): with pytest.raises(exceptions.InvalidAuthority): pr.ParseResultBytes.from_string(invalid_uri) @pytest.mark.parametrize('port', INVALID_PORTS) def test_raises_invalid_port_non_strict_parse(self, port): with pytest.raises(exceptions.InvalidPort): pr.ParseResultBytes.from_string( 'https://httpbin.org:{0}/get'.format(port), strict=False ) def test_copy_with_a_new_path(self, uri_with_everything): uri = pr.ParseResultBytes.from_string(uri_with_everything) new_uri = uri.copy_with(path=b'/parse/result/tests/are/fun') assert new_uri.path == b'/parse/result/tests/are/fun' def test_copy_with_a_new_unicode_path(self, uri_with_everything): uri = pr.ParseResultBytes.from_string(uri_with_everything) pathbytes = b'/parse/result/tests/are/fun' + SNOWMAN new_uri = uri.copy_with(path=pathbytes.decode('utf-8')) assert new_uri.path == (b'/parse/result/tests/are/fun' + SNOWMAN) def test_unsplit(self): uri = pr.ParseResultBytes.from_string( b'http://' + SNOWMAN + b'.com/path', strict=False ) idna_encoded = SNOWMAN_IDNA_HOST.encode('utf-8') + b'/path' assert uri.unsplit(use_idna=True) == idna_encoded def test_eager_normalization_from_string(self): uri = pr.ParseResultBytes.from_string( b'http://' + SNOWMAN + b'.com/path', strict=False, lazy_normalize=False, ) assert uri.unsplit() == b'http:/path' def test_eager_normalization_from_parts(self): uri = pr.ParseResultBytes.from_parts( scheme='http', host=SNOWMAN.decode('utf-8'), path='/path', lazy_normalize=False, ) assert uri.unsplit() == b'http:/path'