2525from collections .abc import Mapping
2626from concurrent .futures import ThreadPoolExecutor , FIRST_COMPLETED , wait as wait_futures
2727from copy import copy
28- from functools import partial , wraps
28+ from functools import partial , reduce , wraps
2929from itertools import groupby , count , chain
3030import json
3131import logging
4545from cassandra import (ConsistencyLevel , AuthenticationFailed , InvalidRequest ,
4646 OperationTimedOut , UnsupportedOperation ,
4747 SchemaTargetType , DriverException , ProtocolVersion ,
48- UnresolvableContactPoints )
48+ UnresolvableContactPoints , DependencyException )
4949from cassandra .auth import _proxy_execute_key , PlainTextAuthProvider
5050from cassandra .connection import (ConnectionException , ConnectionShutdown ,
5151 ConnectionHeartbeat , ProtocolVersionUnsupported ,
113113except ImportError :
114114 from cassandra .util import WeakSet # NOQA
115115
116+ def _is_gevent_monkey_patched ():
117+ if 'gevent.monkey' not in sys .modules :
118+ return False
119+ import gevent .socket
120+ return socket .socket is gevent .socket .socket
121+
122+ def _try_gevent_import ():
123+ if _is_gevent_monkey_patched ():
124+ from cassandra .io .geventreactor import GeventConnection
125+ return (GeventConnection ,None )
126+ else :
127+ return (None ,None )
128+
116129def _is_eventlet_monkey_patched ():
117130 if 'eventlet.patcher' not in sys .modules :
118131 return False
@@ -124,32 +137,46 @@ def _is_eventlet_monkey_patched():
124137 # TODO: remove it when eventlet issue would be fixed
125138 return False
126139
127- def _is_gevent_monkey_patched ():
128- if 'gevent.monkey' not in sys .modules :
129- return False
130- try :
131- import eventlet .patcher
132- return eventlet .patcher .is_monkey_patched ('socket' )
133- # Another case related to PYTHON-1364
134- except AttributeError :
135- return False
140+ def _try_eventlet_import ():
141+ if _is_eventlet_monkey_patched ():
142+ from cassandra .io .eventletreactor import EventletConnection
143+ return (EventletConnection ,None )
144+ else :
145+ return (None ,None )
136146
147+ def _try_libev_import ():
148+ try :
149+ from cassandra .io .libevreactor import LibevConnection
150+ return (LibevConnection ,None )
151+ except DependencyException as e :
152+ return (None , e )
137153
138- # default to gevent when we are monkey patched with gevent, eventlet when
139- # monkey patched with eventlet, otherwise if libev is available, use that as
140- # the default because it's fastest. Otherwise, use asyncore.
141- if _is_gevent_monkey_patched ():
142- from cassandra .io .geventreactor import GeventConnection as DefaultConnection
143- elif _is_eventlet_monkey_patched ():
144- from cassandra .io .eventletreactor import EventletConnection as DefaultConnection
145- else :
154+ def _try_asyncore_import ():
146155 try :
147- from cassandra .io .libevreactor import LibevConnection as DefaultConnection # NOQA
148- except ImportError :
149- try :
150- from cassandra .io .asyncorereactor import AsyncoreConnection as DefaultConnection # NOQA
151- except ImportError :
152- from cassandra .io .asyncioreactor import AsyncioConnection as DefaultConnection # NOQA
156+ from cassandra .io .asyncorereactor import AsyncoreConnection
157+ return (AsyncoreConnection ,None )
158+ except DependencyException as e :
159+ return (None , e )
160+
161+ def _try_asyncio_import ():
162+ from cassandra .io .asyncioreactor import AsyncioConnection
163+ return (AsyncioConnection , None )
164+
165+ def _connection_reduce_fn (val ,import_fn ):
166+ (rv , excs ) = val
167+ # If we've already found a workable Connection class return immediately
168+ if rv :
169+ return val
170+ (import_result , exc ) = import_fn ()
171+ if exc :
172+ excs .append (exc )
173+ return (rv or import_result , excs )
174+
175+ conn_fns = (_try_gevent_import , _try_eventlet_import , _try_libev_import , _try_asyncore_import , _try_asyncio_import )
176+ (conn_class , excs ) = reduce (_connection_reduce_fn , conn_fns , (None ,[]))
177+ if excs :
178+ raise DependencyException ("Exception loading connection class dependencies" , excs )
179+ DefaultConnection = conn_class
153180
154181# Forces load of utf8 encoding module to avoid deadlock that occurs
155182# if code that is being imported tries to import the module in a seperate
0 commit comments