THRIFT-3910 Do not invoke pip as part of build process

This closes #1073
diff --git a/lib/py/CMakeLists.txt b/lib/py/CMakeLists.txt
index 2ec8b56..7bb91fe 100644
--- a/lib/py/CMakeLists.txt
+++ b/lib/py/CMakeLists.txt
@@ -20,7 +20,6 @@
 include_directories(${PYTHON_INCLUDE_DIRS})
 
 add_custom_target(python_build ALL
-    COMMAND ${PIP_EXECUTABLE} install -r requirements.txt || ${PIP_EXECUTABLE} install --user -r requirements.txt
     COMMAND ${PYTHON_EXECUTABLE} setup.py build
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
     COMMENT "Building Python library"
diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am
index f324715..fd9ce25 100644
--- a/lib/py/Makefile.am
+++ b/lib/py/Makefile.am
@@ -21,7 +21,6 @@
 
 if WITH_PY3
 py3-build:
-	$(PIP3) install -r requirements.txt || $(PIP3) install --user -r requirements.txt
 	$(PYTHON3) setup.py build
 py3-test: py3-build
 	$(PYTHON3) test/thrift_json.py
@@ -32,7 +31,6 @@
 endif
 
 all-local: py3-build
-	$(PIP) install -r requirements.txt || $(PIP) install --user -r requirements.txt
 	$(PYTHON) setup.py build
 
 # We're ignoring prefix here because site-packages seems to be
@@ -40,7 +38,6 @@
 # Old version (can't put inline because it's not portable).
 #$(PYTHON) setup.py install --prefix=$(prefix) --root=$(DESTDIR) $(PYTHON_SETUPUTIL_ARGS)
 install-exec-hook:
-	$(PIP) install -r requirements.txt
 	$(PYTHON) setup.py install --root=$(DESTDIR) --prefix=$(PY_PREFIX) $(PYTHON_SETUPUTIL_ARGS)
 
 clean-local:
@@ -54,7 +51,6 @@
 	CMakeLists.txt \
 	coding_standards.md \
 	compat \
-	requirements.txt \
 	setup.py \
 	setup.cfg \
 	src \
diff --git a/lib/py/requirements.txt b/lib/py/requirements.txt
deleted file mode 100644
index 2254a28..0000000
--- a/lib/py/requirements.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-six
-backports.ssl_match_hostname >= 3.5
-ipaddress
diff --git a/lib/py/setup.py b/lib/py/setup.py
index ca10096..99b7172 100644
--- a/lib/py/setup.py
+++ b/lib/py/setup.py
@@ -78,6 +78,14 @@
     else:
         extensions = dict()
 
+    ssl_deps = []
+    if sys.version_info[0] == 2:
+        ssl_deps.append('ipaddress')
+    if sys.hexversion < 0x03050000:
+        ssl_deps.append('backports.ssl_match_hostname>=3.5')
+    tornado_deps = ['tornado>=4.0']
+    twisted_deps = ['twisted']
+
     setup(name='thrift',
           version='1.0.0-dev',
           description='Python bindings for the Apache Thrift RPC system',
@@ -86,6 +94,12 @@
           url='http://thrift.apache.org',
           license='Apache License 2.0',
           install_requires=['six>=1.7.2'],
+          extras_require={
+              'ssl': ssl_deps,
+              'tornado': tornado_deps,
+              'twisted': twisted_deps,
+              'all': ssl_deps + tornado_deps + twisted_deps,
+          },
           packages=[
               'thrift',
               'thrift.protocol',
diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py
index 12bc356..0f7d45e 100644
--- a/lib/py/src/transport/TSSLSocket.py
+++ b/lib/py/src/transport/TSSLSocket.py
@@ -346,7 +346,7 @@
         TSSLBase.__init__(self, True, None, kwargs)
         TSocket.TServerSocket.__init__(self, host, port, unix_socket)
         if self._should_verify and not _match_has_ipaddress:
-            raise ValueError('Need ipaddress and backports.ssl_match_hostname'
+            raise ValueError('Need ipaddress and backports.ssl_match_hostname '
                              'module to verify client certificate')
 
     def setCertfile(self, certfile):