# HG changeset patch
# User Tim Abbott <tabbott@zulipchat.com>
# Date 1539832068 25200
#      Wed Oct 17 20:07:48 2018 -0700
# Node ID 8bb664082b4d2b20d93d95ea3d6f451416ddffcc
# Parent  f02fede26b80dc443e66a72014f94f1115cc0375
pika: Don't automatically import twisted and tornado.

Previously, the pika.adapters convenience import logic would end up
importing Twisted, Tornado, and AsyncIO if they are present in the
current Python environment, regardless of whether the user intended to
use them.

While the convenience names of e.g. `pika.TornadoConnection` (rather
than the more verbose pika.adapters.TornadoConnection`) were nice,
this had the downside of making importing pika expensive in those
environments; on my system, twisted added 150ms and tornado 10ms to
the based ~40ms import time for pika.

We fix this by removing those convenience imports; now, a user needs
to explicitly import pika.adapters.tornado_connection (aka plan to
actually use the relevant adapter feature) in order to end up
importing those large third-party modules.

Fixes #1128.

diff --git a/README.rst b/README.rst
--- a/README.rst
+++ b/README.rst
@@ -113,11 +113,13 @@
       connection.add_callback_threadsafe(functools.partial(ack_message, channel, delivery_tag))
 
 - When using a non-blocking connection adapter, such as
-  :py:class:`pika.AsyncioConnection` or :py:class:`pika.SelectConnection`, you
-  use the underlying asynchronous framework's native API for requesting an
-  ioloop-bound callback from another thread. For example, `SelectConnection`'s
-  `IOLoop` provides `add_callback_threadsafe()`, `Tornado`'s `IOLoop` has
-  `add_callback()`, while `asyncio`'s event loop exposes `call_soon_threadsafe()`.
+:py:class:`pika.adapters.asyncio_connection.AsyncioConnection` or
+:py:class:`pika.SelectConnection`, you use the underlying asynchronous
+framework's native API for requesting an ioloop-bound callback from
+another thread. For example, `SelectConnection`'s `IOLoop` provides
+`add_callback_threadsafe()`, `Tornado`'s `IOLoop` has
+`add_callback()`, while `asyncio`'s event loop exposes
+`call_soon_threadsafe()`.
 
 This threadsafe callback request mechanism may also be used to delegate
 publishing of messages, etc., from a background thread to the connection adapter's
diff --git a/docs/examples/asyncio_consumer.rst b/docs/examples/asyncio_consumer.rst
--- a/docs/examples/asyncio_consumer.rst
+++ b/docs/examples/asyncio_consumer.rst
@@ -59,8 +59,8 @@
 
             """
             LOGGER.info('Connecting to %s', self._url)
-            return adapters.AsyncioConnection(pika.URLParameters(self._url),
-                                              self.on_connection_open)
+            return adapters.asyncio_connection.AsyncioConnection(pika.URLParameters(self._url),
+                                                                 self.on_connection_open)
 
         def close_connection(self):
             """This method closes the connection to RabbitMQ."""
diff --git a/docs/examples/tornado_consumer.rst b/docs/examples/tornado_consumer.rst
--- a/docs/examples/tornado_consumer.rst
+++ b/docs/examples/tornado_consumer.rst
@@ -53,8 +53,8 @@
 
             """
             LOGGER.info('Connecting to %s', self._url)
-            return adapters.TornadoConnection(pika.URLParameters(self._url),
-                                              self.on_connection_open)
+            return adapters.tornado_connection.TornadoConnection(pika.URLParameters(self._url),
+                                                                 self.on_connection_open)
 
         def close_connection(self):
             """This method closes the connection to RabbitMQ."""
diff --git a/pika/__init__.py b/pika/__init__.py
--- a/pika/__init__.py
+++ b/pika/__init__.py
@@ -15,5 +15,3 @@
 from pika.adapters import BaseConnection
 from pika.adapters import BlockingConnection
 from pika.adapters import SelectConnection
-from pika.adapters import TornadoConnection
-from pika.adapters import TwistedConnection
diff --git a/pika/adapters/__init__.py b/pika/adapters/__init__.py
--- a/pika/adapters/__init__.py
+++ b/pika/adapters/__init__.py
@@ -19,22 +19,3 @@
 from pika.adapters.blocking_connection import BlockingConnection
 from pika.adapters.select_connection import SelectConnection
 from pika.adapters.select_connection import IOLoop
-
-# Dynamically handle 3rd party library dependencies for optional imports
-try:
-    from pika.adapters.asyncio_connection import AsyncioConnection
-except ImportError:
-    AsyncioConnection = None
-
-try:
-    from pika.adapters.tornado_connection import TornadoConnection
-except ImportError:
-    TornadoConnection = None
-
-try:
-    from pika.adapters.twisted_connection import TwistedConnection
-    from pika.adapters.twisted_connection import TwistedProtocolConnection
-except ImportError:
-    TwistedConnection = None
-    TwistedProtocolConnection = None
-
diff --git a/tests/acceptance/async_test_base.py b/tests/acceptance/async_test_base.py
--- a/tests/acceptance/async_test_base.py
+++ b/tests/acceptance/async_test_base.py
@@ -238,17 +238,17 @@
     def tornado_test(self):
         """TornadoConnection"""
         ioloop_factory = None
-        if adapters.TornadoConnection is not None:
+        if adapters.tornado_connection.TornadoConnection is not None:
             import tornado.ioloop
             ioloop_factory = tornado.ioloop.IOLoop
-        self.start(adapters.TornadoConnection, ioloop_factory)
+        self.start(adapters.tornado_connection.TornadoConnection, ioloop_factory)
 
     @unittest.skipIf(sys.version_info < (3, 4), "Asyncio available for Python 3.4+")
     def asyncio_test(self):
         """AsyncioConnection"""
         ioloop_factory = None
-        if adapters.AsyncioConnection is not None:
+        if adapters.asyncio_connection.AsyncioConnection is not None:
             import asyncio
             ioloop_factory = asyncio.new_event_loop
 
-        self.start(adapters.AsyncioConnection, ioloop_factory)
+        self.start(adapters.asyncio_connection.AsyncioConnection, ioloop_factory)