Remove all uses of nose from the codebase
MODIFY
Makefile
Makefile
@@ -41,7 +41,7 @@ clean:
.PHONY: test
test: requirements
- nosetests
+ tox
.PHONY: test-all
test-all: requirements

MODIFY
dev-requirements.txt
dev-requirements.txt
-nose==1.3.7
-nose-exclude==0.4.1
mock==1.3.0
coverage==3.7.1
tox==2.1.1
@@ -10,5 +8,6 @@ PySocks==1.5.6
pkginfo>=1.0,!=1.3.0
psutil==4.3.1
pytest-cov==2.5.1
+pytest-timeout==1.2.0
pytest==3.1.0
gcp-devrel-py-tools==0.0.7

MODIFY
dummyserver/testcase.py
dummyserver/testcase.py
import sys
import socket
import threading
-from nose.plugins.skip import SkipTest
+
+import pytest
from tornado import ioloop, web
from dummyserver.server import (
@@ -133,16 +134,10 @@ class HTTPSDummyServerTestCase(HTTPDummyServerTestCase):
certs = DEFAULT_CERTS
+@pytest.mark.skipif(not socket.has_ipv6, reason='IPv6 not available')
class IPV6HTTPSDummyServerTestCase(HTTPSDummyServerTestCase):
host = '::1'
- @classmethod
- def setUpClass(cls):
- if not socket.has_ipv6:
- raise SkipTest('IPv6 not available')
- else:
- super(IPV6HTTPSDummyServerTestCase, cls).setUpClass()
-
class HTTPDummyProxyTestCase(unittest.TestCase):
@@ -183,16 +178,10 @@ class HTTPDummyProxyTestCase(unittest.TestCase):
cls.server_thread.join()
+@pytest.mark.skipif(not socket.has_ipv6, reason='IPv6 not available')
class IPv6HTTPDummyServerTestCase(HTTPDummyServerTestCase):
host = '::1'
- @classmethod
- def setUpClass(cls):
- if not socket.has_ipv6:
- raise SkipTest('IPv6 not available')
- else:
- super(IPv6HTTPDummyServerTestCase, cls).setUpClass()
-
class IPv6HTTPDummyProxyTestCase(HTTPDummyProxyTestCase):

MODIFY
setup.cfg
setup.cfg
-[nosetests]
-logging-clear-handlers=true
-with-coverage=true
-cover-package=urllib3
-# no rounding problems here
-cover-erase=true
-
[flake8]
exclude=./docs/conf.py,./urllib3/packages/*
max-line-length=99

MODIFY
setup.py
setup.py
@@ -56,7 +56,6 @@ setup(name='urllib3',
# These are a less-specific subset of dev-requirements.txt, for the
# convenience of distro package maintainers.
'pytest',
- 'nose',
'mock',
'tornado',
],

MODIFY
test/__init__.py
test/__init__.py
@@ -6,7 +6,7 @@ import logging
import socket
import platform
-from nose.plugins.skip import SkipTest
+import pytest
from urllib3.exceptions import HTTPWarning
from urllib3.packages import six
@@ -44,7 +44,7 @@ def onlyPy26OrOlder(test):
def wrapper(*args, **kwargs):
msg = "{name} only runs on Python2.6.x or older".format(name=test.__name__)
if sys.version_info >= (2, 7):
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -56,7 +56,7 @@ def onlyPy27OrNewer(test):
def wrapper(*args, **kwargs):
msg = "{name} requires Python 2.7.x+ to run".format(name=test.__name__)
if sys.version_info < (2, 7):
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -68,7 +68,7 @@ def onlyPy279OrNewer(test):
def wrapper(*args, **kwargs):
msg = "{name} requires Python 2.7.9+ to run".format(name=test.__name__)
if sys.version_info < (2, 7, 9):
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -80,7 +80,7 @@ def onlyPy2(test):
def wrapper(*args, **kwargs):
msg = "{name} requires Python 2.x to run".format(name=test.__name__)
if six.PY3:
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -92,7 +92,7 @@ def onlyPy3(test):
def wrapper(*args, **kwargs):
msg = "{name} requires Python3.x to run".format(name=test.__name__)
if not six.PY3:
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -104,7 +104,7 @@ def notSecureTransport(test):
def wrapper(*args, **kwargs):
msg = "{name} does not run with SecureTransport".format(name=test.__name__)
if ssl_.IS_SECURETRANSPORT:
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -115,7 +115,7 @@ def onlyPy27OrNewerOrNonWindows(test):
def wrapper(*args, **kwargs):
msg = "{name} requires Python2.7+ or non-Windows to run".format(name=test.__name__)
if sys.version_info < (2, 7) and platform.system() == 'Windows':
- raise SkipTest(msg)
+ pytest.skip(msg)
return test(*args, **kwargs)
return wrapper
@@ -155,7 +155,7 @@ def requires_network(test):
else:
msg = "Can't run {name} because the network is unreachable".format(
name=test.__name__)
- raise SkipTest(msg)
+ pytest.skip(msg)
return wrapper

MODIFY
test/contrib/test_pyopenssl.py
test/contrib/test_pyopenssl.py
# -*- coding: utf-8 -*-
import unittest
-from nose.plugins.skip import SkipTest
+import pytest
try:
from urllib3.contrib.pyopenssl import (inject_into_urllib3,
extract_from_urllib3,
_dnsname_to_stdlib)
except ImportError as e:
- raise SkipTest('Could not import PyOpenSSL: %r' % e)
+ pytestmark = pytest.mark.skip('Could not import PyOpenSSL: %r' % e)
from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1 # noqa: F401

MODIFY
test/contrib/test_pyopenssl_dependencies.py
test/contrib/test_pyopenssl_dependencies.py
# -*- coding: utf-8 -*-
import unittest
-from nose.plugins.skip import SkipTest
+import pytest
try:
from urllib3.contrib.pyopenssl import (inject_into_urllib3,
extract_from_urllib3)
except ImportError as e:
- raise SkipTest('Could not import PyOpenSSL: %r' % e)
+ pytestmark = pytest.mark.skip('Could not import PyOpenSSL: %r' % e)
from mock import patch, Mock

MODIFY
test/contrib/test_securetransport.py
test/contrib/test_securetransport.py
# -*- coding: utf-8 -*-
-from nose.plugins.skip import SkipTest
+import pytest
try:
from urllib3.contrib.securetransport import (inject_into_urllib3,
extract_from_urllib3)
except ImportError as e:
- raise SkipTest('Could not import SecureTransport: %r' % e)
+ pytestmark = pytest.mark.skip('Could not import SecureTransport: %r' % e)
from ..with_dummyserver.test_https import TestHTTPS, TestHTTPS_TLSv1 # noqa: F401
from ..with_dummyserver.test_socketlevel import ( # noqa: F401

MODIFY
test/contrib/test_socks.py
test/contrib/test_socks.py
@@ -7,7 +7,7 @@ from urllib3.exceptions import ConnectTimeoutError, NewConnectionError
from dummyserver.server import DEFAULT_CERTS
from dummyserver.testcase import IPV4SocketDummyServerTestCase
-from nose.plugins.skip import SkipTest
+import pytest
try:
import ssl
@@ -632,10 +632,8 @@ class TestSOCKSWithTLS(IPV4SocketDummyServerTestCase):
"""
Test that TLS behaves properly for SOCKS proxies.
"""
+ @pytest.mark.skipif(not HAS_SSL, reason='No TLS available')
def test_basic_request(self):
- if not HAS_SSL:
- raise SkipTest("No TLS available")
-
def request_handler(listener):
sock = listener.accept()[0]

MODIFY
test/with_dummyserver/test_https.py
test/with_dummyserver/test_https.py
@@ -6,7 +6,7 @@ import unittest
import warnings
import mock
-from nose.plugins.skip import SkipTest
+import pytest
from dummyserver.testcase import (
HTTPSDummyServerTestCase, IPV6HTTPSDummyServerTestCase
@@ -560,7 +560,7 @@ class TestHTTPS_IPSAN(HTTPSDummyServerTestCase):
try:
import ipaddress # noqa: F401
except ImportError:
- raise SkipTest("Only runs on systems with an ipaddress module")
+ pytest.skip("Only runs on systems with an ipaddress module")
https_pool = HTTPSConnectionPool('127.0.0.1', self.port,
cert_reqs='CERT_REQUIRED',
@@ -573,10 +573,9 @@ class TestHTTPS_IPSAN(HTTPSDummyServerTestCase):
class TestHTTPS_IPv6Addr(IPV6HTTPSDummyServerTestCase):
certs = IPV6_ADDR_CERTS
+ @pytest.mark.skipif(not HAS_IPV6, reason='Only runs on IPv6 systems')
def test_strip_square_brackets_before_validating(self):
"""Test that the fix for #760 works."""
- if not HAS_IPV6:
- raise SkipTest("Only runs on IPv6 systems")
https_pool = HTTPSConnectionPool('[::1]', self.port,
cert_reqs='CERT_REQUIRED',
ca_certs=IPV6_ADDR_CA)

MODIFY
test/with_dummyserver/test_poolmanager.py
test/with_dummyserver/test_poolmanager.py
import unittest
import json
-from nose.plugins.skip import SkipTest
+import pytest
+
from dummyserver.server import HAS_IPV6
from dummyserver.testcase import (HTTPDummyServerTestCase,
IPv6HTTPDummyServerTestCase)
@@ -216,9 +217,11 @@ class TestPoolManager(HTTPDummyServerTestCase):
self.assertEqual(r.status, 200)
+@pytest.mark.skipif(
+ not HAS_IPV6,
+ reason='IPv6 is not supported on this system'
+)
class TestIPv6PoolManager(IPv6HTTPDummyServerTestCase):
- if not HAS_IPV6:
- raise SkipTest("IPv6 is not supported on this system.")
def setUp(self):
self.base_url = 'http://[%s]:%d' % (self.host, self.port)

MODIFY
test/with_dummyserver/test_proxy_poolmanager.py
test/with_dummyserver/test_proxy_poolmanager.py
@@ -2,7 +2,7 @@ import json
import socket
import unittest
-from nose.tools import timed
+import pytest
from dummyserver.testcase import HTTPDummyProxyTestCase, IPv6HTTPDummyProxyTestCase
from dummyserver.server import (
@@ -295,7 +295,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
self.assertNotEqual(sc2, sc3)
self.assertEqual(sc3, sc4)
- @timed(0.5)
+ @pytest.mark.timeout(0.5)
@requires_network
def test_https_proxy_timeout(self):
https = proxy_from_url('https://{host}'.format(host=TARPIT_HOST))
@@ -306,7 +306,7 @@ class TestHTTPProxyManager(HTTPDummyProxyTestCase):
except MaxRetryError as e:
self.assertEqual(type(e.reason), ConnectTimeoutError)
- @timed(0.5)
+ @pytest.mark.timeout(0.5)
@requires_network
def test_https_proxy_pool_timeout(self):
https = proxy_from_url('https://{host}'.format(host=TARPIT_HOST),

MODIFY
test/with_dummyserver/test_socketlevel.py
test/with_dummyserver/test_socketlevel.py
@@ -22,7 +22,6 @@ from dummyserver.server import (
from .. import onlyPy3, LogRecorder
-from nose.plugins.skip import SkipTest
try:
from mimetools import Message as MimeToolMessage
except ImportError:
@@ -33,6 +32,8 @@ import select
import socket
import ssl
+import pytest
+
class TestCookies(SocketDummyServerTestCase):
@@ -60,10 +61,8 @@ class TestCookies(SocketDummyServerTestCase):
class TestSNI(SocketDummyServerTestCase):
+ @pytest.mark.skipif(not HAS_SNI, reason='SNI-support not available')
def test_hostname_in_first_request_packet(self):
- if not HAS_SNI:
- raise SkipTest('SNI-support not available')
-
done_receiving = Event()
self.buf = b''
@@ -1260,12 +1259,11 @@ class TestHeaders(SocketDummyServerTestCase):
self.assertEqual(expected_response_headers, actual_response_headers)
+@pytest.mark.skipif(
+ issubclass(httplib.HTTPMessage, MimeToolMessage),
+ reason='Header parsing errors not available'
+)
class TestBrokenHeaders(SocketDummyServerTestCase):
- def setUp(self):
- if issubclass(httplib.HTTPMessage, MimeToolMessage):
- raise SkipTest('Header parsing errors not available')
-
- super(TestBrokenHeaders, self).setUp()
def _test_broken_header_parsing(self, headers):
self.start_response_handler((

Remove all uses of nose from the codebase