25
25
from collections .abc import Mapping
26
26
from concurrent .futures import ThreadPoolExecutor , FIRST_COMPLETED , wait as wait_futures
27
27
from copy import copy
28
- from functools import partial , wraps
28
+ from functools import partial , reduce , wraps
29
29
from itertools import groupby , count , chain
30
30
import json
31
31
import logging
45
45
from cassandra import (ConsistencyLevel , AuthenticationFailed , InvalidRequest ,
46
46
OperationTimedOut , UnsupportedOperation ,
47
47
SchemaTargetType , DriverException , ProtocolVersion ,
48
- UnresolvableContactPoints )
48
+ UnresolvableContactPoints , DependencyException )
49
49
from cassandra .auth import _proxy_execute_key , PlainTextAuthProvider
50
50
from cassandra .connection import (ConnectionException , ConnectionShutdown ,
51
51
ConnectionHeartbeat , ProtocolVersionUnsupported ,
113
113
except ImportError :
114
114
from cassandra .util import WeakSet # NOQA
115
115
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
+
116
129
def _is_eventlet_monkey_patched ():
117
130
if 'eventlet.patcher' not in sys .modules :
118
131
return False
@@ -124,32 +137,46 @@ def _is_eventlet_monkey_patched():
124
137
# TODO: remove it when eventlet issue would be fixed
125
138
return False
126
139
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 )
136
146
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 )
137
153
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 ():
146
155
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
153
180
154
181
# Forces load of utf8 encoding module to avoid deadlock that occurs
155
182
# if code that is being imported tries to import the module in a seperate
0 commit comments