diff --git a/Makefile b/Makefile
index dea33a3f..60b5e000 100644
--- a/Makefile
+++ b/Makefile
@@ -6,10 +6,10 @@ init:
test:
# This runs all of the tests. To run an individual test, run py.test with
# the -k flag, like "py.test -k test_path_is_not_double_encoded"
- py.test test_requests.py
+ py.test tests
coverage:
- py.test --verbose --cov-report term --cov=requests test_requests.py
+ py.test --verbose --cov-report term --cov=requests tests
ci: init
py.test --junitxml=junit.xml
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 00000000..57d631c3
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1 @@
+# coding: utf-8
diff --git a/tests/compat.py b/tests/compat.py
new file mode 100644
index 00000000..a26bd9f4
--- /dev/null
+++ b/tests/compat.py
@@ -0,0 +1,20 @@
+# coding: utf-8
+from requests.compat import is_py3
+
+
+try:
+ import StringIO
+except ImportError:
+ import io as StringIO
+
+try:
+ from cStringIO import StringIO as cStringIO
+except ImportError:
+ cStringIO = None
+
+if is_py3:
+ def u(s):
+ return s
+else:
+ def u(s):
+ return s.decode('unicode-escape')
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 00000000..af20e54d
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,23 @@
+# coding: utf-8
+import pytest
+from requests.compat import urljoin
+
+
+def prepare_url(value):
+ # Issue #1483: Make sure the URL always has a trailing slash
+ httpbin_url = value.url.rstrip('/') + '/'
+
+ def inner(*suffix):
+ return urljoin(httpbin_url, '/'.join(suffix))
+
+ return inner
+
+
+@pytest.fixture
+def httpbin(httpbin):
+ return prepare_url(httpbin)
+
+
+@pytest.fixture
+def httpbin_secure(httpbin_secure):
+ return prepare_url(httpbin_secure)
diff --git a/test_requests.py b/tests/test_requests.py
similarity index 79%
rename from test_requests.py
rename to tests/test_requests.py
index 0193f06f..0d1ca049 100755
--- a/test_requests.py
+++ b/tests/test_requests.py
@@ -16,7 +16,7 @@ import pytest
from requests.adapters import HTTPAdapter
from requests.auth import HTTPDigestAuth, _basic_auth_str
from requests.compat import (
- Morsel, cookielib, getproxies, str, urljoin, urlparse, is_py3,
+ Morsel, cookielib, getproxies, str, urlparse,
builtin_str, OrderedDict)
from requests.cookies import cookiejar_from_dict, morsel_to_cookie
from requests.exceptions import (
@@ -28,45 +28,7 @@ from requests.sessions import SessionRedirectMixin
from requests.models import urlencode
from requests.hooks import default_hooks
-try:
- import StringIO
-except ImportError:
- import io as StringIO
-
-try:
- from multiprocessing.pool import ThreadPool
-except ImportError:
- ThreadPool = None
-
-if is_py3:
- def u(s):
- return s
-else:
- def u(s):
- return s.decode('unicode-escape')
-
-
-@pytest.fixture
-def httpbin(httpbin):
- # Issue #1483: Make sure the URL always has a trailing slash
- httpbin_url = httpbin.url.rstrip('/') + '/'
-
- def inner(*suffix):
- return urljoin(httpbin_url, '/'.join(suffix))
-
- return inner
-
-
-@pytest.fixture
-def httpsbin_url(httpbin_secure):
- # Issue #1483: Make sure the URL always has a trailing slash
- httpbin_url = httpbin_secure.url.rstrip('/') + '/'
-
- def inner(*suffix):
- return urljoin(httpbin_url, '/'.join(suffix))
-
- return inner
-
+from .compat import StringIO, u
# Requests to this URL should always fail with a connection timeout (nothing
# listening on that port)
@@ -344,8 +306,8 @@ class TestRequests:
r = s.get(url)
assert r.status_code == 200
- @pytest.mark.parametrize('url, exception',
- (
+ @pytest.mark.parametrize(
+ 'url, exception', (
# Connecting to an unknown domain should raise a ConnectionError
('http://doesnotexist.google.com', ConnectionError),
# Connecting to an invalid port should raise a ConnectionError
@@ -536,8 +498,8 @@ class TestRequests:
headers={str('Content-Type'): 'application/octet-stream'},
data='\xff') # compat.str is unicode.
- def test_pyopenssl_redirect(self, httpsbin_url, httpbin_ca_bundle):
- requests.get(httpsbin_url('status', '301'), verify=httpbin_ca_bundle)
+ def test_pyopenssl_redirect(self, httpbin_secure, httpbin_ca_bundle):
+ requests.get(httpbin_secure('status', '301'), verify=httpbin_ca_bundle)
def test_urlencoded_get_query_multivalued_param(self, httpbin):
@@ -578,13 +540,13 @@ class TestRequests:
assert b'name="b\'stuff\'"' not in prep.body
def test_unicode_method_name(self, httpbin):
- files = {'file': open('test_requests.py', 'rb')}
+ files = {'file': open(__file__, 'rb')}
r = requests.request(
method=u('POST'), url=httpbin('post'), files=files)
assert r.status_code == 200
def test_unicode_method_name_with_request_object(self, httpbin):
- files = {'file': open('test_requests.py', 'rb')}
+ files = {'file': open(__file__, 'rb')}
s = requests.Session()
req = requests.Request(u("POST"), httpbin('post'), files=files)
prep = s.prepare_request(req)
@@ -851,26 +813,6 @@ class TestRequests:
assert r.request.url == pr.request.url
assert r.request.headers == pr.request.headers
- def test_get_auth_from_url(self):
- url = 'http://user:pass@complex.url.com/path?query=yes'
- assert ('user', 'pass') == requests.utils.get_auth_from_url(url)
-
- def test_get_auth_from_url_encoded_spaces(self):
- url = 'http://user:pass%20pass@complex.url.com/path?query=yes'
- assert ('user', 'pass pass') == requests.utils.get_auth_from_url(url)
-
- def test_get_auth_from_url_not_encoded_spaces(self):
- url = 'http://user:pass pass@complex.url.com/path?query=yes'
- assert ('user', 'pass pass') == requests.utils.get_auth_from_url(url)
-
- def test_get_auth_from_url_percent_chars(self):
- url = 'http://user%25user:pass@complex.url.com/path?query=yes'
- assert ('user%user', 'pass') == requests.utils.get_auth_from_url(url)
-
- def test_get_auth_from_url_encoded_hashes(self):
- url = 'http://user:pass%23pass@complex.url.com/path?query=yes'
- assert ('user', 'pass#pass') == requests.utils.get_auth_from_url(url)
-
def test_cannot_send_unprepared_requests(self, httpbin):
r = requests.Request(url=httpbin())
with pytest.raises(ValueError):
@@ -986,23 +928,10 @@ class TestRequests:
assert 'unicode' in p.headers.keys()
assert 'byte' in p.headers.keys()
- def test_can_send_nonstring_objects_with_files(self, httpbin):
- data = {'a': 0.0}
- files = {'b': 'foo'}
- r = requests.Request('POST', httpbin('post'), data=data, files=files)
- p = r.prepare()
-
- assert 'multipart/form-data' in p.headers['Content-Type']
-
- def test_can_send_bytes_bytearray_objects_with_files(self, httpbin):
- # Test bytes:
+ @pytest.mark.parametrize('files', ('foo', b'foo', bytearray(b'foo')))
+ def test_can_send_objects_with_files(self, httpbin, files):
data = {'a': 'this is a string'}
- files = {'b': b'foo'}
- r = requests.Request('POST', httpbin('post'), data=data, files=files)
- p = r.prepare()
- assert 'multipart/form-data' in p.headers['Content-Type']
- # Test bytearrays:
- files = {'b': bytearray(b'foo')}
+ files = {'b': files}
r = requests.Request('POST', httpbin('post'), data=data, files=files)
p = r.prepare()
assert 'multipart/form-data' in p.headers['Content-Type']
@@ -1145,43 +1074,10 @@ class TestRequests:
assert len(list(r.iter_lines())) == 3
-class TestContentEncodingDetection:
-
- def test_none(self):
- encodings = requests.utils.get_encodings_from_content('')
- assert not len(encodings)
-
- @pytest.mark.parametrize(
- 'content', (
- # HTML5 meta charset attribute
- '',
- # HTML4 pragma directive
- '',
- # XHTML 1.x served with text/html MIME type
- '',
- # XHTML 1.x served as XML
- '',
- )
- )
- def test_pragmas(self, content):
- encodings = requests.utils.get_encodings_from_content(content)
- assert len(encodings) == 1
- assert encodings[0] == 'UTF-8'
-
- def test_precedence(self):
- content = '''
-
-
-
- '''.strip()
- encodings = requests.utils.get_encodings_from_content(content)
- assert encodings == ['HTML5', 'HTML4', 'XML']
-
-
class TestCaseInsensitiveDict:
- @pytest.mark.parametrize('cid',
- (
+ @pytest.mark.parametrize(
+ 'cid', (
CaseInsensitiveDict({'Foo': 'foo', 'BAr': 'bar'}),
CaseInsensitiveDict([('Foo', 'foo'), ('BAr', 'bar')]),
CaseInsensitiveDict(FOO='foo', BAr='bar'),
@@ -1321,146 +1217,6 @@ class TestCaseInsensitiveDict:
assert cid != cid_copy
-class TestUtils:
-
- def test_super_len_io_streams(self):
- """ Ensures that we properly deal with different kinds of IO streams. """
- # uses StringIO or io.StringIO (see import above)
- from io import BytesIO
- from requests.utils import super_len
-
- assert super_len(StringIO.StringIO()) == 0
- assert super_len(
- StringIO.StringIO('with so much drama in the LBC')) == 29
-
- assert super_len(BytesIO()) == 0
- assert super_len(
- BytesIO(b"it's kinda hard bein' snoop d-o-double-g")) == 40
-
- try:
- import cStringIO
- except ImportError:
- pass
- else:
- assert super_len(
- cStringIO.StringIO('but some how, some way...')) == 25
-
- def test_super_len_correctly_calculates_len_of_partially_read_file(self):
- """Ensure that we handle partially consumed file like objects."""
- from requests.utils import super_len
- s = StringIO.StringIO()
- s.write('foobarbogus')
- assert super_len(s) == 0
-
- def test_get_environ_proxies_ip_ranges(self):
- """Ensures that IP addresses are correctly matches with ranges
- in no_proxy variable."""
- from requests.utils import get_environ_proxies
- os.environ['no_proxy'] = "192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1"
- assert get_environ_proxies('http://192.168.0.1:5000/') == {}
- assert get_environ_proxies('http://192.168.0.1/') == {}
- assert get_environ_proxies('http://172.16.1.1/') == {}
- assert get_environ_proxies('http://172.16.1.1:5000/') == {}
- assert get_environ_proxies('http://192.168.1.1:5000/') != {}
- assert get_environ_proxies('http://192.168.1.1/') != {}
-
- def test_get_environ_proxies(self):
- """Ensures that IP addresses are correctly matches with ranges
- in no_proxy variable."""
- from requests.utils import get_environ_proxies
- os.environ['no_proxy'] = "127.0.0.1,localhost.localdomain,192.168.0.0/24,172.16.1.1"
- assert get_environ_proxies(
- 'http://localhost.localdomain:5000/v1.0/') == {}
- assert get_environ_proxies('http://www.requests.com/') != {}
-
- def test_select_proxies(self):
- """Make sure we can select per-host proxies correctly."""
- from requests.utils import select_proxy
- proxies = {'http': 'http://http.proxy',
- 'http://some.host': 'http://some.host.proxy'}
- assert select_proxy('hTTp://u:p@Some.Host/path', proxies) == 'http://some.host.proxy'
- assert select_proxy('hTTp://u:p@Other.Host/path', proxies) == 'http://http.proxy'
- assert select_proxy('hTTps://Other.Host', proxies) is None
-
- def test_guess_filename_when_int(self):
- from requests.utils import guess_filename
- assert None is guess_filename(1)
-
- def test_guess_filename_when_filename_is_an_int(self):
- from requests.utils import guess_filename
- fake = type('Fake', (object,), {'name': 1})()
- assert None is guess_filename(fake)
-
- def test_guess_filename_with_file_like_obj(self):
- from requests.utils import guess_filename
- from requests import compat
- fake = type('Fake', (object,), {'name': b'value'})()
- guessed_name = guess_filename(fake)
- assert b'value' == guessed_name
- assert isinstance(guessed_name, compat.bytes)
-
- def test_guess_filename_with_unicode_name(self):
- from requests.utils import guess_filename
- from requests import compat
- filename = b'value'.decode('utf-8')
- fake = type('Fake', (object,), {'name': filename})()
- guessed_name = guess_filename(fake)
- assert filename == guessed_name
- assert isinstance(guessed_name, compat.str)
-
- def test_is_ipv4_address(self):
- from requests.utils import is_ipv4_address
- assert is_ipv4_address('8.8.8.8')
- assert not is_ipv4_address('8.8.8.8.8')
- assert not is_ipv4_address('localhost.localdomain')
-
- def test_is_valid_cidr(self):
- from requests.utils import is_valid_cidr
- assert not is_valid_cidr('8.8.8.8')
- assert is_valid_cidr('192.168.1.0/24')
-
- def test_dotted_netmask(self):
- from requests.utils import dotted_netmask
- assert dotted_netmask(8) == '255.0.0.0'
- assert dotted_netmask(24) == '255.255.255.0'
- assert dotted_netmask(25) == '255.255.255.128'
-
- def test_address_in_network(self):
- from requests.utils import address_in_network
- assert address_in_network('192.168.1.1', '192.168.1.0/24')
- assert not address_in_network('172.16.0.1', '192.168.1.0/24')
-
- def test_get_auth_from_url(self):
- """Ensures that username and password in well-encoded URI as per
- RFC 3986 are correctly extracted."""
- from requests.utils import get_auth_from_url
- from requests.compat import quote
- percent_encoding_test_chars = "%!*'();:@&=+$,/?#[] "
- url_address = "request.com/url.html#test"
- url = "http://" + quote(
- percent_encoding_test_chars, '') + ':' + quote(
- percent_encoding_test_chars, '') + '@' + url_address
- (username, password) = get_auth_from_url(url)
- assert username == percent_encoding_test_chars
- assert password == percent_encoding_test_chars
-
- def test_requote_uri_with_unquoted_percents(self):
- """Ensure we handle unquoted percent signs in redirects.
-
- See: https://github.com/kennethreitz/requests/issues/2356
- """
- from requests.utils import requote_uri
- bad_uri = 'http://example.com/fiz?buz=%ppicture'
- quoted = 'http://example.com/fiz?buz=%25ppicture'
- assert quoted == requote_uri(bad_uri)
-
- def test_requote_uri_properly_requotes(self):
- """Ensure requoting doesn't break expectations."""
- from requests.utils import requote_uri
- quoted = 'http://example.com/fiz?buz=%25ppicture'
- assert quoted == requote_uri(quoted)
-
-
class TestMorselToCookieExpires:
"""Tests for morsel_to_cookie when morsel contains expires."""
@@ -1472,8 +1228,8 @@ class TestMorselToCookieExpires:
cookie = morsel_to_cookie(morsel)
assert cookie.expires == 1
- @pytest.mark.parametrize('value, exception',
- (
+ @pytest.mark.parametrize(
+ 'value, exception', (
(100, TypeError),
('woops', ValueError),
)
@@ -1516,20 +1272,23 @@ class TestMorselToCookieMaxAge:
class TestTimeout:
+
def test_stream_timeout(self, httpbin):
try:
requests.get(httpbin('delay/10'), timeout=2.0)
except requests.exceptions.Timeout as e:
assert 'Read timed out' in e.args[0].args[0]
- def test_invalid_timeout(self, httpbin):
+ @pytest.mark.parametrize(
+ 'timeout, error_text', (
+ ((3, 4, 5), '(connect, read)'),
+ ('foo', 'must be an int or float'),
+ )
+ )
+ def test_invalid_timeout(self, httpbin, timeout, error_text):
with pytest.raises(ValueError) as e:
- requests.get(httpbin('get'), timeout=(3, 4, 5))
- assert '(connect, read)' in str(e)
-
- with pytest.raises(ValueError) as e:
- requests.get(httpbin('get'), timeout="foo")
- assert 'must be an int or float' in str(e)
+ requests.get(httpbin('get'), timeout=timeout)
+ assert error_text in str(e)
def test_none_timeout(self, httpbin):
""" Check that you can set None as a valid timeout value.
@@ -1606,7 +1365,13 @@ class RedirectSession(SessionRedirectMixin):
return string
-class TestRedirects:
+def test_requests_are_updated_each_time(httpbin):
+ session = RedirectSession([303, 307])
+ prep = requests.Request('POST', httpbin('post')).prepare()
+ r0 = session.send(prep)
+ assert r0.request.method == 'POST'
+ assert session.calls[-1] == SendCall((r0.request,), {})
+ redirect_generator = session.resolve_redirects(r0, prep)
default_keyword_args = {
'stream': False,
'verify': True,
@@ -1615,85 +1380,62 @@ class TestRedirects:
'allow_redirects': False,
'proxies': {},
}
-
- def test_requests_are_updated_each_time(self, httpbin):
- session = RedirectSession([303, 307])
- prep = requests.Request('POST', httpbin('post')).prepare()
- r0 = session.send(prep)
- assert r0.request.method == 'POST'
- assert session.calls[-1] == SendCall((r0.request,), {})
- redirect_generator = session.resolve_redirects(r0, prep)
- for response in redirect_generator:
- assert response.request.method == 'GET'
- send_call = SendCall((response.request,),
- TestRedirects.default_keyword_args)
- assert session.calls[-1] == send_call
+ for response in redirect_generator:
+ assert response.request.method == 'GET'
+ send_call = SendCall((response.request,), default_keyword_args)
+ assert session.calls[-1] == send_call
-@pytest.fixture
-def list_of_tuples():
- return [
+@pytest.mark.parametrize(
+ 'data', (
(('a', 'b'), ('c', 'd')),
(('c', 'd'), ('a', 'b')),
(('a', 'b'), ('c', 'd'), ('e', 'f')),
- ]
-
-
-def test_data_argument_accepts_tuples(list_of_tuples):
+ )
+)
+def test_data_argument_accepts_tuples(data):
"""Ensure that the data argument will accept tuples of strings
and properly encode them.
"""
- for data in list_of_tuples:
- p = PreparedRequest()
- p.prepare(
- method='GET',
- url='http://www.example.com',
- data=data,
- hooks=default_hooks()
- )
- assert p.body == urlencode(data)
-
-
-def assert_copy(p, p_copy):
- for attr in ('method', 'url', 'headers', '_cookies', 'body', 'hooks'):
- assert getattr(p, attr) == getattr(p_copy, attr)
-
-
-def test_prepared_request_empty_copy():
- p = PreparedRequest()
- assert_copy(p, p.copy())
-
-
-def test_prepared_request_no_cookies_copy():
p = PreparedRequest()
p.prepare(
method='GET',
url='http://www.example.com',
- data='foo=bar',
+ data=data,
hooks=default_hooks()
)
- assert_copy(p, p.copy())
+ assert p.body == urlencode(data)
-def test_prepared_request_complete_copy():
- p = PreparedRequest()
- p.prepare(
- method='GET',
- url='http://www.example.com',
- data='foo=bar',
- hooks=default_hooks(),
- cookies={'foo': 'bar'}
+@pytest.mark.parametrize(
+ 'kwargs', (
+ None,
+ {
+ 'method': 'GET',
+ 'url': 'http://www.example.com',
+ 'data': 'foo=bar',
+ 'hooks': default_hooks()
+ },
+ {
+ 'method': 'GET',
+ 'url': 'http://www.example.com',
+ 'data': 'foo=bar',
+ 'hooks': default_hooks(),
+ 'cookies': {'foo': 'bar'}
+ },
+ {
+ 'method': 'GET',
+ 'url': u('http://www.example.com/üniçø∂é')
+ },
)
- assert_copy(p, p.copy())
-
-
-def test_prepare_unicode_url():
+)
+def test_prepared_copy(kwargs):
p = PreparedRequest()
- p.prepare(
- method='GET',
- url=u('http://www.example.com/üniçø∂é'),
- )
- assert_copy(p, p.copy())
+ if kwargs:
+ p.prepare(**kwargs)
+ copy = p.copy()
+ for attr in ('method', 'url', 'headers', '_cookies', 'body', 'hooks'):
+ assert getattr(p, attr) == getattr(copy, attr)
def test_urllib3_retries(httpbin):
diff --git a/tests/test_utils.py b/tests/test_utils.py
new file mode 100644
index 00000000..0f7aec34
--- /dev/null
+++ b/tests/test_utils.py
@@ -0,0 +1,242 @@
+# coding: utf-8
+import os
+from io import BytesIO
+
+import pytest
+from requests import compat
+from requests.utils import (
+ address_in_network, dotted_netmask,
+ get_auth_from_url, get_encodings_from_content,
+ get_environ_proxies, guess_filename,
+ is_ipv4_address, is_valid_cidr, requote_uri,
+ select_proxy, super_len)
+
+from .compat import StringIO, cStringIO
+
+
+class TestSuperLen:
+
+ @pytest.mark.parametrize(
+ 'stream, value', (
+ (StringIO.StringIO, 'Test'),
+ (BytesIO, b'Test'),
+ pytest.mark.skipif('cStringIO is None')(
+ (cStringIO, 'Test')
+ ),
+ ))
+ def test_io_streams(self, stream, value):
+ """ Ensures that we properly deal with different kinds of IO streams. """
+ assert super_len(stream()) == 0
+ assert super_len(stream(value)) == 4
+
+ def test_super_len_correctly_calculates_len_of_partially_read_file(self):
+ """Ensure that we handle partially consumed file like objects."""
+ s = StringIO.StringIO()
+ s.write('foobarbogus')
+ assert super_len(s) == 0
+
+
+class TestGetEnvironProxies:
+ """Ensures that IP addresses are correctly matches with ranges
+ in no_proxy variable."""
+
+ @pytest.yield_fixture(scope='class', autouse=True, params=['no_proxy', 'NO_PROXY'])
+ def no_proxy(self, request):
+ os.environ[request.param] = '192.168.0.0/24,127.0.0.1,localhost.localdomain,172.16.1.1'
+ yield
+ del os.environ[request.param]
+
+ @pytest.mark.parametrize(
+ 'url', (
+ 'http://192.168.0.1:5000/',
+ 'http://192.168.0.1/',
+ 'http://172.16.1.1/',
+ 'http://172.16.1.1:5000/',
+ 'http://localhost.localdomain:5000/v1.0/',
+ )
+ )
+ def test_bypass(self, url):
+ assert get_environ_proxies(url) == {}
+
+ @pytest.mark.parametrize(
+ 'url', (
+ 'http://192.168.1.1:5000/',
+ 'http://192.168.1.1/',
+ 'http://www.requests.com/',
+ )
+ )
+ def test_not_bypass(self, url):
+ assert get_environ_proxies(url) != {}
+
+
+class TestIsIPv4Address:
+
+ def test_valid(self):
+ assert is_ipv4_address('8.8.8.8')
+
+ @pytest.mark.parametrize('value', ('8.8.8.8.8', 'localhost.localdomain'))
+ def test_invalid(self, value):
+ assert not is_ipv4_address(value)
+
+
+class TestIsValidCIDR:
+
+ def test_valid(self):
+ assert is_valid_cidr('192.168.1.0/24')
+
+ @pytest.mark.parametrize(
+ 'value', (
+ '8.8.8.8',
+ '192.168.1.0/a',
+ '192.168.1.0/128',
+ '192.168.1.0/-1',
+ '192.168.1.999/24',
+ )
+ )
+ def test_invalid(self, value):
+ assert not is_valid_cidr(value)
+
+
+class TestAddressInNetwork:
+
+ def test_valid(self):
+ assert address_in_network('192.168.1.1', '192.168.1.0/24')
+
+ def test_invalid(self):
+ assert not address_in_network('172.16.0.1', '192.168.1.0/24')
+
+
+class TestGuessFilename:
+
+ @pytest.mark.parametrize(
+ 'value', (1, type('Fake', (object,), {'name': 1})()),
+ )
+ def test_guess_filename_invalid(self, value):
+ assert guess_filename(value) is None
+
+ @pytest.mark.parametrize(
+ 'value, expected_type', (
+ (b'value', compat.bytes),
+ (b'value'.decode('utf-8'), compat.str)
+ )
+ )
+ def test_guess_filename_valid(self, value, expected_type):
+ obj = type('Fake', (object,), {'name': value})()
+ result = guess_filename(obj)
+ assert result == value
+ assert isinstance(result, expected_type)
+
+
+class TestContentEncodingDetection:
+
+ def test_none(self):
+ encodings = get_encodings_from_content('')
+ assert not len(encodings)
+
+ @pytest.mark.parametrize(
+ 'content', (
+ # HTML5 meta charset attribute
+ '',
+ # HTML4 pragma directive
+ '',
+ # XHTML 1.x served with text/html MIME type
+ '',
+ # XHTML 1.x served as XML
+ '',
+ )
+ )
+ def test_pragmas(self, content):
+ encodings = get_encodings_from_content(content)
+ assert len(encodings) == 1
+ assert encodings[0] == 'UTF-8'
+
+ def test_precedence(self):
+ content = '''
+
+
+
+ '''.strip()
+ assert get_encodings_from_content(content) == ['HTML5', 'HTML4', 'XML']
+
+
+USER = PASSWORD = "%!*'();:@&=+$,/?#[] "
+ENCODED_USER = compat.quote(USER, '')
+ENCODED_PASSWORD = compat.quote(PASSWORD, '')
+
+
+@pytest.mark.parametrize(
+ 'url, auth', (
+ (
+ 'http://' + ENCODED_USER + ':' + ENCODED_PASSWORD + '@' +
+ 'request.com/url.html#test',
+ (USER, PASSWORD)
+ ),
+ (
+ 'http://user:pass@complex.url.com/path?query=yes',
+ ('user', 'pass')
+ ),
+ (
+ 'http://user:pass%20pass@complex.url.com/path?query=yes',
+ ('user', 'pass pass')
+ ),
+ (
+ 'http://user:pass pass@complex.url.com/path?query=yes',
+ ('user', 'pass pass')
+ ),
+ (
+ 'http://user%25user:pass@complex.url.com/path?query=yes',
+ ('user%user', 'pass')
+ ),
+ (
+ 'http://user:pass%23pass@complex.url.com/path?query=yes',
+ ('user', 'pass#pass')
+ ),
+ )
+)
+def test_get_auth_from_url(url, auth):
+ assert get_auth_from_url(url) == auth
+
+
+@pytest.mark.parametrize(
+ 'uri, expected', (
+ (
+ # Ensure requoting doesn't break expectations
+ 'http://example.com/fiz?buz=%25ppicture',
+ 'http://example.com/fiz?buz=%25ppicture',
+ ),
+ (
+ # Ensure we handle unquoted percent signs in redirects
+ 'http://example.com/fiz?buz=%ppicture',
+ 'http://example.com/fiz?buz=%25ppicture',
+ ),
+ )
+)
+def test_requote_uri_with_unquoted_percents(uri, expected):
+ """See: https://github.com/kennethreitz/requests/issues/2356
+ """
+ assert requote_uri(uri) == expected
+
+
+@pytest.mark.parametrize(
+ 'mask, expected', (
+ (8, '255.0.0.0'),
+ (24, '255.255.255.0'),
+ (25, '255.255.255.128'),
+ )
+)
+def test_dotted_netmask(mask, expected):
+ assert dotted_netmask(mask) == expected
+
+
+@pytest.mark.parametrize(
+ 'url, expected', (
+ ('hTTp://u:p@Some.Host/path', 'http://some.host.proxy'),
+ ('hTTp://u:p@Other.Host/path', 'http://http.proxy'),
+ ('hTTps://Other.Host', None),
+ )
+)
+def test_select_proxies(url, expected):
+ """Make sure we can select per-host proxies correctly."""
+ proxies = {'http': 'http://http.proxy',
+ 'http://some.host': 'http://some.host.proxy'}
+ assert select_proxy(url, proxies) == expected