Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions cassandra/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@
import logging
import importlib.metadata


class NullHandler(logging.Handler):

def emit(self, record):
pass


logging.getLogger('cassandra').addHandler(NullHandler())

__version__ = importlib.metadata.version('cassandra-driver')


class ConsistencyLevel(object):
"""
Specifies how many replicas must respond for an operation to be considered
Expand Down Expand Up @@ -417,10 +420,10 @@ def __init__(self, summary_message, consistency=None, required_replicas=None, al
self.consistency = consistency
self.required_replicas = required_replicas
self.alive_replicas = alive_replicas
Exception.__init__(self, summary_message + ' info=' +
repr({'consistency': consistency_value_to_name(consistency),
'required_replicas': required_replicas,
'alive_replicas': alive_replicas}))
Exception.__init__(self, summary_message + ' info='
+ repr({'consistency': consistency_value_to_name(consistency),
'required_replicas': required_replicas,
'alive_replicas': alive_replicas}))


class Timeout(RequestExecutionException):
Expand Down Expand Up @@ -632,7 +635,7 @@ class RequestValidationException(DriverException):

class ConfigurationException(RequestValidationException):
"""
Server indicated request errro due to current configuration
Server indicated request error due to current configuration
"""
pass

Expand Down Expand Up @@ -729,6 +732,7 @@ class UnresolvableContactPoints(DriverException):
"""
pass


class DependencyException(Exception):
"""
Specific exception class for handling issues with driver dependencies
Expand Down
1 change: 1 addition & 0 deletions cassandra/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def initial_response(self):
def evaluate_challenge(self, challenge):
return self.sasl.process(challenge)


# TODO remove me next major
DSEPlainTextAuthProvider = PlainTextAuthProvider

Expand Down
47 changes: 26 additions & 21 deletions cassandra/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,21 +98,24 @@
except ImportError:
from cassandra.util import WeakSet # NOQA


def _try_libev_import():
try:
from cassandra.io.libevreactor import LibevConnection
return (LibevConnection,None)
return (LibevConnection, None)
except DependencyException as e:
return (None, e)


def _try_asyncore_import():
try:
from cassandra.io.asyncorereactor import AsyncoreConnection
return (AsyncoreConnection,None)
return (AsyncoreConnection, None)
except DependencyException as e:
return (None, e)

def _connection_reduce_fn(val,import_fn):

def _connection_reduce_fn(val, import_fn):
(rv, excs) = val
# If we've already found a workable Connection class return immediately
if rv:
Expand All @@ -122,10 +125,11 @@ def _connection_reduce_fn(val,import_fn):
excs.append(exc)
return (rv or import_result, excs)


log = logging.getLogger(__name__)

conn_fns = (_try_libev_import, _try_asyncore_import)
(conn_class, excs) = reduce(_connection_reduce_fn, conn_fns, (None,[]))
(conn_class, excs) = reduce(_connection_reduce_fn, conn_fns, (None, []))
if not conn_class:
raise DependencyException("Unable to load a default connection class", excs)
DefaultConnection = conn_class
Expand Down Expand Up @@ -383,8 +387,8 @@ def __init__(self, load_balancing_policy=_NOT_SET, retry_policy=None,

self.retry_policy = retry_policy or RetryPolicy()

if (serial_consistency_level is not None and
not ConsistencyLevel.is_serial(serial_consistency_level)):
if (serial_consistency_level is not None
and not ConsistencyLevel.is_serial(serial_consistency_level)):
raise ValueError("serial_consistency_level must be either "
"ConsistencyLevel.SERIAL "
"or ConsistencyLevel.LOCAL_SERIAL.")
Expand Down Expand Up @@ -675,6 +679,7 @@ def auth_provider(self, value):
self._auth_provider = value

_load_balancing_policy = None

@property
def load_balancing_policy(self):
"""
Expand Down Expand Up @@ -711,6 +716,7 @@ def _default_load_balancing_policy(self):
"""

_default_retry_policy = RetryPolicy()

@property
def default_retry_policy(self):
"""
Expand Down Expand Up @@ -768,9 +774,8 @@ def default_retry_policy(self, policy):
Using ssl_options without ssl_context is deprecated and will be removed in the
next major release.

An optional dict which will be used as kwargs for ``ssl.SSLContext.wrap_socket``
when new sockets are created. This should be used when client encryption is enabled
in Cassandra.
An optional dict which will be used as kwargs for ``ssl.SSLContext.wrap_socket`` when new
sockets are created. This should be used when client encryption is enabled in Cassandra.

The following documentation only applies when ssl_options is used without ssl_context.

Expand Down Expand Up @@ -2289,6 +2294,7 @@ class Session(object):
_monitor_reporter = None

_row_factory = staticmethod(named_tuple_factory)

@property
def row_factory(self):
"""
Expand Down Expand Up @@ -2354,8 +2360,8 @@ def default_consistency_level(self, cl):
*Deprecated:* use execution profiles instead
"""
warn("Setting the consistency level at the session level will be removed in 4.0. Consider using "
"execution profiles and setting the desired consistency level to the EXEC_PROFILE_DEFAULT profile."
, DeprecationWarning)
"execution profiles and setting the desired consistency level to the EXEC_PROFILE_DEFAULT profile.",
DeprecationWarning)
self._validate_set_legacy_config('default_consistency_level', cl)

_default_serial_consistency_level = None
Expand All @@ -2373,8 +2379,8 @@ def default_serial_consistency_level(self):

@default_serial_consistency_level.setter
def default_serial_consistency_level(self, cl):
if (cl is not None and
not ConsistencyLevel.is_serial(cl)):
if (cl is not None
and not ConsistencyLevel.is_serial(cl)):
raise ValueError("default_serial_consistency_level must be either "
"ConsistencyLevel.SERIAL "
"or ConsistencyLevel.LOCAL_SERIAL.")
Expand Down Expand Up @@ -3161,7 +3167,7 @@ def prepare_on_all_hosts(self, query, excluded_host, keyspace=None):
for host in tuple(self._pools.keys()):
if host != excluded_host and host.is_up:
future = ResponseFuture(self, PrepareMessage(query=query, keyspace=keyspace),
None, self.default_timeout)
None, self.default_timeout)

# we don't care about errors preparing against specific hosts,
# since we can always prepare them as needed when the prepared
Expand Down Expand Up @@ -3198,7 +3204,7 @@ def shutdown(self):
self.is_shutdown = True

# PYTHON-673. If shutdown was called shortly after session init, avoid
# a race by cancelling any initial connection attempts haven't started,
# a race by cancelling any initial connection attempts which haven't started,
# then blocking on any that have.
for future in self._initial_connect_futures:
future.cancel()
Expand Down Expand Up @@ -3298,8 +3304,7 @@ def update_created_pools(self):
but also on other nodes (for instance, if a node dies, another
previously ignored node may be now considered).

This method ensures that all hosts for which a pool should exist
have one, and hosts that shouldn't don't.
Ensures host pools exist only for eligible hosts.

For internal use only.
"""
Expand Down Expand Up @@ -3907,9 +3912,9 @@ def _refresh_node_list_and_token_map(self, connection, preloaded_results=None,

@staticmethod
def _is_valid_peer(row):
return bool(_NodeInfo.get_broadcast_rpc_address(row) and row.get("host_id") and
row.get("data_center") and row.get("rack") and
('tokens' not in row or row.get('tokens')))
return bool(_NodeInfo.get_broadcast_rpc_address(row) and row.get("host_id")
and row.get("data_center") and row.get("rack")
and ('tokens' not in row or row.get('tokens')))

def _update_location_info(self, host, datacenter, rack):
if host.datacenter == datacenter and host.rack == rack:
Expand Down Expand Up @@ -4717,7 +4722,7 @@ def _set_result(self, host, connection, pool, response):
current_keyspace = self._connection.keyspace
prepared_keyspace = prepared_statement.keyspace
if not ProtocolVersion.uses_keyspace_flag(self.session.cluster.protocol_version) \
and prepared_keyspace and current_keyspace != prepared_keyspace:
and prepared_keyspace and current_keyspace != prepared_keyspace:
self._set_final_exception(
ValueError("The Session's current keyspace (%s) does "
"not match the keyspace the statement was "
Expand Down
5 changes: 3 additions & 2 deletions cassandra/concurrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@

ExecutionResult = namedtuple('ExecutionResult', ['success', 'result_or_exc'])

def execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True, results_generator=False, execution_profile=EXEC_PROFILE_DEFAULT):

def execute_concurrent(session, statements_and_parameters, concurrency=100, raise_on_first_error=True,
results_generator=False, execution_profile=EXEC_PROFILE_DEFAULT):
"""
See :meth:`.Session.execute_concurrent`.
"""
Expand Down Expand Up @@ -161,7 +163,6 @@ def _results(self):
return [r[1] for r in sorted(self._results_queue)]



def execute_concurrent_with_args(session, statement, parameters, *args, **kwargs):
"""
See :meth:`.Session.execute_concurrent_with_args`.
Expand Down
51 changes: 25 additions & 26 deletions cassandra/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ def resolve(self):
return self._address, self._port

def __eq__(self, other):
return isinstance(other, DefaultEndPoint) and \
self.address == other.address and self.port == other.port
return isinstance(other, DefaultEndPoint)\
and self.address == other.address and self.port == other.port

def __hash__(self):
return hash((self.address, self.port))
Expand All @@ -217,8 +217,7 @@ class DefaultEndPointFactory(EndPointFactory):

port = None
"""
If no port is discovered in the row, this is the default port
used for endpoint creation.
If no port is discovered in the row, this is the default port used for endpoint creation.
"""

def __init__(self, port=None):
Expand Down Expand Up @@ -282,16 +281,16 @@ def _resolve_proxy_addresses(self):
socket.AF_UNSPEC, socket.SOCK_STREAM)

def __eq__(self, other):
return (isinstance(other, SniEndPoint) and
self.address == other.address and self.port == other.port and
self._server_name == other._server_name)
return (isinstance(other, SniEndPoint)
and self.address == other.address and self.port == other.port
and self._server_name == other._server_name)

def __hash__(self):
return hash((self.address, self.port, self._server_name))

def __lt__(self, other):
return ((self.address, self.port, self._server_name) <
(other.address, other.port, self._server_name))
return ((self.address, self.port, self._server_name)
< (other.address, other.port, self._server_name))
Comment on lines 291 to +293

def __str__(self):
return str("%s:%d:%s" % (self.address, self.port, self._server_name))
Expand Down Expand Up @@ -351,8 +350,8 @@ def resolve(self):
return self.address, None

def __eq__(self, other):
return (isinstance(other, UnixSocketEndPoint) and
self._unix_socket_path == other._unix_socket_path)
return (isinstance(other, UnixSocketEndPoint)
and self._unix_socket_path == other._unix_socket_path)

def __hash__(self):
return hash(self._unix_socket_path)
Expand All @@ -378,12 +377,12 @@ def __init__(self, version, flags, stream, opcode, body_offset, end_pos):

def __eq__(self, other): # facilitates testing
if isinstance(other, _Frame):
return (self.version == other.version and
self.flags == other.flags and
self.stream == other.stream and
self.opcode == other.opcode and
self.body_offset == other.body_offset and
self.end_pos == other.end_pos)
return (self.version == other.version
and self.flags == other.flags
and self.stream == other.stream
and self.opcode == other.opcode
and self.body_offset == other.body_offset
and self.end_pos == other.end_pos)
return NotImplemented

def __str__(self):
Expand Down Expand Up @@ -647,7 +646,7 @@ def is_checksumming_enabled(self):

@property
def has_consumed_segment(self):
return self._segment_consumed;
return self._segment_consumed

def readable_io_bytes(self):
return self.io_buffer.tell()
Expand Down Expand Up @@ -721,7 +720,7 @@ class Connection(object):
# If the number of orphaned streams reaches this threshold, this connection
# will become marked and will be replaced with a new connection by the
# owning pool (currently, only HostConnection supports this)
orphaned_threshold = 3 * max_in_flight // 4
orphaned_threshold = 3 * max_in_flight // 4

is_defunct = False
is_closed = False
Expand Down Expand Up @@ -869,7 +868,7 @@ def _build_ssl_context_from_options(self):

# Extract a subset of names from self.ssl_options which apply to SSLContext creation
ssl_context_opt_names = ['ssl_version', 'cert_reqs', 'check_hostname', 'keyfile', 'certfile', 'ca_certs', 'ciphers']
opts = {k:self.ssl_options.get(k, None) for k in ssl_context_opt_names if k in self.ssl_options}
opts = {k: self.ssl_options.get(k, None) for k in ssl_context_opt_names if k in self.ssl_options}

# Python >= 3.10 requires either PROTOCOL_TLS_CLIENT or PROTOCOL_TLS_SERVER, so we'll get ahead of things by always
# being explicit
Expand Down Expand Up @@ -897,11 +896,11 @@ def _wrap_socket_from_context(self):
# Extract a subset of names from self.ssl_options which apply to SSLContext.wrap_socket (or at least the parts
# of it that don't involve building an SSLContext under the covers)
wrap_socket_opt_names = ['server_side', 'do_handshake_on_connect', 'suppress_ragged_eofs', 'server_hostname']
opts = {k:self.ssl_options.get(k, None) for k in wrap_socket_opt_names if k in self.ssl_options}
opts = {k: self.ssl_options.get(k, None) for k in wrap_socket_opt_names if k in self.ssl_options}

# PYTHON-1186: set the server_hostname only if the SSLContext has
# check_hostname enabled, and it is not already provided by the EndPoint ssl options
#opts['server_hostname'] = self.endpoint.address
# opts['server_hostname'] = self.endpoint.address
if (self.ssl_context.check_hostname and 'server_hostname' not in opts):
server_hostname = self.endpoint.address
opts['server_hostname'] = server_hostname
Expand Down Expand Up @@ -1355,8 +1354,8 @@ def _handle_options_response(self, options_response):
self._compressor = None
compression_type = None
if self.compression:
overlap = (set(locally_supported_compressions.keys()) &
set(remote_supported_compressions))
overlap = (set(locally_supported_compressions.keys())
& set(remote_supported_compressions))
if len(overlap) == 0:
log.debug("No available compression types supported on both ends."
" locally supported: %r. remotely supported: %r",
Expand All @@ -1381,8 +1380,8 @@ def _handle_options_response(self, options_response):

# If snappy compression is selected with v5+checksumming, the connection
# will fail with OTO. Only lz4 is supported
if (compression_type == 'snappy' and
ProtocolVersion.has_checksumming_support(self.protocol_version)):
if (compression_type == 'snappy'
and ProtocolVersion.has_checksumming_support(self.protocol_version)):
log.debug("Snappy compression is not supported with protocol version %s and "
"checksumming. Consider installing lz4. Disabling compression.", self.protocol_version)
compression_type = None
Expand Down
Loading