2424from collections .abc import Mapping
2525from concurrent .futures import ThreadPoolExecutor , FIRST_COMPLETED , wait as wait_futures
2626from copy import copy
27- from functools import partial , wraps
27+ from functools import partial , reduce , wraps
2828from itertools import groupby , count , chain
2929import json
3030import logging
4444from cassandra import (ConsistencyLevel , AuthenticationFailed ,
4545 OperationTimedOut , UnsupportedOperation ,
4646 SchemaTargetType , DriverException , ProtocolVersion ,
47- UnresolvableContactPoints )
47+ UnresolvableContactPoints , DependencyException )
4848from cassandra .auth import _proxy_execute_key , PlainTextAuthProvider
4949from cassandra .connection import (ConnectionException , ConnectionShutdown ,
5050 ConnectionHeartbeat , ProtocolVersionUnsupported ,
111111except ImportError :
112112 from cassandra .util import WeakSet # NOQA
113113
114+ def _is_gevent_monkey_patched ():
115+ if 'gevent.monkey' not in sys .modules :
116+ return False
117+ import gevent .socket
118+ return socket .socket is gevent .socket .socket
119+
120+ def _try_gevent_import ():
121+ if _is_gevent_monkey_patched ():
122+ from cassandra .io .geventreactor import GeventConnection
123+ return (GeventConnection ,None )
124+ else :
125+ return (None ,None )
126+
114127def _is_eventlet_monkey_patched ():
115128 if 'eventlet.patcher' not in sys .modules :
116129 return False
@@ -121,26 +134,42 @@ def _is_eventlet_monkey_patched():
121134 except AttributeError :
122135 return False
123136
137+ def _try_eventlet_import ():
138+ if _is_eventlet_monkey_patched ():
139+ from cassandra .io .eventletreactor import EventletConnection
140+ return (EventletConnection ,None )
141+ else :
142+ return (None ,None )
124143
125- def _is_gevent_monkey_patched ():
126- if 'gevent.monkey' not in sys . modules :
127- return False
128- import gevent . socket
129- return socket . socket is gevent . socket . socket
130-
144+ def _try_libev_import ():
145+ try :
146+ from cassandra . io . libevreactor import LibevConnection
147+ return ( LibevConnection , None )
148+ except DependencyException as e :
149+ return ( None , e )
131150
132- # default to gevent when we are monkey patched with gevent, eventlet when
133- # monkey patched with eventlet, otherwise if libev is available, use that as
134- # the default because it's fastest. Otherwise, use asyncore.
135- if _is_gevent_monkey_patched ():
136- from cassandra .io .geventreactor import GeventConnection as DefaultConnection
137- elif _is_eventlet_monkey_patched ():
138- from cassandra .io .eventletreactor import EventletConnection as DefaultConnection
139- else :
151+ def _try_asyncore_import ():
140152 try :
141- from cassandra .io .libevreactor import LibevConnection as DefaultConnection # NOQA
142- except ImportError :
143- from cassandra .io .asyncorereactor import AsyncoreConnection as DefaultConnection # NOQA
153+ from cassandra .io .asyncorereactor import AsyncoreConnection
154+ return (AsyncoreConnection ,None )
155+ except DependencyException as e :
156+ return (None , e )
157+
158+ def _connection_reduce_fn (val ,import_fn ):
159+ (rv , excs ) = val
160+ # If we've already found a workable Connection class return immediately
161+ if rv :
162+ return val
163+ (import_result , exc ) = import_fn ()
164+ if exc :
165+ excs .append (exc )
166+ return (rv or import_result , excs )
167+
168+ conn_fns = (_try_gevent_import , _try_eventlet_import , _try_libev_import , _try_asyncore_import )
169+ (conn_class , excs ) = reduce (_connection_reduce_fn , conn_fns , (None ,[]))
170+ if excs :
171+ raise DependencyException ("Exception loading connection class dependencies" , excs )
172+ DefaultConnection = conn_class
144173
145174# Forces load of utf8 encoding module to avoid deadlock that occurs
146175# if code that is being imported tries to import the module in a seperate
0 commit comments