From 36945334756a16e7eef1c6465e562929b1f3a242 Mon Sep 17 00:00:00 2001 From: Yaniv Michael Kaul Date: Mon, 2 Feb 2026 12:47:22 +0200 Subject: [PATCH] (Improvement) Remove CQL binary protocol v3 No one needs it anymore. Any reasonable version of Cassandra and ScyllaDB support CQL binary protocol v4 (or higher). This also assume that we test against Cassandra 2.2 or above, so removed some <= 2.1 items. Signed-off-by: Yaniv Kaul --- CONTRIBUTING.rst | 7 +- cassandra/__init__.py | 11 +- cassandra/cluster.py | 30 +- cassandra/connection.py | 20 +- cassandra/cqlengine/models.py | 8 +- cassandra/cqlengine/query.py | 2 +- cassandra/cqltypes.py | 185 ++++++----- cassandra/deserializers.pxd | 9 +- cassandra/deserializers.pyx | 94 +++--- cassandra/metadata.py | 2 +- cassandra/numpy_parser.pyx | 2 +- cassandra/obj_parser.pyx | 4 +- cassandra/parsing.pxd | 1 - cassandra/parsing.pyx | 3 +- cassandra/protocol.py | 36 +-- cassandra/query.py | 47 +-- cassandra/row_parser.pyx | 4 +- cassandra/util.py | 5 +- docs/cqlengine/models.rst | 2 +- docs/object-mapper.rst | 2 +- docs/security.rst | 2 +- docs/user-defined-types.rst | 6 +- tests/integration/__init__.py | 76 +---- .../columns/test_container_columns.py | 16 +- .../cqlengine/columns/test_static_column.py | 6 +- .../cqlengine/columns/test_validation.py | 17 +- .../cqlengine/columns/test_value_io.py | 35 +-- .../cqlengine/connections/test_connection.py | 2 +- .../cqlengine/management/test_management.py | 15 +- .../cqlengine/model/test_model_io.py | 23 +- .../integration/cqlengine/model/test_udts.py | 7 - .../cqlengine/model/test_updates.py | 2 - .../cqlengine/query/test_queryset.py | 41 +-- .../cqlengine/query/test_updates.py | 2 - tests/integration/cqlengine/test_ifexists.py | 7 - .../integration/cqlengine/test_ifnotexists.py | 3 - .../cqlengine/test_lwt_conditional.py | 2 - tests/integration/cqlengine/test_ttl.py | 17 +- tests/integration/datatype_utils.py | 8 +- tests/integration/long/test_failure_types.py | 38 +-- tests/integration/long/test_large_data.py | 2 +- .../long/test_loadbalancingpolicies.py | 2 +- tests/integration/simulacron/__init__.py | 8 +- tests/integration/simulacron/test_policies.py | 13 +- .../standard/test_authentication.py | 15 +- .../standard/test_client_warnings.py | 14 +- tests/integration/standard/test_cluster.py | 44 +-- tests/integration/standard/test_concurrent.py | 12 +- tests/integration/standard/test_connection.py | 3 +- .../standard/test_control_connection.py | 6 +- .../standard/test_custom_payload.py | 2 +- .../standard/test_custom_protocol_handler.py | 6 +- .../standard/test_cython_protocol_handlers.py | 9 +- tests/integration/standard/test_metadata.py | 286 +++++------------- .../standard/test_prepared_statements.py | 21 +- tests/integration/standard/test_query.py | 33 +- .../integration/standard/test_query_paging.py | 7 +- .../standard/test_row_factories.py | 3 - .../standard/test_single_interface.py | 2 +- tests/integration/standard/test_types.py | 102 +------ tests/integration/standard/test_udts.py | 75 +---- tests/integration/util.py | 3 - tests/unit/advanced/test_geometry.py | 19 +- tests/unit/cython/types_testhelper.pyx | 10 +- tests/unit/io/utils.py | 2 +- tests/unit/test_cluster.py | 2 - tests/unit/test_marshalling.py | 19 +- tests/unit/test_orderedmap.py | 9 +- tests/unit/test_parameter_binding.py | 55 ++-- tests/unit/test_query.py | 1 - tests/unit/test_types.py | 81 +++-- 71 files changed, 472 insertions(+), 1193 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8b8fc0e791..1b80e813ee 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -89,12 +89,11 @@ The test will start the appropriate Scylla clusters when necessary but if you d Specify a Protocol Version for Tests ------------------------------------ The protocol version defaults to: -- 4 for Scylla >= 3.0 and Scylla Enterprise > 2019. -- 3 for older versions of Scylla -- 5 for Cassandra >= 4.0, 4 for Cassandra >= 2.2, 3 for Cassandra >= 2.1, 2 for Cassandra >= 2.0 +- 4 for Scylla. +- 5 for Cassandra >= 4.0, 4 for Cassandra >= 2.2 You can overwrite it with the ``PROTOCOL_VERSION`` environment variable:: - PROTOCOL_VERSION=3 SCYLLA_VERSION="release:5.1" uv run pytest tests/integration/standard tests/integration/cqlengine/ + PROTOCOL_VERSION=4 SCYLLA_VERSION="release:5.1" uv run pytest tests/integration/standard tests/integration/cqlengine/ Seeing Test Logs in Real Time ----------------------------- diff --git a/cassandra/__init__.py b/cassandra/__init__.py index 88fbb11f88..d772814643 100644 --- a/cassandra/__init__.py +++ b/cassandra/__init__.py @@ -136,13 +136,6 @@ class ProtocolVersion(object): Defines native protocol versions supported by this driver. """ - V3 = 3 - """ - v3, supported in Cassandra 2.1-->3.x+; - added support for protocol-level client-side timestamps (see :attr:`.Session.use_client_timestamp`), - serial consistency levels for :class:`~.BatchStatement`, and an improved connection pool. - """ - V4 = 4 """ v4, supported in Cassandra 2.2-->3.x+; @@ -170,9 +163,9 @@ class ProtocolVersion(object): DSE private protocol v2, supported in DSE 6.0+ """ - SUPPORTED_VERSIONS = (V5, V4, V3) + SUPPORTED_VERSIONS = (V5, V4) """ - A tuple of all supported protocol versions for ScyllaDB, including future v5 version. + A tuple of all supported protocol versions for ScyllaDB. """ BETA_VERSIONS = (V6,) diff --git a/cassandra/cluster.py b/cassandra/cluster.py index 622b706330..c8b45f5ec8 100644 --- a/cassandra/cluster.py +++ b/cassandra/cluster.py @@ -717,11 +717,9 @@ def application_info(self) -> Optional[ApplicationInfoBase]: @property def auth_provider(self): """ - When :attr:`~.Cluster.protocol_version` is 2 or higher, this should - be an instance of a subclass of :class:`~cassandra.auth.AuthProvider`, + This should be an instance of a subclass of :class:`~cassandra.auth.AuthProvider`, such as :class:`~.PlainTextAuthProvider`. - When not using authentication, this should be left as :const:`None`. """ return self._auth_provider @@ -735,12 +733,7 @@ def auth_provider(self, value): try: self._auth_provider_callable = value.new_authenticator except AttributeError: - if self.protocol_version > 1: - raise TypeError("auth_provider must implement the cassandra.auth.AuthProvider " - "interface when protocol_version >= 2") - elif not callable(value): - raise TypeError("auth_provider must be callable when protocol_version == 1") - self._auth_provider_callable = value + raise TypeError("auth_provider must implement the cassandra.auth.AuthProvider interface") self._auth_provider = value @@ -1557,7 +1550,7 @@ def register_user_type(self, keyspace, user_type, klass): Example:: - cluster = Cluster(protocol_version=3) + cluster = Cluster(protocol_version=4) session = cluster.connect() session.set_keyspace('mykeyspace') session.execute("CREATE TYPE address (street text, zipcode int)") @@ -1582,11 +1575,6 @@ def __init__(self, street, zipcode): print(row.id, row.location.street, row.location.zipcode) """ - if self.protocol_version < 3: - log.warning("User Type serialization is only supported in native protocol version 3+ (%d in use). " - "CQL encoding for simple statements will still work, but named tuples will " - "be returned when reading type %s.%s.", self.protocol_version, keyspace, user_type) - self._user_types[keyspace][user_type] = klass for session in tuple(self.sessions): session.user_type_registered(keyspace, user_type, klass) @@ -2445,8 +2433,6 @@ def default_serial_consistency_level(self): The default :class:`~ConsistencyLevel` for serial phase of conditional updates executed through this session. This default may be overridden by setting the :attr:`~.Statement.serial_consistency_level` on individual statements. - - Only valid for ``protocol_version >= 2``. """ return self._default_serial_consistency_level @@ -2957,11 +2943,6 @@ def _create_response_future(self, query, parameters, trace, custom_payload, continuous_paging_options=continuous_paging_options, result_metadata_id=prepared_statement.result_metadata_id) elif isinstance(query, BatchStatement): - if self._protocol_version < 2: - raise UnsupportedOperation( - "BatchStatement execution is only supported with protocol version " - "2 or higher (supported in Cassandra 2.0 and higher). Consider " - "setting Cluster.protocol_version to 2 to support this operation.") statement_keyspace = query.keyspace if ProtocolVersion.uses_keyspace_flag(self._protocol_version) else None message = BatchMessage( query.batch_type, query._statements_and_parameters, cl, @@ -3100,7 +3081,7 @@ def prepare(self, query, custom_payload=None, keyspace=None): prepared_keyspace = keyspace if keyspace else None prepared_statement = PreparedStatement.from_message( response.query_id, response.bind_metadata, response.pk_indexes, self.cluster.metadata, query, prepared_keyspace, - self._protocol_version, response.column_metadata, response.result_metadata_id, response.is_lwt, self.cluster.column_encryption_policy) + response.column_metadata, response.result_metadata_id, response.is_lwt, self.cluster.column_encryption_policy) prepared_statement.custom_payload = future.custom_payload self.cluster.add_prepared(response.query_id, prepared_statement) @@ -4640,10 +4621,9 @@ def _set_result(self, host, connection, pool, response): self._custom_payload = getattr(response, 'custom_payload', None) if self._custom_payload and self.session.cluster.control_connection._tablets_routing_v1 and 'tablets-routing-v1' in self._custom_payload: - protocol = self.session.cluster.protocol_version info = self._custom_payload.get('tablets-routing-v1') ctype = types.lookup_casstype('TupleType(LongType, LongType, ListType(TupleType(UUIDType, Int32Type)))') - tablet_routing_info = ctype.from_binary(info, protocol) + tablet_routing_info = ctype.from_binary(info) first_token = tablet_routing_info[0] last_token = tablet_routing_info[1] tablet_replicas = tablet_routing_info[2] diff --git a/cassandra/connection.py b/cassandra/connection.py index 87f860f32b..d8570fde03 100644 --- a/cassandra/connection.py +++ b/cassandra/connection.py @@ -41,7 +41,7 @@ from cassandra import ConsistencyLevel, AuthenticationFailed, OperationTimedOut, ProtocolVersion from cassandra.marshal import int32_pack from cassandra.protocol import (ReadyMessage, AuthenticateMessage, OptionsMessage, - StartupMessage, ErrorMessage, CredentialsMessage, + StartupMessage, ErrorMessage, QueryMessage, ResultMessage, ProtocolHandler, InvalidRequestException, SupportedMessage, AuthResponseMessage, AuthChallengeMessage, @@ -1477,18 +1477,12 @@ def _handle_startup_response(self, startup_response, did_authenticate=False): if ProtocolVersion.has_checksumming_support(self.protocol_version): self._enable_checksumming() - if isinstance(self.authenticator, dict): - log.debug("Sending credentials-based auth response on %s", self) - cm = CredentialsMessage(creds=self.authenticator) - callback = partial(self._handle_startup_response, did_authenticate=True) - self.send_msg(cm, self.get_request_id(), cb=callback) - else: - log.debug("Sending SASL-based auth response on %s", self) - self.authenticator.server_authenticator_class = startup_response.authenticator - initial_response = self.authenticator.initial_response() - initial_response = "" if initial_response is None else initial_response - self.send_msg(AuthResponseMessage(initial_response), self.get_request_id(), - self._handle_auth_response) + log.debug("Sending SASL-based auth response on %s", self) + self.authenticator.server_authenticator_class = startup_response.authenticator + initial_response = self.authenticator.initial_response() + initial_response = "" if initial_response is None else initial_response + self.send_msg(AuthResponseMessage(initial_response), self.get_request_id(), + self._handle_auth_response) elif isinstance(startup_response, ErrorMessage): log.debug("Received ErrorMessage on new connection (%s) from %s: %s", id(self), self.endpoint, startup_response.summary_msg()) diff --git a/cassandra/cqlengine/models.py b/cassandra/cqlengine/models.py index bc00001666..7cdb5ddd3f 100644 --- a/cassandra/cqlengine/models.py +++ b/cassandra/cqlengine/models.py @@ -422,8 +422,8 @@ def __str__(self): ', '.join('{0}={1}'.format(k, getattr(self, k)) for k in self._primary_keys.keys())) @classmethod - def _routing_key_from_values(cls, pk_values, protocol_version): - return cls._key_serializer(pk_values, protocol_version) + def _routing_key_from_values(cls, pk_values): + return cls._key_serializer(pk_values) @classmethod def _discover_polymorphic_submodels(cls): @@ -948,10 +948,10 @@ def _transform_column(col_name, col_obj): key_cols = [c for c in partition_keys.values()] partition_key_index = dict((col.db_field_name, col._partition_key_index) for col in key_cols) key_cql_types = [c.cql_type for c in key_cols] - key_serializer = staticmethod(lambda parts, proto_version: [t.to_binary(p, proto_version) for t, p in zip(key_cql_types, parts)]) + key_serializer = staticmethod(lambda parts: [t.to_binary(p) for t, p in zip(key_cql_types, parts)]) else: partition_key_index = {} - key_serializer = staticmethod(lambda parts, proto_version: None) + key_serializer = staticmethod(lambda parts: None) # setup partition key shortcut if len(partition_keys) == 0: diff --git a/cassandra/cqlengine/query.py b/cassandra/cqlengine/query.py index afc7ceeef6..5eb4be9166 100644 --- a/cassandra/cqlengine/query.py +++ b/cassandra/cqlengine/query.py @@ -1523,7 +1523,7 @@ def _execute_statement(model, statement, consistency_level, timeout, connection= if model._partition_key_index: key_values = statement.partition_key_values(model._partition_key_index) if not any(v is None for v in key_values): - parts = model._routing_key_from_values(key_values, conn.get_cluster(connection).protocol_version) + parts = model._routing_key_from_values(key_values) s.routing_key = parts s.keyspace = model._get_keyspace() connection = connection or model._get_connection() diff --git a/cassandra/cqltypes.py b/cassandra/cqltypes.py index e36c48563c..7a9c8e9d88 100644 --- a/cassandra/cqltypes.py +++ b/cassandra/cqltypes.py @@ -291,7 +291,7 @@ def __repr__(self): return '<%s>' % (self.cql_parameterized_type()) @classmethod - def from_binary(cls, byts, protocol_version): + def from_binary(cls, byts): """ Deserialize a bytestring into a value. See the deserialize() method for more information. This method differs in that if None or the empty @@ -301,19 +301,19 @@ def from_binary(cls, byts, protocol_version): return None elif len(byts) == 0 and not cls.empty_binary_ok: return EMPTY if cls.support_empty_values else None - return cls.deserialize(byts, protocol_version) + return cls.deserialize(byts) @classmethod - def to_binary(cls, val, protocol_version): + def to_binary(cls, val): """ Serialize a value into a bytestring. See the serialize() method for more information. This method differs in that if None is passed in, the result is the empty string. """ - return b'' if val is None else cls.serialize(val, protocol_version) + return b'' if val is None else cls.serialize(val) @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): """ Given a bytestring, deserialize into a value according to the protocol for this type. Note that this does not create a new instance of this @@ -323,7 +323,7 @@ def deserialize(byts, protocol_version): return byts @staticmethod - def serialize(val, protocol_version): + def serialize(val): """ Given a value appropriate for this class, serialize it according to the protocol for this type and return the corresponding bytestring. @@ -416,7 +416,7 @@ class BytesType(_CassandraType): empty_binary_ok = True @staticmethod - def serialize(val, protocol_version): + def serialize(val): return bytes(val) @@ -424,13 +424,13 @@ class DecimalType(_CassandraType): typename = 'decimal' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): scale = int32_unpack(byts[:4]) unscaled = varint_unpack(byts[4:]) return Decimal('%de%d' % (unscaled, -scale)) @staticmethod - def serialize(dec, protocol_version): + def serialize(dec): try: sign, digits, exponent = dec.as_tuple() except AttributeError: @@ -450,11 +450,11 @@ class UUIDType(_CassandraType): typename = 'uuid' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return UUID(bytes=byts) @staticmethod - def serialize(uuid, protocol_version): + def serialize(uuid): try: return uuid.bytes except AttributeError: @@ -468,11 +468,11 @@ class BooleanType(_CassandraType): typename = 'boolean' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return bool(int8_unpack(byts)) @staticmethod - def serialize(truth, protocol_version): + def serialize(truth): return int8_pack(truth) @classmethod @@ -483,11 +483,11 @@ class ByteType(_CassandraType): typename = 'tinyint' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return int8_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return int8_pack(byts) @@ -496,11 +496,11 @@ class AsciiType(_CassandraType): empty_binary_ok = True @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return byts.decode('ascii') @staticmethod - def serialize(var, protocol_version): + def serialize(var): try: return var.encode('ascii') except UnicodeDecodeError: @@ -511,11 +511,11 @@ class FloatType(_CassandraType): typename = 'float' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return float_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return float_pack(byts) @classmethod @@ -526,11 +526,11 @@ class DoubleType(_CassandraType): typename = 'double' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return double_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return double_pack(byts) @classmethod @@ -541,11 +541,11 @@ class LongType(_CassandraType): typename = 'bigint' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return int64_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return int64_pack(byts) @classmethod @@ -556,11 +556,11 @@ class Int32Type(_CassandraType): typename = 'int' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return int32_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return int32_pack(byts) @classmethod @@ -571,11 +571,11 @@ class IntegerType(_CassandraType): typename = 'varint' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return varint_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return varint_pack(byts) @@ -583,7 +583,7 @@ class InetAddressType(_CassandraType): typename = 'inet' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): if len(byts) == 16: return util.inet_ntop(socket.AF_INET6, byts) else: @@ -592,7 +592,7 @@ def deserialize(byts, protocol_version): return socket.inet_ntoa(byts) @staticmethod - def serialize(addr, protocol_version): + def serialize(addr): try: if ':' in addr: return util.inet_pton(socket.AF_INET6, addr) @@ -641,12 +641,12 @@ def interpret_datestring(val): raise ValueError("can't interpret %r as a date" % (val,)) @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): timestamp = int64_unpack(byts) / 1000.0 return util.datetime_from_timestamp(timestamp) @staticmethod - def serialize(v, protocol_version): + def serialize(v): try: # v is datetime timestamp_seconds = calendar.timegm(v.utctimetuple()) @@ -677,11 +677,11 @@ def my_timestamp(self): return util.unix_time_from_uuid1(self.val) @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return UUID(bytes=byts) @staticmethod - def serialize(timeuuid, protocol_version): + def serialize(timeuuid): try: return timeuuid.bytes except AttributeError: @@ -701,12 +701,12 @@ class SimpleDateType(_CassandraType): EPOCH_OFFSET_DAYS = 2 ** 31 @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): days = uint32_unpack(byts) - SimpleDateType.EPOCH_OFFSET_DAYS return util.Date(days) @staticmethod - def serialize(val, protocol_version): + def serialize(val): try: days = val.days_from_epoch except AttributeError: @@ -723,11 +723,11 @@ class ShortType(_CassandraType): typename = 'smallint' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return int16_unpack(byts) @staticmethod - def serialize(byts, protocol_version): + def serialize(byts): return int16_pack(byts) class TimeType(_CassandraType): @@ -740,11 +740,11 @@ class TimeType(_CassandraType): # return 8 @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return util.Time(int64_unpack(byts)) @staticmethod - def serialize(val, protocol_version): + def serialize(val): try: nano = val.nanosecond_time except AttributeError: @@ -756,12 +756,12 @@ class DurationType(_CassandraType): typename = 'duration' @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): months, days, nanoseconds = vints_unpack(byts) return util.Duration(months, days, nanoseconds) @staticmethod - def serialize(duration, protocol_version): + def serialize(duration): try: m, d, n = duration.months, duration.days, duration.nanoseconds except AttributeError: @@ -774,11 +774,11 @@ class UTF8Type(_CassandraType): empty_binary_ok = True @staticmethod - def deserialize(byts, protocol_version): + def deserialize(byts): return byts.decode('utf8') @staticmethod - def serialize(ustr, protocol_version): + def serialize(ustr): try: return ustr.encode('utf-8') except UnicodeDecodeError: @@ -794,29 +794,28 @@ class _ParameterizedType(_CassandraType): num_subtypes = 'UNKNOWN' @classmethod - def deserialize(cls, byts, protocol_version): + def deserialize(cls, byts): if not cls.subtypes: raise NotImplementedError("can't deserialize unparameterized %s" % cls.typename) - return cls.deserialize_safe(byts, protocol_version) + return cls.deserialize_safe(byts) @classmethod - def serialize(cls, val, protocol_version): + def serialize(cls, val): if not cls.subtypes: raise NotImplementedError("can't serialize unparameterized %s" % cls.typename) - return cls.serialize_safe(val, protocol_version) + return cls.serialize_safe(val) class _SimpleParameterizedType(_ParameterizedType): @classmethod - def deserialize_safe(cls, byts, protocol_version): + def deserialize_safe(cls, byts): subtype, = cls.subtypes length = 4 numelements = int32_unpack(byts[:length]) p = length result = [] - inner_proto = max(3, protocol_version) for _ in range(numelements): itemlen = int32_unpack(byts[p:p + length]) p += length @@ -825,23 +824,22 @@ def deserialize_safe(cls, byts, protocol_version): else: item = byts[p:p + itemlen] p += itemlen - result.append(subtype.from_binary(item, inner_proto)) + result.append(subtype.from_binary(item)) return cls.adapter(result) @classmethod - def serialize_safe(cls, items, protocol_version): + def serialize_safe(cls, items): if isinstance(items, str): raise TypeError("Received a string for a type that expects a sequence") subtype, = cls.subtypes buf = io.BytesIO() buf.write(int32_pack(len(items))) - inner_proto = max(3, protocol_version) for item in items: if item is None: buf.write(int32_pack(-1)) else: - itembytes = subtype.to_binary(item, inner_proto) + itembytes = subtype.to_binary(item) buf.write(int32_pack(len(itembytes))) buf.write(itembytes) return buf.getvalue() @@ -864,13 +862,12 @@ class MapType(_ParameterizedType): num_subtypes = 2 @classmethod - def deserialize_safe(cls, byts, protocol_version): + def deserialize_safe(cls, byts): key_type, value_type = cls.subtypes length = 4 numelements = int32_unpack(byts[:length]) p = length - themap = util.OrderedMapSerializedKey(key_type, protocol_version) - inner_proto = max(3, protocol_version) + themap = util.OrderedMapSerializedKey(key_type) for _ in range(numelements): key_len = int32_unpack(byts[p:p + length]) p += length @@ -880,7 +877,7 @@ def deserialize_safe(cls, byts, protocol_version): else: keybytes = byts[p:p + key_len] p += key_len - key = key_type.from_binary(keybytes, inner_proto) + key = key_type.from_binary(keybytes) val_len = int32_unpack(byts[p:p + length]) p += length @@ -889,13 +886,13 @@ def deserialize_safe(cls, byts, protocol_version): else: valbytes = byts[p:p + val_len] p += val_len - val = value_type.from_binary(valbytes, inner_proto) + val = value_type.from_binary(valbytes) themap._insert_unchecked(key, keybytes, val) return themap @classmethod - def serialize_safe(cls, themap, protocol_version): + def serialize_safe(cls, themap): key_type, value_type = cls.subtypes buf = io.BytesIO() buf.write(int32_pack(len(themap))) @@ -903,16 +900,15 @@ def serialize_safe(cls, themap, protocol_version): items = themap.items() except AttributeError: raise TypeError("Got a non-map object for a map value") - inner_proto = max(3, protocol_version) for key, val in items: if key is not None: - keybytes = key_type.to_binary(key, inner_proto) + keybytes = key_type.to_binary(key) buf.write(int32_pack(len(keybytes))) buf.write(keybytes) else: buf.write(int32_pack(-1)) if val is not None: - valbytes = value_type.to_binary(val, inner_proto) + valbytes = value_type.to_binary(val) buf.write(int32_pack(len(valbytes))) buf.write(valbytes) else: @@ -924,8 +920,7 @@ class TupleType(_ParameterizedType): typename = 'tuple' @classmethod - def deserialize_safe(cls, byts, protocol_version): - proto_version = max(3, protocol_version) + def deserialize_safe(cls, byts): p = 0 values = [] for col_type in cls.subtypes: @@ -940,7 +935,7 @@ def deserialize_safe(cls, byts, protocol_version): item = None # collections inside UDTs are always encoded with at least the # version 3 format - values.append(col_type.from_binary(item, proto_version)) + values.append(col_type.from_binary(item)) if len(values) < len(cls.subtypes): nones = [None] * (len(cls.subtypes) - len(values)) @@ -949,16 +944,15 @@ def deserialize_safe(cls, byts, protocol_version): return tuple(values) @classmethod - def serialize_safe(cls, val, protocol_version): + def serialize_safe(cls, val): if len(val) > len(cls.subtypes): raise ValueError("Expected %d items in a tuple, but got %d: %s" % (len(cls.subtypes), len(val), val)) - proto_version = max(3, protocol_version) buf = io.BytesIO() for item, subtype in zip(val, cls.subtypes): if item is not None: - packed_item = subtype.to_binary(item, proto_version) + packed_item = subtype.to_binary(item) buf.write(int32_pack(len(packed_item))) buf.write(packed_item) else: @@ -1012,8 +1006,8 @@ def cql_parameterized_type(cls): return "frozen<%s>" % (cls.typename,) @classmethod - def deserialize_safe(cls, byts, protocol_version): - values = super(UserType, cls).deserialize_safe(byts, protocol_version) + def deserialize_safe(cls, byts): + values = super(UserType, cls).deserialize_safe(byts) if cls.mapped_class: return cls.mapped_class(**dict(zip(cls.fieldnames, values))) elif cls.tuple_type: @@ -1022,8 +1016,7 @@ def deserialize_safe(cls, byts, protocol_version): return tuple(values) @classmethod - def serialize_safe(cls, val, protocol_version): - proto_version = max(3, protocol_version) + def serialize_safe(cls, val): buf = io.BytesIO() for i, (fieldname, subtype) in enumerate(zip(cls.fieldnames, cls.subtypes)): # first treat as a tuple, else by custom type @@ -1035,7 +1028,7 @@ def serialize_safe(cls, val, protocol_version): log.warning(f"field {fieldname} is part of the UDT {cls.typename} but is not present in the value {val}") if item is not None: - packed_item = subtype.to_binary(item, proto_version) + packed_item = subtype.to_binary(item) buf.write(int32_pack(len(packed_item))) buf.write(packed_item) else: @@ -1085,7 +1078,7 @@ def cql_parameterized_type(cls): return "'%s'" % (typestring,) @classmethod - def deserialize_safe(cls, byts, protocol_version): + def deserialize_safe(cls, byts): result = [] for subtype in cls.subtypes: if not byts: @@ -1097,7 +1090,7 @@ def deserialize_safe(cls, byts, protocol_version): # skip element length, element, and the EOC (one byte) byts = byts[2 + element_length + 1:] - result.append(subtype.from_binary(element, protocol_version)) + result.append(subtype.from_binary(element)) return tuple(result) @@ -1125,14 +1118,14 @@ class ReversedType(_ParameterizedType): num_subtypes = 1 @classmethod - def deserialize_safe(cls, byts, protocol_version): + def deserialize_safe(cls, byts): subtype, = cls.subtypes - return subtype.from_binary(byts, protocol_version) + return subtype.from_binary(byts) @classmethod - def serialize_safe(cls, val, protocol_version): + def serialize_safe(cls, val): subtype, = cls.subtypes - return subtype.to_binary(val, protocol_version) + return subtype.to_binary(val) class FrozenType(_ParameterizedType): @@ -1140,14 +1133,14 @@ class FrozenType(_ParameterizedType): num_subtypes = 1 @classmethod - def deserialize_safe(cls, byts, protocol_version): + def deserialize_safe(cls, byts): subtype, = cls.subtypes - return subtype.from_binary(byts, protocol_version) + return subtype.from_binary(byts) @classmethod - def serialize_safe(cls, val, protocol_version): + def serialize_safe(cls, val): subtype, = cls.subtypes - return subtype.to_binary(val, protocol_version) + return subtype.to_binary(val) def is_counter_type(t): @@ -1182,11 +1175,11 @@ class PointType(CassandraType): _type = struct.pack('[[]] type_ = int8_unpack(byts[0:1]) @@ -1376,7 +1369,7 @@ def deserialize(cls, byts, protocol_version): raise ValueError('Could not deserialize %r' % (byts,)) @classmethod - def serialize(cls, v, protocol_version): + def serialize(cls, v): buf = io.BytesIO() bound_kind, bounds = None, () @@ -1444,7 +1437,7 @@ def apply_parameters(cls, params, names): return type('%s(%s)' % (cls.cass_parameterized_type_with([]), vsize), (cls,), {'vector_size': vsize, 'subtype': subtype}) @classmethod - def deserialize(cls, byts, protocol_version): + def deserialize(cls, byts): serialized_size = cls.subtype.serial_size() if serialized_size is not None: expected_byte_size = serialized_size * cls.vector_size @@ -1453,7 +1446,7 @@ def deserialize(cls, byts, protocol_version): "Expected vector of type {0} and dimension {1} to have serialized size {2}; observed serialized size of {3} instead"\ .format(cls.subtype.typename, cls.vector_size, expected_byte_size, len(byts))) indexes = (serialized_size * x for x in range(0, cls.vector_size)) - return [cls.subtype.deserialize(byts[idx:idx + serialized_size], protocol_version) for idx in indexes] + return [cls.subtype.deserialize(byts[idx:idx + serialized_size]) for idx in indexes] idx = 0 rv = [] @@ -1461,7 +1454,7 @@ def deserialize(cls, byts, protocol_version): try: size, bytes_read = uvint_unpack(byts[idx:]) idx += bytes_read - rv.append(cls.subtype.deserialize(byts[idx:idx + size], protocol_version)) + rv.append(cls.subtype.deserialize(byts[idx:idx + size])) idx += size except: raise ValueError("Error reading additional data during vector deserialization after successfully adding {} elements"\ @@ -1473,7 +1466,7 @@ def deserialize(cls, byts, protocol_version): return rv @classmethod - def serialize(cls, v, protocol_version): + def serialize(cls, v): v_length = len(v) if cls.vector_size != v_length: raise ValueError( @@ -1483,7 +1476,7 @@ def serialize(cls, v, protocol_version): serialized_size = cls.subtype.serial_size() buf = io.BytesIO() for item in v: - item_bytes = cls.subtype.serialize(item, protocol_version) + item_bytes = cls.subtype.serialize(item) if serialized_size is None: buf.write(uvint_pack(len(item_bytes))) buf.write(item_bytes) diff --git a/cassandra/deserializers.pxd b/cassandra/deserializers.pxd index 7b307226ad..ff2c45167f 100644 --- a/cassandra/deserializers.pxd +++ b/cassandra/deserializers.pxd @@ -26,18 +26,17 @@ cdef class Deserializer: # paragraph 6) cdef bint empty_binary_ok - cdef deserialize(self, Buffer *buf, int protocol_version) - # cdef deserialize(self, CString byts, protocol_version) + cdef deserialize(self, Buffer *buf) + # cdef deserialize(self, CString byts) cdef inline object from_binary(Deserializer deserializer, - Buffer *buf, - int protocol_version): + Buffer *buf): if buf.size < 0: return None elif buf.size == 0 and not deserializer.empty_binary_ok: return _ret_empty(deserializer, buf.size) else: - return deserializer.deserialize(buf, protocol_version) + return deserializer.deserialize(buf) cdef _ret_empty(Deserializer deserializer, Py_ssize_t buf_size) diff --git a/cassandra/deserializers.pyx b/cassandra/deserializers.pyx index 97d249d02f..fd84b2a1d6 100644 --- a/cassandra/deserializers.pyx +++ b/cassandra/deserializers.pyx @@ -36,12 +36,12 @@ cdef class Deserializer: self.cqltype = cqltype self.empty_binary_ok = cqltype.empty_binary_ok - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): raise NotImplementedError cdef class DesBytesType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): if buf.size == 0: return b"" return to_bytes(buf) @@ -50,14 +50,14 @@ cdef class DesBytesType(Deserializer): # It is switched in by simply overwriting DesBytesType: # deserializers.DesBytesType = deserializers.DesBytesTypeByteArray cdef class DesBytesTypeByteArray(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): if buf.size == 0: return bytearray() return bytearray(buf.ptr[:buf.size]) # TODO: Use libmpdec: http://www.bytereef.org/mpdecimal/index.html cdef class DesDecimalType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): cdef Buffer varint_buf slice_buffer(buf, &varint_buf, 4, buf.size - 4) @@ -68,56 +68,56 @@ cdef class DesDecimalType(Deserializer): cdef class DesUUIDType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return UUID(bytes=to_bytes(buf)) cdef class DesBooleanType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): if unpack_num[int8_t](buf): return True return False cdef class DesByteType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[int8_t](buf) cdef class DesAsciiType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): if buf.size == 0: return "" return to_bytes(buf).decode('ascii') cdef class DesFloatType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[float](buf) cdef class DesDoubleType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[double](buf) cdef class DesLongType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[int64_t](buf) cdef class DesInt32Type(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[int32_t](buf) cdef class DesIntegerType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return varint_unpack(buf) cdef class DesInetAddressType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): cdef bytes byts = to_bytes(buf) # TODO: optimize inet_ntop, inet_ntoa @@ -134,7 +134,7 @@ cdef class DesCounterColumnType(DesLongType): cdef class DesDateType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): cdef double timestamp = unpack_num[int64_t](buf) / 1000.0 return datetime_from_timestamp(timestamp) @@ -144,7 +144,7 @@ cdef class TimestampType(DesDateType): cdef class TimeUUIDType(DesDateType): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return UUID(bytes=to_bytes(buf)) @@ -154,23 +154,23 @@ cdef class TimeUUIDType(DesDateType): EPOCH_OFFSET_DAYS = 2 ** 31 cdef class DesSimpleDateType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): days = unpack_num[uint32_t](buf) - EPOCH_OFFSET_DAYS return util.Date(days) cdef class DesShortType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return unpack_num[int16_t](buf) cdef class DesTimeType(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): return util.Time(unpack_num[int64_t](buf)) cdef class DesUTF8Type(Deserializer): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): if buf.size == 0: return "" cdef val = to_bytes(buf) @@ -207,19 +207,19 @@ cdef class _DesSingleParamType(_DesParameterizedType): # List and set deserialization cdef class DesListType(_DesSingleParamType): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): result = _deserialize_list_or_set( - buf, protocol_version, self.deserializer) + buf, self.deserializer) return result cdef class DesSetType(DesListType): - cdef deserialize(self, Buffer *buf, int protocol_version): - return util.sortedset(DesListType.deserialize(self, buf, protocol_version)) + cdef deserialize(self, Buffer *buf): + return util.sortedset(DesListType.deserialize(self, buf)) -cdef list _deserialize_list_or_set(Buffer *buf, int protocol_version, +cdef list _deserialize_list_or_set(Buffer *buf, Deserializer deserializer): """ Deserialize a list or set. @@ -233,10 +233,9 @@ cdef list _deserialize_list_or_set(Buffer *buf, int protocol_version, _unpack_len(buf, 0, &numelements) offset = sizeof(int32_t) - protocol_version = max(3, protocol_version) for _ in range(numelements): subelem(buf, &elem_buf, &offset) - result.append(from_binary(deserializer, &elem_buf, protocol_version)) + result.append(from_binary(deserializer, &elem_buf)) return result @@ -277,18 +276,18 @@ cdef class DesMapType(_DesParameterizedType): self.key_deserializer = self.deserializers[0] self.val_deserializer = self.deserializers[1] - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): key_type, val_type = self.cqltype.subtypes result = _deserialize_map( - buf, protocol_version, + buf, self.key_deserializer, self.val_deserializer, key_type, val_type) return result -cdef _deserialize_map(Buffer *buf, int protocol_version, +cdef _deserialize_map(Buffer *buf, Deserializer key_deserializer, Deserializer val_deserializer, key_type, val_type): cdef Buffer key_buf, val_buf @@ -300,13 +299,12 @@ cdef _deserialize_map(Buffer *buf, int protocol_version, _unpack_len(buf, 0, &numelements) offset = sizeof(int32_t) - themap = util.OrderedMapSerializedKey(key_type, protocol_version) - protocol_version = max(3, protocol_version) + themap = util.OrderedMapSerializedKey(key_type) for _ in range(numelements): subelem(buf, &key_buf, &offset) subelem(buf, &val_buf, &offset) - key = from_binary(key_deserializer, &key_buf, protocol_version) - val = from_binary(val_deserializer, &val_buf, protocol_version) + key = from_binary(key_deserializer, &key_buf) + val = from_binary(val_deserializer, &val_buf) themap._insert_unchecked(key, to_bytes(&key_buf), val) return themap @@ -317,7 +315,7 @@ cdef class DesTupleType(_DesParameterizedType): # TODO: Use TupleRowParser to parse these tuples - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): cdef Py_ssize_t i, p cdef int32_t itemlen cdef tuple res = tuple_new(self.subtypes_len) @@ -325,10 +323,6 @@ cdef class DesTupleType(_DesParameterizedType): cdef Buffer itemlen_buf cdef Deserializer deserializer - # collections inside UDTs are always encoded with at least the - # version 3 format - protocol_version = max(3, protocol_version) - p = 0 values = [] for i in range(self.subtypes_len): @@ -342,7 +336,7 @@ cdef class DesTupleType(_DesParameterizedType): p += itemlen deserializer = self.deserializers[i] - item = from_binary(deserializer, &item_buf, protocol_version) + item = from_binary(deserializer, &item_buf) tuple_set(res, i, item) @@ -350,9 +344,9 @@ cdef class DesTupleType(_DesParameterizedType): cdef class DesUserType(DesTupleType): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): typ = self.cqltype - values = DesTupleType.deserialize(self, buf, protocol_version) + values = DesTupleType.deserialize(self, buf) if typ.mapped_class: return typ.mapped_class(**dict(zip(typ.fieldnames, values))) elif typ.tuple_type: @@ -362,7 +356,7 @@ cdef class DesUserType(DesTupleType): cdef class DesCompositeType(_DesParameterizedType): - cdef deserialize(self, Buffer *buf, int protocol_version): + cdef deserialize(self, Buffer *buf): cdef Py_ssize_t i, idx, start cdef Buffer elem_buf cdef int16_t element_length @@ -387,7 +381,7 @@ cdef class DesCompositeType(_DesParameterizedType): slice_buffer(buf, &elem_buf, 2, element_length) deserializer = self.deserializers[i] - item = from_binary(deserializer, &elem_buf, protocol_version) + item = from_binary(deserializer, &elem_buf) tuple_set(res, i, item) # skip element length, element, and the EOC (one byte) @@ -401,13 +395,13 @@ DesDynamicCompositeType = DesCompositeType cdef class DesReversedType(_DesSingleParamType): - cdef deserialize(self, Buffer *buf, int protocol_version): - return from_binary(self.deserializer, buf, protocol_version) + cdef deserialize(self, Buffer *buf): + return from_binary(self.deserializer, buf) cdef class DesFrozenType(_DesSingleParamType): - cdef deserialize(self, Buffer *buf, int protocol_version): - return from_binary(self.deserializer, buf, protocol_version) + cdef deserialize(self, Buffer *buf): + return from_binary(self.deserializer, buf) #-------------------------------------------------------------------------- @@ -431,8 +425,8 @@ cdef class GenericDeserializer(Deserializer): Wrap a generic datatype for deserialization """ - cdef deserialize(self, Buffer *buf, int protocol_version): - return self.cqltype.deserialize(to_bytes(buf), protocol_version) + cdef deserialize(self, Buffer *buf): + return self.cqltype.deserialize(to_bytes(buf)) def __repr__(self): return "GenericDeserializer(%s)" % (self.cqltype,) diff --git a/cassandra/metadata.py b/cassandra/metadata.py index b85308449e..8716b688f6 100644 --- a/cassandra/metadata.py +++ b/cassandra/metadata.py @@ -3495,7 +3495,7 @@ def group_keys_by_replica(session, keyspace, table, keys): distance = cluster._default_load_balancing_policy.distance for key in keys: - serialized_key = [serializer.serialize(pk, cluster.protocol_version) + serialized_key = [serializer.serialize(pk) for serializer, pk in zip(serializers, key)] if len(serialized_key) == 1: routing_key = serialized_key[0] diff --git a/cassandra/numpy_parser.pyx b/cassandra/numpy_parser.pyx index 0ad34f66e2..8687305ae8 100644 --- a/cassandra/numpy_parser.pyx +++ b/cassandra/numpy_parser.pyx @@ -156,7 +156,7 @@ cdef inline int unpack_row( if arr.is_object: deserializer = desc.deserializers[i] - val = from_binary(deserializer, &buf, desc.protocol_version) + val = from_binary(deserializer, &buf) Py_INCREF(val) ( arr.buf_ptr)[0] = val elif buf.size >= 0: diff --git a/cassandra/obj_parser.pyx b/cassandra/obj_parser.pyx index cf43771dd7..7155c50c64 100644 --- a/cassandra/obj_parser.pyx +++ b/cassandra/obj_parser.pyx @@ -81,9 +81,9 @@ cdef class TupleRowParser(RowParser): decrypted_bytes = ce_policy.decrypt(coldesc, to_bytes(&buf)) PyBytes_AsStringAndSize(decrypted_bytes, &newbuf.ptr, &newbuf.size) deserializer = find_deserializer(ce_policy.column_type(coldesc)) - val = from_binary(deserializer, &newbuf, desc.protocol_version) + val = from_binary(deserializer, &newbuf) else: - val = from_binary(deserializer, &buf, desc.protocol_version) + val = from_binary(deserializer, &buf) except Exception as e: raise DriverException('Failed decoding result column "%s" of type %s: %s' % (desc.colnames[i], desc.coltypes[i].cql_parameterized_type(), diff --git a/cassandra/parsing.pxd b/cassandra/parsing.pxd index 27dc368b07..8fcee2c45e 100644 --- a/cassandra/parsing.pxd +++ b/cassandra/parsing.pxd @@ -21,7 +21,6 @@ cdef class ParseDesc: cdef public object column_encryption_policy cdef public list coldescs cdef Deserializer[::1] deserializers - cdef public int protocol_version cdef Py_ssize_t rowsize cdef class ColumnParser: diff --git a/cassandra/parsing.pyx b/cassandra/parsing.pyx index 954767d227..c67f18fd88 100644 --- a/cassandra/parsing.pyx +++ b/cassandra/parsing.pyx @@ -19,13 +19,12 @@ Module containing the definitions and declarations (parsing.pxd) for parsers. cdef class ParseDesc: """Description of what structure to parse""" - def __init__(self, colnames, coltypes, column_encryption_policy, coldescs, deserializers, protocol_version): + def __init__(self, colnames, coltypes, column_encryption_policy, coldescs, deserializers): self.colnames = colnames self.coltypes = coltypes self.column_encryption_policy = column_encryption_policy self.coldescs = coldescs self.deserializers = deserializers - self.protocol_version = protocol_version self.rowsize = len(colnames) diff --git a/cassandra/protocol.py b/cassandra/protocol.py index f37633a756..4c484fa7c3 100644 --- a/cassandra/protocol.py +++ b/cassandra/protocol.py @@ -449,25 +449,6 @@ def recv_body(cls, f, *args): return cls(authenticator=authname) -class CredentialsMessage(_MessageType): - opcode = 0x04 - name = 'CREDENTIALS' - - def __init__(self, creds): - self.creds = creds - - def send_body(self, f, protocol_version): - if protocol_version > 1: - raise UnsupportedOperation( - "Credentials-based authentication is not supported with " - "protocol version 2 or higher. Use the SASL authentication " - "mechanism instead.") - write_short(f, len(self.creds)) - for credkey, credval in self.creds.items(): - write_string(f, credkey) - write_string(f, credval) - - class AuthChallengeMessage(_MessageType): opcode = 0x0E name = 'AUTH_CHALLENGE' @@ -695,7 +676,7 @@ def recv(self, f, protocol_version, protocol_features, user_type_map, result_met if self.kind == RESULT_KIND_VOID: return elif self.kind == RESULT_KIND_ROWS: - self.recv_results_rows(f, protocol_version, user_type_map, result_metadata, column_encryption_policy) + self.recv_results_rows(f, user_type_map, result_metadata, column_encryption_policy) elif self.kind == RESULT_KIND_SET_KEYSPACE: self.new_keyspace = read_string(f) elif self.kind == RESULT_KIND_PREPARED: @@ -712,7 +693,7 @@ def recv_body(cls, f, protocol_version, protocol_features, user_type_map, result msg.recv(f, protocol_version, protocol_features, user_type_map, result_metadata, column_encryption_policy) return msg - def recv_results_rows(self, f, protocol_version, user_type_map, result_metadata, column_encryption_policy): + def recv_results_rows(self, f, user_type_map, result_metadata, column_encryption_policy): self.recv_results_metadata(f, user_type_map) column_metadata = self.column_metadata or result_metadata rowcount = read_int(f) @@ -725,7 +706,7 @@ def decode_val(val, col_md, col_desc): uses_ce = column_encryption_policy and column_encryption_policy.contains_column(col_desc) col_type = column_encryption_policy.column_type(col_desc) if uses_ce else col_md[3] raw_bytes = column_encryption_policy.decrypt(col_desc, val) if uses_ce else val - return col_type.from_binary(raw_bytes, protocol_version) + return col_type.from_binary(raw_bytes) def decode_row(row): return tuple(decode_val(val, col_md, col_desc) for val, col_md, col_desc in zip(row, column_metadata, col_descs)) @@ -748,7 +729,7 @@ def recv_results_prepared(self, f, protocol_version, protocol_features, user_typ self.result_metadata_id = read_binary_string(f) else: self.result_metadata_id = None - self.recv_prepared_metadata(f, protocol_version, protocol_features, user_type_map) + self.recv_prepared_metadata(f, protocol_features, user_type_map) def recv_results_metadata(self, f, user_type_map): flags = read_int(f) @@ -786,14 +767,13 @@ def recv_results_metadata(self, f, user_type_map): self.column_metadata = column_metadata - def recv_prepared_metadata(self, f, protocol_version, protocol_features, user_type_map): + def recv_prepared_metadata(self, f, protocol_features, user_type_map): flags = read_int(f) self.is_lwt = protocol_features.lwt_info.get_lwt_flag(flags) if protocol_features.lwt_info is not None else False colcount = read_int(f) pk_indexes = None - if protocol_version >= 4: - num_pk_indexes = read_int(f) - pk_indexes = [read_short(f) for _ in range(num_pk_indexes)] + num_pk_indexes = read_int(f) + pk_indexes = [read_short(f) for _ in range(num_pk_indexes)] glob_tblspec = bool(flags & self._FLAGS_GLOBAL_TABLES_SPEC) if glob_tblspec: @@ -1086,8 +1066,6 @@ def encode_message(cls, msg, stream_id, protocol_version, compressor, allow_beta """ flags = 0 if msg.custom_payload: - if protocol_version < 4: - raise UnsupportedOperation("Custom key/value payloads can only be used with protocol version 4 or higher") flags |= CUSTOM_PAYLOAD_FLAG if msg.tracing: diff --git a/cassandra/query.py b/cassandra/query.py index 6c6878fdb4..85dbdd2a52 100644 --- a/cassandra/query.py +++ b/cassandra/query.py @@ -377,9 +377,6 @@ def is_lwt(self): conditional update. Serial reads should use the regular :attr:`consistency_level`. - Serial consistency levels may only be used against Cassandra 2.0+ - and the :attr:`~.Cluster.protocol_version` must be set to 2 or higher. - See :doc:`/lwt` for a discussion on how to work with results returned from conditional statements. @@ -448,7 +445,6 @@ class PreparedStatement(object): custom_payload = None fetch_size = FETCH_SIZE_UNSET keyspace = None # change to prepared_keyspace in major release - protocol_version = None query_id = None query_string = None result_metadata = None @@ -460,14 +456,13 @@ class PreparedStatement(object): _is_lwt = False def __init__(self, column_metadata, query_id, routing_key_indexes, query, - keyspace, protocol_version, result_metadata, result_metadata_id, + keyspace, result_metadata, result_metadata_id, is_lwt=False, column_encryption_policy=None): self.column_metadata = column_metadata self.query_id = query_id self.routing_key_indexes = routing_key_indexes self.query_string = query self.keyspace = keyspace - self.protocol_version = protocol_version self.result_metadata = result_metadata self.result_metadata_id = result_metadata_id self.column_encryption_policy = column_encryption_policy @@ -476,11 +471,11 @@ def __init__(self, column_metadata, query_id, routing_key_indexes, query, @classmethod def from_message(cls, query_id, column_metadata, pk_indexes, cluster_metadata, - query, prepared_keyspace, protocol_version, result_metadata, + query, prepared_keyspace, result_metadata, result_metadata_id, is_lwt, column_encryption_policy=None): if not column_metadata: return PreparedStatement(column_metadata, query_id, None, - query, prepared_keyspace, protocol_version, result_metadata, + query, prepared_keyspace, result_metadata, result_metadata_id, is_lwt, column_encryption_policy) if pk_indexes: @@ -506,7 +501,7 @@ def from_message(cls, query_id, column_metadata, pk_indexes, cluster_metadata, pass # statement; just leave routing_key_indexes as None return PreparedStatement(column_metadata, query_id, routing_key_indexes, - query, prepared_keyspace, protocol_version, result_metadata, + query, prepared_keyspace, result_metadata, result_metadata_id, is_lwt, column_encryption_policy) def bind(self, values): @@ -586,7 +581,7 @@ def bind(self, values): .. versionchanged:: 2.6.0 :data:`~.UNSET_VALUE` was introduced. These can be bound as positional parameters - in a sequence, or by name in a dict. Additionally, when using protocol v4+: + in a sequence, or by name in a dict. Additionally: * short sequences will be extended to match bind parameters with UNSET_VALUE * names may be omitted from a dict with UNSET_VALUE implied. @@ -597,7 +592,6 @@ def bind(self, values): """ if values is None: values = () - proto_version = self.prepared_statement.protocol_version col_meta = self.prepared_statement.column_metadata ce_policy = self.prepared_statement.column_encryption_policy @@ -611,12 +605,7 @@ def bind(self, values): try: values.append(values_dict[col.name]) except KeyError: - if proto_version >= 4: - values.append(UNSET_VALUE) - else: - raise KeyError( - 'Column name `%s` not found in bound dict.' % - (col.name)) + values.append(UNSET_VALUE) value_len = len(values) col_meta_len = len(col_meta) @@ -626,30 +615,19 @@ def bind(self, values): "Too many arguments provided to bind() (got %d, expected %d)" % (len(values), len(col_meta))) - # this is fail-fast for clarity pre-v4. When v4 can be assumed, - # the error will be better reported when UNSET_VALUE is implicitly added. - if proto_version < 4 and self.prepared_statement.routing_key_indexes and \ - value_len < len(self.prepared_statement.routing_key_indexes): - raise ValueError( - "Too few arguments provided to bind() (got %d, required %d for routing key)" % - (value_len, len(self.prepared_statement.routing_key_indexes))) - self.raw_values = values self.values = [] for value, col_spec in zip(values, col_meta): if value is None: self.values.append(None) elif value is UNSET_VALUE: - if proto_version >= 4: - self._append_unset_value() - else: - raise ValueError("Attempt to bind UNSET_VALUE while using unsuitable protocol version (%d < 4)" % proto_version) + self._append_unset_value() else: try: col_desc = ColDesc(col_spec.keyspace_name, col_spec.table_name, col_spec.name) uses_ce = ce_policy and ce_policy.contains_column(col_desc) col_type = ce_policy.column_type(col_desc) if uses_ce else col_spec.type - col_bytes = col_type.serialize(value, proto_version) + col_bytes = col_type.serialize(value) if uses_ce: col_bytes = ce_policy.encrypt(col_desc, col_bytes) self.values.append(col_bytes) @@ -659,11 +637,10 @@ def bind(self, values): 'Expected: %s, Got: %s; (%s)' % (col_spec.name, col_spec.type, actual_type, exc)) raise TypeError(message) - if proto_version >= 4: - diff = col_meta_len - len(self.values) - if diff: - for _ in range(diff): - self._append_unset_value() + diff = col_meta_len - len(self.values) + if diff: + for _ in range(diff): + self._append_unset_value() return self diff --git a/cassandra/row_parser.pyx b/cassandra/row_parser.pyx index 88277a4593..80a66c3291 100644 --- a/cassandra/row_parser.pyx +++ b/cassandra/row_parser.pyx @@ -20,7 +20,7 @@ from cassandra.deserializers import make_deserializers include "ioutils.pyx" def make_recv_results_rows(ColumnParser colparser): - def recv_results_rows(self, f, int protocol_version, user_type_map, result_metadata, column_encryption_policy): + def recv_results_rows(self, f, user_type_map, result_metadata, column_encryption_policy): """ Parse protocol data given as a BytesIO f into a set of columns (e.g. list of tuples) This is used as the recv_results_rows method of (Fast)ResultMessage @@ -34,7 +34,7 @@ def make_recv_results_rows(ColumnParser colparser): desc = ParseDesc(self.column_names, self.column_types, column_encryption_policy, [ColDesc(md[0], md[1], md[2]) for md in column_metadata], - make_deserializers(self.column_types), protocol_version) + make_deserializers(self.column_types)) reader = BytesIOReader(f.read()) try: self.parsed_rows = colparser.parse_rows(reader, desc) diff --git a/cassandra/util.py b/cassandra/util.py index 12886d05ab..5cef7f61af 100644 --- a/cassandra/util.py +++ b/cassandra/util.py @@ -767,17 +767,16 @@ def _serialize_key(self, key): class OrderedMapSerializedKey(OrderedMap): - def __init__(self, cass_type, protocol_version): + def __init__(self, cass_type): super(OrderedMapSerializedKey, self).__init__() self.cass_key_type = cass_type - self.protocol_version = protocol_version def _insert_unchecked(self, key, flat_key, value): self._items.append((key, value)) self._index[flat_key] = len(self._items) - 1 def _serialize_key(self, key): - return self.cass_key_type.serialize(key, self.protocol_version) + return self.cass_key_type.serialize(key) @total_ordering diff --git a/docs/cqlengine/models.rst b/docs/cqlengine/models.rst index 719513f4a9..ab7f4e93f5 100644 --- a/docs/cqlengine/models.rst +++ b/docs/cqlengine/models.rst @@ -215,4 +215,4 @@ Upon declaration, types are automatically registered with the driver, so query r class*. ***Note**: UDTs were not added to the native protocol until v3. When setting up the cqlengine connection, be sure to specify -``protocol_version=3``. If using an earlier version, UDT queries will still work, but the returned type will be a namedtuple. +``protocol_version=4`` (the minimum supported version). UDT queries will return instances of your ``UserType`` class. diff --git a/docs/object-mapper.rst b/docs/object-mapper.rst index 5eb78f57b6..0aef1eed50 100644 --- a/docs/object-mapper.rst +++ b/docs/object-mapper.rst @@ -65,7 +65,7 @@ Getting Started #next, setup the connection to your cassandra server(s)... # see http://datastax.github.io/python-driver/api/cassandra/cluster.html for options # the list of hosts will be passed to create a Cluster() instance - connection.setup(['127.0.0.1'], "cqlengine", protocol_version=3) + connection.setup(['127.0.0.1'], "cqlengine", protocol_version=4) #...and create your CQL table >>> sync_table(ExampleModel) diff --git a/docs/security.rst b/docs/security.rst index 5c8645e685..633402f9a8 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -24,7 +24,7 @@ For example, suppose Cassandra is setup with its default from cassandra.auth import PlainTextAuthProvider auth_provider = PlainTextAuthProvider(username='cassandra', password='cassandra') - cluster = Cluster(auth_provider=auth_provider, protocol_version=2) + cluster = Cluster(auth_provider=auth_provider) diff --git a/docs/user-defined-types.rst b/docs/user-defined-types.rst index 32c03e37e8..8cbd5c4b7c 100644 --- a/docs/user-defined-types.rst +++ b/docs/user-defined-types.rst @@ -21,7 +21,7 @@ Map a Class to a UDT .. code-block:: python - cluster = Cluster(protocol_version=3) + cluster = Cluster(protocol_version=4) session = cluster.connect() session.set_keyspace('mykeyspace') session.execute("CREATE TYPE address (street text, zipcode int)") @@ -50,7 +50,7 @@ Map a dict to a UDT .. code-block:: python - cluster = Cluster(protocol_version=3) + cluster = Cluster(protocol_version=4) session = cluster.connect() session.set_keyspace('mykeyspace') session.execute("CREATE TYPE address (street text, zipcode int)") @@ -80,7 +80,7 @@ for the UDT: .. code-block:: python - cluster = Cluster(protocol_version=3) + cluster = Cluster(protocol_version=4) session = cluster.connect() session.set_keyspace('mykeyspace') session.execute("CREATE TYPE address (street text, zipcode int)") diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py index b4eab35875..7527fb64ad 100644 --- a/tests/integration/__init__.py +++ b/tests/integration/__init__.py @@ -163,49 +163,22 @@ def cmd_line_args_to_dict(env_var): def get_default_protocol(): if CASSANDRA_VERSION >= Version('4.0-a'): return ProtocolVersion.V5 - if CASSANDRA_VERSION >= Version('3.10'): - return 4 - if CASSANDRA_VERSION >= Version('2.2'): - return 4 - elif CASSANDRA_VERSION >= Version('2.1'): - return 3 else: - raise Exception("Running tests with an unsupported Cassandra version: {0}".format(CASSANDRA_VERSION)) + return 4 def get_scylla_default_protocol(): - if len(CASSANDRA_VERSION.release) == 4: - # An enterprise, i.e. 2021.1.6 - if CASSANDRA_VERSION > Version('2019'): - return 4 - return 3 - if CASSANDRA_VERSION >= Version('3.0'): - return 4 - return 3 + return 4 def get_supported_protocol_versions(): """ - 2.1 -> 3 - 2.2 -> 4, 3 - 3.X -> 4, 3 - 3.10(C*) -> 5(beta),4,3 - 4.0(C*) -> 6(beta),5,4,3 -` """ + Returns supported protocol versions (v4 minimum). + """ if CASSANDRA_VERSION >= Version('4.0-beta5'): - return (3, 4, 5) - if CASSANDRA_VERSION >= Version('4.0-a'): - return (3, 4, 5) - elif CASSANDRA_VERSION >= Version('3.10'): - return (3, 4) - elif CASSANDRA_VERSION >= Version('3.0'): - return (3, 4) - elif CASSANDRA_VERSION >= Version('2.2'): - return (3, 4) - elif CASSANDRA_VERSION >= Version('2.1'): - return (3) + return (4, 5) else: - return (3,) + return (4,) def get_unsupported_lower_protocol(): @@ -213,34 +186,22 @@ def get_unsupported_lower_protocol(): This is used to determine the lowest protocol version that is NOT supported by the version of C* running """ - if SCYLLA_VERSION is not None: - return 2 - if CASSANDRA_VERSION >= Version('3.0'): - return 2 - else: - return None + return 3 def get_unsupported_upper_protocol(): """ This is used to determine the highest protocol version that is NOT - supported by the version of C* running + supported by the version of C* running. Since protocol v4 is the minimum + supported, this returns v5 or higher for older Cassandra versions. """ if SCYLLA_VERSION is not None: return 5 if CASSANDRA_VERSION >= Version('4.0-a'): return ProtocolVersion.DSE_V1 - if CASSANDRA_VERSION >= Version('3.10'): - return 5 - if CASSANDRA_VERSION >= Version('2.2'): - return 5 - elif CASSANDRA_VERSION >= Version('2.1'): - return 4 - elif CASSANDRA_VERSION >= Version('2.0'): - return 3 else: - return 2 + return 5 default_protocol_version = get_scylla_default_protocol() if SCYLLA_VERSION else get_default_protocol() @@ -267,11 +228,6 @@ def xfail_scylla_version(filter: Callable[[Version], bool], reason: str, *args, return pytest.mark.xfail(filter(current_version), reason=reason, *args, **kwargs) local = local_decorator_creator() -notprotocolv1 = unittest.skipUnless(PROTOCOL_VERSION > 1, 'Protocol v1 not supported') -greaterthanprotocolv3 = unittest.skipUnless(PROTOCOL_VERSION >= 4, 'Protocol versions less than 4 are not supported') - -greaterthancass20 = unittest.skipUnless(CASSANDRA_VERSION >= Version('2.1'), 'Cassandra version 2.1 or greater required') -greaterthancass21 = unittest.skipUnless(CASSANDRA_VERSION >= Version('2.2'), 'Cassandra version 2.2 or greater required') greaterthanorequalcass30 = unittest.skipUnless(CASSANDRA_VERSION >= Version('3.0'), 'Cassandra version 3.0 or greater required') greaterthanorequalcass31 = unittest.skipUnless(CASSANDRA_VERSION >= Version('3.1'), 'Cassandra version 3.1 or greater required') greaterthanorequalcass36 = unittest.skipUnless(CASSANDRA_VERSION >= Version('3.6'), 'Cassandra version 3.6 or greater required') @@ -281,7 +237,6 @@ def xfail_scylla_version(filter: Callable[[Version], bool], reason: str, *args, greaterthanorequalcass50 = unittest.skipUnless(CASSANDRA_VERSION >= Version('5.0-beta'), 'Cassandra version 5.0 or greater required') lessthanorequalcass40 = unittest.skipUnless(CASSANDRA_VERSION <= Version('4.0'), 'Cassandra version less or equal to 4.0 required') lessthancass40 = unittest.skipUnless(CASSANDRA_VERSION < Version('4.0'), 'Cassandra version less than 4.0 required') -lessthancass30 = unittest.skipUnless(CASSANDRA_VERSION < Version('3.0'), 'Cassandra version less then 3.0 required') # pytest.mark.xfail instead of unittest.expectedFailure because # 1. unittest doesn't skip setUpClass when used on class and we need it sometimes @@ -295,15 +250,15 @@ def xfail_scylla_version(filter: Callable[[Version], bool], reason: str, *args, reason='Scylla does not support UDFs written in Java') requires_composite_type = pytest.mark.skipif(SCYLLA_VERSION is not None, reason='Scylla does not support composite types') -requires_custom_payload = pytest.mark.skipif(SCYLLA_VERSION is not None or PROTOCOL_VERSION < 4, - reason='Scylla does not support custom payloads. Cassandra requires native protocol v4.0+') +requires_custom_payload = pytest.mark.skipif(SCYLLA_VERSION is not None, + reason='Scylla does not support custom payloads') xfail_scylla = lambda reason, *args, **kwargs: pytest.mark.xfail(SCYLLA_VERSION is not None, reason=reason, *args, **kwargs) incorrect_test = lambda reason='This test seems to be incorrect and should be fixed', *args, **kwargs: pytest.mark.xfail(reason=reason, *args, **kwargs) pypy = unittest.skipUnless(platform.python_implementation() == "PyPy", "Test is skipped unless it's on PyPy") requiresmallclockgranularity = unittest.skipIf("Windows" in platform.system() or "asyncore" in EVENT_LOOP_MANAGER, "This test is not suitible for environments with large clock granularity") -requiressimulacron = unittest.skipIf(SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"), "Simulacron jar hasn't been specified or C* version is 2.0") +requiressimulacron = unittest.skipIf(SIMULACRON_JAR is None, "Simulacron jar hasn't been specified") requirescompactstorage = xfail_scylla_version(lambda v: v >= Version('2025.1.0'), reason="ScyllaDB deprecated compact storage", raises=InvalidRequest) libevtest = unittest.skipUnless(EVENT_LOOP_MANAGER=="libev", "Test timing designed for libev loop") @@ -507,9 +462,8 @@ def use_cluster(cluster_name, nodes, ipformat=None, start=True, workloads=None, if 'graph' in workloads: jvm_args += ['-Xms1500M', '-Xmx1500M'] - else: - if PROTOCOL_VERSION >= 4 and not SCYLLA_VERSION: - jvm_args = [" -Dcassandra.custom_query_handler_class=org.apache.cassandra.cql3.CustomPayloadMirroringQueryHandler"] + elif not SCYLLA_VERSION: + jvm_args = [" -Dcassandra.custom_query_handler_class=org.apache.cassandra.cql3.CustomPayloadMirroringQueryHandler"] if len(workloads) > 0: for node in CCM_CLUSTER.nodes.values(): node.set_workloads(workloads) diff --git a/tests/integration/cqlengine/columns/test_container_columns.py b/tests/integration/cqlengine/columns/test_container_columns.py index 6fb2754877..95523dc1f3 100644 --- a/tests/integration/cqlengine/columns/test_container_columns.py +++ b/tests/integration/cqlengine/columns/test_container_columns.py @@ -18,7 +18,6 @@ import sys import traceback from uuid import uuid4 -from packaging.version import Version from cassandra import WriteTimeout, OperationTimedOut import cassandra.cqlengine.columns as columns @@ -29,7 +28,6 @@ from tests.integration import CASSANDRA_IP from tests.integration.cqlengine import is_prepend_reversed from tests.integration.cqlengine.base import BaseCassEngTestCase -from tests.integration import greaterthancass20, CASSANDRA_VERSION import pytest log = logging.getLogger(__name__) @@ -570,15 +568,12 @@ class TestTupleModel(Model): mixed_tuple = columns.Tuple(columns.Text, columns.Integer, columns.Text, required=False) -@greaterthancass20 class TestTupleColumn(BaseCassEngTestCase): @classmethod def setUpClass(cls): - # Skip annotations don't seem to skip class level teradown and setup methods - if CASSANDRA_VERSION >= Version('2.1'): - drop_table(TestTupleModel) - sync_table(TestTupleModel) + drop_table(TestTupleModel) + sync_table(TestTupleModel) @classmethod def tearDownClass(cls): @@ -774,15 +769,12 @@ class TestNestedModel(Model): set_tuple = columns.Set(columns.Tuple(columns.Integer, columns.Integer), required=False) -@greaterthancass20 class TestNestedType(BaseCassEngTestCase): @classmethod def setUpClass(cls): - # Skip annotations don't seem to skip class level teradown and setup methods - if CASSANDRA_VERSION >= Version('2.1'): - drop_table(TestNestedModel) - sync_table(TestNestedModel) + drop_table(TestNestedModel) + sync_table(TestNestedModel) @classmethod def tearDownClass(cls): diff --git a/tests/integration/cqlengine/columns/test_static_column.py b/tests/integration/cqlengine/columns/test_static_column.py index e5d63c29bb..3e45f7dea5 100644 --- a/tests/integration/cqlengine/columns/test_static_column.py +++ b/tests/integration/cqlengine/columns/test_static_column.py @@ -21,11 +21,9 @@ from cassandra.cqlengine.models import Model from tests.integration.cqlengine.base import BaseCassEngTestCase -from tests.integration import PROTOCOL_VERSION -# TODO: is this really a protocol limitation, or is it just C* version? -# good enough proxy for now -STATIC_SUPPORTED = PROTOCOL_VERSION >= 2 +# Static columns are supported for all currently supported protocol versions (v4+) +STATIC_SUPPORTED = True class TestStaticModel(Model): __test__ = False diff --git a/tests/integration/cqlengine/columns/test_validation.py b/tests/integration/cqlengine/columns/test_validation.py index ebffc0666c..ae5beed4c0 100644 --- a/tests/integration/cqlengine/columns/test_validation.py +++ b/tests/integration/cqlengine/columns/test_validation.py @@ -31,7 +31,7 @@ from cassandra.cqlengine.usertype import UserType from cassandra import util -from tests.integration import PROTOCOL_VERSION, CASSANDRA_VERSION, greaterthanorequalcass30, greaterthanorequalcass3_11 +from tests.integration import CASSANDRA_VERSION, greaterthanorequalcass30, greaterthanorequalcass3_11 from tests.integration.cqlengine.base import BaseCassEngTestCase import pytest @@ -193,7 +193,7 @@ def test_varint_io(self): class DataType(): @classmethod def setUpClass(cls): - if PROTOCOL_VERSION < 4 or CASSANDRA_VERSION < Version("3.0"): + if CASSANDRA_VERSION < Version("3.0"): return class DataTypeTest(Model): @@ -205,16 +205,15 @@ class DataTypeTest(Model): @classmethod def tearDownClass(cls): - if PROTOCOL_VERSION < 4 or CASSANDRA_VERSION < Version("3.0"): + if CASSANDRA_VERSION < Version("3.0"): return drop_table(cls.model_class) def setUp(self): - if PROTOCOL_VERSION < 4 or CASSANDRA_VERSION < Version("3.0"): - raise unittest.SkipTest("Protocol v4 datatypes " - "require native protocol 4+ and C* version >=3.0, " - "currently using protocol {0} and C* version {1}". - format(PROTOCOL_VERSION, CASSANDRA_VERSION)) + if CASSANDRA_VERSION < Version("3.0"): + raise unittest.SkipTest("Cassandra version >=3.0 required, " + "currently using C* version {0}". + format(CASSANDRA_VERSION)) def _check_value_is_correct_in_db(self, value): """ @@ -385,7 +384,7 @@ class UserModel(Model): class TestUDT(DataType, BaseCassEngTestCase): @classmethod def setUpClass(cls): - if PROTOCOL_VERSION < 4 or CASSANDRA_VERSION < Version("3.0"): + if CASSANDRA_VERSION < Version("3.0"): return cls.db_klass, cls.python_klass = UserDefinedType, User diff --git a/tests/integration/cqlengine/columns/test_value_io.py b/tests/integration/cqlengine/columns/test_value_io.py index 758ca714a6..7c17e80023 100644 --- a/tests/integration/cqlengine/columns/test_value_io.py +++ b/tests/integration/cqlengine/columns/test_value_io.py @@ -24,7 +24,6 @@ from cassandra.util import Date, Time -from tests.integration import PROTOCOL_VERSION from tests.integration.cqlengine.base import BaseCassEngTestCase @@ -198,25 +197,11 @@ def comparator_converter(self, val): class ProtocolV4Test(BaseColumnIOTest): + pass - @classmethod - def setUpClass(cls): - if PROTOCOL_VERSION >= 4: - super(ProtocolV4Test, cls).setUpClass() - - @classmethod - def tearDownClass(cls): - if PROTOCOL_VERSION >= 4: - super(ProtocolV4Test, cls).tearDownClass() class TestDate(ProtocolV4Test): - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - - super(TestDate, self).setUp() - column = columns.Date now = Date(datetime.now().date()) @@ -226,12 +211,6 @@ def setUp(self): class TestTime(ProtocolV4Test): - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - - super(TestTime, self).setUp() - column = columns.Time pkey_val = Time(time(2, 12, 7, 48)) @@ -240,12 +219,6 @@ def setUp(self): class TestSmallInt(ProtocolV4Test): - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - - super(TestSmallInt, self).setUp() - column = columns.SmallInt pkey_val = 16768 @@ -254,12 +227,6 @@ def setUp(self): class TestTinyInt(ProtocolV4Test): - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - - super(TestTinyInt, self).setUp() - column = columns.TinyInt pkey_val = 1 diff --git a/tests/integration/cqlengine/connections/test_connection.py b/tests/integration/cqlengine/connections/test_connection.py index 78d5133e63..9160d43fce 100644 --- a/tests/integration/cqlengine/connections/test_connection.py +++ b/tests/integration/cqlengine/connections/test_connection.py @@ -23,7 +23,7 @@ from cassandra.policies import RoundRobinPolicy from cassandra.query import dict_factory -from tests.integration import CASSANDRA_IP, PROTOCOL_VERSION, execute_with_long_wait_retry, local, TestCluster +from tests.integration import CASSANDRA_IP, execute_with_long_wait_retry, local, TestCluster from tests.integration.cqlengine.base import BaseCassEngTestCase from tests.integration.cqlengine import DEFAULT_KEYSPACE, setup_connection diff --git a/tests/integration/cqlengine/management/test_management.py b/tests/integration/cqlengine/management/test_management.py index 1332680cef..08cae93e69 100644 --- a/tests/integration/cqlengine/management/test_management.py +++ b/tests/integration/cqlengine/management/test_management.py @@ -23,7 +23,7 @@ from cassandra.cqlengine.models import Model from cassandra.cqlengine import columns -from tests.integration import PROTOCOL_VERSION, greaterthancass20, requires_collection_indexes, \ +from tests.integration import requires_collection_indexes, \ MockLoggingHandler, CASSANDRA_VERSION, SCYLLA_VERSION, xfail_scylla from tests.integration.cqlengine.base import BaseCassEngTestCase from tests.integration.cqlengine.query.test_queryset import TestModel @@ -369,11 +369,10 @@ def test_sync_warnings(self): sync_table(BaseInconsistent) sync_table(ChangedInconsistent) assert 'differing from the model type' in mock_handler.messages.get('warning')[0] - if CASSANDRA_VERSION >= Version('2.1'): - sync_type(DEFAULT_KEYSPACE, BaseInconsistentType) - mock_handler.reset() - sync_type(DEFAULT_KEYSPACE, ChangedInconsistentType) - assert 'differing from the model user type' in mock_handler.messages.get('warning')[0] + sync_type(DEFAULT_KEYSPACE, BaseInconsistentType) + mock_handler.reset() + sync_type(DEFAULT_KEYSPACE, ChangedInconsistentType) + assert 'differing from the model user type' in mock_handler.messages.get('warning')[0] class TestIndexSetModel(Model): @@ -432,7 +431,6 @@ def test_sync_index_case_sensitive(self): table_meta = management._get_table_metadata(IndexCaseSensitiveModel) assert management._get_index_name_by_column(table_meta, 'second_key') is not None - @greaterthancass20 @requires_collection_indexes @xfail_scylla("scylladb/scylladb#22019 - Scylla incorrectly reports target as keys(%s) for sets") def test_sync_indexed_set(self): @@ -464,9 +462,6 @@ def test_failure(self): class StaticColumnTests(BaseCassEngTestCase): def test_static_columns(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest("Native protocol 2+ required, currently using: {0}".format(PROTOCOL_VERSION)) - class StaticModel(Model): id = columns.Integer(primary_key=True) c = columns.Integer(primary_key=True) diff --git a/tests/integration/cqlengine/model/test_model_io.py b/tests/integration/cqlengine/model/test_model_io.py index f55815310a..a1ce2d6984 100644 --- a/tests/integration/cqlengine/model/test_model_io.py +++ b/tests/integration/cqlengine/model/test_model_io.py @@ -30,7 +30,7 @@ from cassandra.cqlengine.statements import SelectStatement, DeleteStatement, WhereClause from cassandra.cqlengine.operators import EqualsOperator -from tests.integration import PROTOCOL_VERSION, greaterthanorequalcass3_10 +from tests.integration import greaterthanorequalcass3_10 from tests.integration.cqlengine.base import BaseCassEngTestCase from tests.integration.cqlengine import DEFAULT_KEYSPACE from tests.util import assertSetEqual @@ -248,9 +248,6 @@ def test_can_insert_model_with_all_protocol_v4_column_types(self): @test_category data_types:primitive """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - class v4DatatypesModel(Model): id = columns.Integer(primary_key=True) a = columns.Date() @@ -672,25 +669,15 @@ class TestQuerying(BaseCassEngTestCase): @classmethod def setUpClass(cls): - if PROTOCOL_VERSION < 4: - return - super(TestQuerying, cls).setUpClass() drop_table(TestQueryModel) sync_table(TestQueryModel) @classmethod def tearDownClass(cls): - if PROTOCOL_VERSION < 4: - return - super(TestQuerying, cls).tearDownClass() drop_table(TestQueryModel) - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Date query tests require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) - def test_query_with_date(self): uid = uuid4() day = date(2013, 11, 26) @@ -770,7 +757,7 @@ def test_routing_key_is_ignored(self): """.format(DEFAULT_KEYSPACE)) bound = prepared.bind((1, 2)) - mrk = BasicModelNoRouting._routing_key_from_values([1], self.session.cluster.protocol_version) + mrk = BasicModelNoRouting._routing_key_from_values([1]) simple = SimpleStatement("") simple.routing_key = mrk assert bound.routing_key != simple.routing_key @@ -802,7 +789,7 @@ def test_routing_key_generation_basic(self): """.format(DEFAULT_KEYSPACE)) bound = prepared.bind((1, 2)) - mrk = BasicModel._routing_key_from_values([1], self.session.cluster.protocol_version) + mrk = BasicModel._routing_key_from_values([1]) simple = SimpleStatement("") simple.routing_key = mrk assert bound.routing_key == simple.routing_key @@ -823,7 +810,7 @@ def test_routing_key_generation_multi(self): INSERT INTO {0}.basic_model_routing_multi (k, v) VALUES (?, ?) """.format(DEFAULT_KEYSPACE)) bound = prepared.bind((1, 2)) - mrk = BasicModelMulti._routing_key_from_values([1, 2], self.session.cluster.protocol_version) + mrk = BasicModelMulti._routing_key_from_values([1, 2]) simple = SimpleStatement("") simple.routing_key = mrk assert bound.routing_key == simple.routing_key @@ -849,7 +836,7 @@ def test_routing_key_generation_complex(self): float = 1.2 text_2 = "text_2" bound = prepared.bind((partition, cluster, count, text, float, text_2)) - mrk = ComplexModelRouting._routing_key_from_values([partition, cluster, text, float], self.session.cluster.protocol_version) + mrk = ComplexModelRouting._routing_key_from_values([partition, cluster, text, float]) simple = SimpleStatement("") simple.routing_key = mrk assert bound.routing_key == simple.routing_key diff --git a/tests/integration/cqlengine/model/test_udts.py b/tests/integration/cqlengine/model/test_udts.py index 80f1b9693f..4580bf0da2 100644 --- a/tests/integration/cqlengine/model/test_udts.py +++ b/tests/integration/cqlengine/model/test_udts.py @@ -25,7 +25,6 @@ from cassandra.cqlengine import ValidationError from cassandra.util import Date, Time -from tests.integration import PROTOCOL_VERSION from tests.integration.cqlengine.base import BaseCassEngTestCase from tests.integration.cqlengine import DEFAULT_KEYSPACE import pytest @@ -65,10 +64,6 @@ class AllDatatypesModel(Model): class UserDefinedTypeTests(BaseCassEngTestCase): - def setUp(self): - if PROTOCOL_VERSION < 3: - raise unittest.SkipTest("UDTs require native protocol 3+, currently using: {0}".format(PROTOCOL_VERSION)) - def test_can_create_udts(self): class User(UserType): age = columns.Integer() @@ -302,8 +297,6 @@ def test_can_insert_udts_protocol_v4_datatypes(self): @test_category data_types:udt """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol v4 datatypes in UDTs require native protocol 4+, currently using: {0}".format(PROTOCOL_VERSION)) class Allv4Datatypes(UserType): a = columns.Date() diff --git a/tests/integration/cqlengine/model/test_updates.py b/tests/integration/cqlengine/model/test_updates.py index c64df8fdcc..d8ebfa56fe 100644 --- a/tests/integration/cqlengine/model/test_updates.py +++ b/tests/integration/cqlengine/model/test_updates.py @@ -17,7 +17,6 @@ from cassandra.cqlengine import ValidationError -from tests.integration import greaterthancass21 from tests.integration.cqlengine.base import BaseCassEngTestCase from cassandra.cqlengine.models import Model from cassandra.cqlengine import columns @@ -178,7 +177,6 @@ class ModelWithDefaultCollection(Model): udt = columns.UserDefinedType(UDT) udt_default = columns.UserDefinedType(UDT, default=UDT(age=1, mf={2: 2})) -@greaterthancass21 class ModelWithDefaultTests(BaseCassEngTestCase): @classmethod diff --git a/tests/integration/cqlengine/query/test_queryset.py b/tests/integration/cqlengine/query/test_queryset.py index 34b4ab5964..06927c4059 100644 --- a/tests/integration/cqlengine/query/test_queryset.py +++ b/tests/integration/cqlengine/query/test_queryset.py @@ -17,7 +17,6 @@ from datetime import datetime from uuid import uuid4 -from packaging.version import Version import uuid from cassandra.cluster import Session @@ -38,8 +37,7 @@ from cassandra.cqlengine import operators from cassandra.util import uuid_from_time from cassandra.cqlengine.connection import get_session -from tests.integration import PROTOCOL_VERSION, CASSANDRA_VERSION, greaterthancass20, greaterthancass21, \ - greaterthanorequalcass30, TestCluster, requires_collection_indexes +from tests.integration import greaterthanorequalcass30, TestCluster, requires_collection_indexes from tests.integration.cqlengine import execute_count, DEFAULT_KEYSPACE import pytest @@ -362,22 +360,21 @@ def setUpClass(cls): IndexedTestModel.objects.create(test_id=11, attempt_id=3, description='try12', expected_result=75, test_result=45) - if CASSANDRA_VERSION >= Version('2.1'): - drop_table(IndexedCollectionsTestModel) - sync_table(IndexedCollectionsTestModel) - IndexedCollectionsTestModel.objects.create(test_id=12, attempt_id=3, description='list12', expected_result=75, - test_result=45, test_list=[1, 2, 42], test_set=set([1, 2, 3]), - test_map={'1': 1, '2': 2, '3': 3}) - IndexedCollectionsTestModel.objects.create(test_id=13, attempt_id=3, description='list13', expected_result=75, - test_result=45, test_list=[3, 4, 5], test_set=set([4, 5, 42]), - test_map={'1': 5, '2': 6, '3': 7}) - IndexedCollectionsTestModel.objects.create(test_id=14, attempt_id=3, description='list14', expected_result=75, - test_result=45, test_list=[1, 2, 3], test_set=set([1, 2, 3]), - test_map={'1': 1, '2': 2, '3': 42}) - - IndexedCollectionsTestModel.objects.create(test_id=15, attempt_id=4, description='list14', expected_result=75, - test_result=45, test_list_no_index=[1, 2, 3], test_set_no_index=set([1, 2, 3]), - test_map_no_index={'1': 1, '2': 2, '3': 42}) + drop_table(IndexedCollectionsTestModel) + sync_table(IndexedCollectionsTestModel) + IndexedCollectionsTestModel.objects.create(test_id=12, attempt_id=3, description='list12', expected_result=75, + test_result=45, test_list=[1, 2, 42], test_set=set([1, 2, 3]), + test_map={'1': 1, '2': 2, '3': 3}) + IndexedCollectionsTestModel.objects.create(test_id=13, attempt_id=3, description='list13', expected_result=75, + test_result=45, test_list=[3, 4, 5], test_set=set([4, 5, 42]), + test_map={'1': 5, '2': 6, '3': 7}) + IndexedCollectionsTestModel.objects.create(test_id=14, attempt_id=3, description='list14', expected_result=75, + test_result=45, test_list=[1, 2, 3], test_set=set([1, 2, 3]), + test_map={'1': 1, '2': 2, '3': 42}) + + IndexedCollectionsTestModel.objects.create(test_id=15, attempt_id=4, description='list14', expected_result=75, + test_result=45, test_list_no_index=[1, 2, 3], test_set_no_index=set([1, 2, 3]), + test_map_no_index={'1': 1, '2': 2, '3': 42}) @classmethod def tearDownClass(cls): @@ -590,7 +587,6 @@ def test_zero_result(self): q = TestModel.objects.distinct(['test_id']).filter(test_id__in=[52]) assert len(q) == 0 - @greaterthancass21 @execute_count(2) def test_distinct_with_explicit_count(self): q = TestModel.objects.distinct(['test_id']) @@ -723,7 +719,6 @@ def test_primary_key_or_index_must_have_equal_relation_filter(self): q = TestModel.objects(test_id__gt=0) list([i for i in q]) - @greaterthancass20 @execute_count(7) def test_indexed_field_can_be_queried(self): """ @@ -1005,7 +1000,6 @@ class bool_model2(Model): assert len(list(bool_model2.objects(k__in=(True, False)))) == 2 -@greaterthancass20 @requires_collection_indexes class TestContainsOperator(BaseQuerySetUsage): @@ -1097,9 +1091,6 @@ def test_objects_property_returns_fresh_queryset(self): class PageQueryTests(BaseCassEngTestCase): @execute_count(3) def test_paged_result_handling(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest("Paging requires native protocol 2+, currently using: {0}".format(PROTOCOL_VERSION)) - # addresses #225 class PagingTest(Model): id = columns.Integer(primary_key=True) diff --git a/tests/integration/cqlengine/query/test_updates.py b/tests/integration/cqlengine/query/test_updates.py index cedde0cd7b..bd29395d23 100644 --- a/tests/integration/cqlengine/query/test_updates.py +++ b/tests/integration/cqlengine/query/test_updates.py @@ -22,7 +22,6 @@ from tests.integration.cqlengine import is_prepend_reversed from tests.integration.cqlengine.base import BaseCassEngTestCase, TestQueryUpdateModel from tests.integration.cqlengine import execute_count -from tests.integration import greaterthancass20 import pytest @@ -234,7 +233,6 @@ def test_map_update_none_deletes_key(self): obj = TestQueryUpdateModel.objects.get(partition=partition, cluster=cluster) assert obj.text_map == {"foo": '1'} - @greaterthancass20 @execute_count(5) def test_map_update_remove(self): """ diff --git a/tests/integration/cqlengine/test_ifexists.py b/tests/integration/cqlengine/test_ifexists.py index 6c2ff437ab..6313aa3000 100644 --- a/tests/integration/cqlengine/test_ifexists.py +++ b/tests/integration/cqlengine/test_ifexists.py @@ -21,7 +21,6 @@ from cassandra.cqlengine.query import BatchQuery, BatchType, LWTException, IfExistsWithCounterColumn from tests.integration.cqlengine.base import BaseCassEngTestCase -from tests.integration import PROTOCOL_VERSION import pytest @@ -78,7 +77,6 @@ def tearDownClass(cls): class IfExistsUpdateTests(BaseIfExistsTest): - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_update_if_exists(self): """ Tests that update with if_exists work as expected @@ -116,7 +114,6 @@ def test_update_if_exists(self): assert assertion.value.existing.get('[applied]') == False - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_batch_update_if_exists_success(self): """ Tests that batch update with if_exists work as expected @@ -150,7 +147,6 @@ def test_batch_update_if_exists_success(self): assert tm.count == 8 assert tm.text == '111111111' - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_batch_mixed_update_if_exists_success(self): """ Tests that batch update with with one bad query will still fail with LWTException @@ -172,7 +168,6 @@ def test_batch_mixed_update_if_exists_success(self): assert assertion.value.existing.get('[applied]') == False - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_delete_if_exists(self): """ Tests that delete with if_exists work, and throw proper LWT exception when they are are not applied @@ -203,7 +198,6 @@ def test_delete_if_exists(self): assert assertion.value.existing.get('[applied]') == False - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_batch_delete_if_exists_success(self): """ Tests that batch deletes with if_exists work, and throw proper LWTException when they are are not applied @@ -232,7 +226,6 @@ def test_batch_delete_if_exists_success(self): assert assertion.value.existing.get('[applied]') == False - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_batch_delete_mixed(self): """ Tests that batch deletes with multiple queries and throw proper LWTException when they are are not all applicable diff --git a/tests/integration/cqlengine/test_ifnotexists.py b/tests/integration/cqlengine/test_ifnotexists.py index 6a1dd9d4bc..4159a3f00c 100644 --- a/tests/integration/cqlengine/test_ifnotexists.py +++ b/tests/integration/cqlengine/test_ifnotexists.py @@ -21,7 +21,6 @@ from cassandra.cqlengine.query import BatchQuery, LWTException, IfNotExistsWithCounterColumn from tests.integration.cqlengine.base import BaseCassEngTestCase -from tests.integration import PROTOCOL_VERSION import pytest class TestIfNotExistsModel(Model): @@ -73,7 +72,6 @@ def tearDownClass(cls): class IfNotExistsInsertTests(BaseIfNotExistsTest): - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_insert_if_not_exists(self): """ tests that insertion with if_not_exists work as expected """ @@ -101,7 +99,6 @@ def test_insert_if_not_exists(self): assert tm.count == 8 assert tm.text == '123456789' - @unittest.skipUnless(PROTOCOL_VERSION >= 2, "only runs against the cql3 protocol v2.0") def test_batch_insert_if_not_exists(self): """ tests that batch insertion with if_not_exists work as expected """ diff --git a/tests/integration/cqlengine/test_lwt_conditional.py b/tests/integration/cqlengine/test_lwt_conditional.py index f8d9d01035..634d482749 100644 --- a/tests/integration/cqlengine/test_lwt_conditional.py +++ b/tests/integration/cqlengine/test_lwt_conditional.py @@ -22,7 +22,6 @@ from cassandra.cqlengine.statements import ConditionalClause from tests.integration.cqlengine.base import BaseCassEngTestCase -from tests.integration import greaterthancass20 import pytest @@ -43,7 +42,6 @@ class TestUpdateModel(Model): text = columns.Text(required=False, index=True) -@greaterthancass20 class TestConditional(BaseCassEngTestCase): @classmethod diff --git a/tests/integration/cqlengine/test_ttl.py b/tests/integration/cqlengine/test_ttl.py index df1afb6bf0..9fa5895566 100644 --- a/tests/integration/cqlengine/test_ttl.py +++ b/tests/integration/cqlengine/test_ttl.py @@ -15,8 +15,6 @@ import unittest -from packaging.version import Version - from cassandra import InvalidRequest from cassandra.cqlengine.management import sync_table, drop_table from tests.integration.cqlengine.base import BaseCassEngTestCase @@ -25,7 +23,6 @@ from cassandra.cqlengine import columns from unittest import mock from cassandra.cqlengine.connection import get_session -from tests.integration import CASSANDRA_VERSION, greaterthancass20 class TestTTLModel(Model): @@ -62,17 +59,15 @@ class BaseDefaultTTLTest(BaseCassEngTestCase): @classmethod def setUpClass(cls): - if CASSANDRA_VERSION >= Version('2.0'): - super(BaseDefaultTTLTest, cls).setUpClass() - sync_table(TestDefaultTTLModel) - sync_table(TestTTLModel) + super(BaseDefaultTTLTest, cls).setUpClass() + sync_table(TestDefaultTTLModel) + sync_table(TestTTLModel) @classmethod def tearDownClass(cls): - if CASSANDRA_VERSION >= Version('2.0'): - super(BaseDefaultTTLTest, cls).tearDownClass() - drop_table(TestDefaultTTLModel) - drop_table(TestTTLModel) + super(BaseDefaultTTLTest, cls).tearDownClass() + drop_table(TestDefaultTTLModel) + drop_table(TestTTLModel) class TTLQueryTests(BaseTTLTest): diff --git a/tests/integration/datatype_utils.py b/tests/integration/datatype_utils.py index 1f7fb50a05..9191f2de8d 100644 --- a/tests/integration/datatype_utils.py +++ b/tests/integration/datatype_utils.py @@ -52,12 +52,10 @@ def update_datatypes(): _cass_version, _cql_version = get_server_versions() - if _cass_version >= (2, 1, 0): - COLLECTION_TYPES.add('tuple') + COLLECTION_TYPES.add('tuple') - if _cass_version >= (2, 2, 0): - PRIMITIVE_DATATYPES.update(['date', 'time', 'smallint', 'tinyint']) - PRIMITIVE_DATATYPES_KEYS.update(['date', 'time', 'smallint', 'tinyint']) + PRIMITIVE_DATATYPES.update(['date', 'time', 'smallint', 'tinyint']) + PRIMITIVE_DATATYPES_KEYS.update(['date', 'time', 'smallint', 'tinyint']) if _cass_version >= (3, 10): PRIMITIVE_DATATYPES.add('duration') diff --git a/tests/integration/long/test_failure_types.py b/tests/integration/long/test_failure_types.py index beb10f02c0..0c3d90eb92 100644 --- a/tests/integration/long/test_failure_types.py +++ b/tests/integration/long/test_failure_types.py @@ -28,7 +28,7 @@ from cassandra.concurrent import execute_concurrent_with_args from cassandra.query import SimpleStatement from tests.integration import ( - use_singledc, PROTOCOL_VERSION, get_cluster, setup_keyspace, remove_cluster, + use_singledc, get_cluster, setup_keyspace, remove_cluster, get_node, start_cluster_wait_for_up, requiresmallclockgranularity, local, CASSANDRA_VERSION, TestCluster) @@ -43,23 +43,19 @@ @local def setup_module(): """ - We need some custom setup for this module. All unit tests in this module - require protocol >=4. We won't bother going through the setup required unless that is the - protocol version we are using. + We need some custom setup for this module. """ - # If we aren't at protocol v 4 or greater don't waste time setting anything up, all tests will be skipped - if PROTOCOL_VERSION >= 4: - use_singledc(start=False) - ccm_cluster = get_cluster() - ccm_cluster.stop() - config_options = { - 'tombstone_failure_threshold': 2000, - 'tombstone_warn_threshold': 1000, - } - ccm_cluster.set_configuration_options(config_options) - start_cluster_wait_for_up(ccm_cluster) - setup_keyspace() + use_singledc(start=False) + ccm_cluster = get_cluster() + ccm_cluster.stop() + config_options = { + 'tombstone_failure_threshold': 2000, + 'tombstone_warn_threshold': 1000, + } + ccm_cluster.set_configuration_options(config_options) + start_cluster_wait_for_up(ccm_cluster) + setup_keyspace() def teardown_module(): @@ -67,20 +63,12 @@ def teardown_module(): The rest of the tests don't need custom tombstones remove the cluster so as to not interfere with other tests. """ - if PROTOCOL_VERSION >= 4: - remove_cluster() + remove_cluster() class ClientExceptionTests(unittest.TestCase): def setUp(self): - """ - Test is skipped if run with native protocol version <4 - """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest( - "Native protocol 4,0+ is required for custom payloads, currently using %r" - % (PROTOCOL_VERSION,)) self.cluster = TestCluster() self.session = self.cluster.connect() self.nodes_currently_failing = [] diff --git a/tests/integration/long/test_large_data.py b/tests/integration/long/test_large_data.py index 0a1b368bf0..c6ddaea709 100644 --- a/tests/integration/long/test_large_data.py +++ b/tests/integration/long/test_large_data.py @@ -21,7 +21,7 @@ from cassandra.cluster import ExecutionProfile, EXEC_PROFILE_DEFAULT from cassandra.query import dict_factory from cassandra.query import SimpleStatement -from tests.integration import use_singledc, PROTOCOL_VERSION, TestCluster +from tests.integration import use_singledc, TestCluster from tests.integration.long.utils import create_schema import unittest diff --git a/tests/integration/long/test_loadbalancingpolicies.py b/tests/integration/long/test_loadbalancingpolicies.py index fd8edde14c..619e729b47 100644 --- a/tests/integration/long/test_loadbalancingpolicies.py +++ b/tests/integration/long/test_loadbalancingpolicies.py @@ -633,7 +633,7 @@ def test_token_aware_with_transient_replication(self): query = session.prepare("SELECT * FROM test_tr.users WHERE id = ?") for i in range(100): f = session.execute_async(query, (i,), trace=True) - full_dc1_replicas = [h for h in cluster.metadata.get_replicas('test_tr', cqltypes.Int32Type.serialize(i, cluster.protocol_version)) + full_dc1_replicas = [h for h in cluster.metadata.get_replicas('test_tr', cqltypes.Int32Type.serialize(i)) if h.datacenter == 'dc1'] assert len(full_dc1_replicas) == 2 diff --git a/tests/integration/simulacron/__init__.py b/tests/integration/simulacron/__init__.py index b75b67c540..6536e91c4a 100644 --- a/tests/integration/simulacron/__init__.py +++ b/tests/integration/simulacron/__init__.py @@ -13,7 +13,7 @@ # limitations under the License import unittest -from tests.integration import CASSANDRA_VERSION, SIMULACRON_JAR, PROTOCOL_VERSION +from tests.integration import SIMULACRON_JAR, PROTOCOL_VERSION from tests.integration.simulacron.utils import ( clear_queries, start_and_prime_singledc, @@ -23,8 +23,6 @@ from cassandra.cluster import Cluster -from packaging.version import Version - PROTOCOL_VERSION = min(4, PROTOCOL_VERSION) @@ -45,7 +43,7 @@ class SimulacronCluster(SimulacronBase): @classmethod def setUpClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return start_and_prime_singledc() @@ -55,7 +53,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return if cls.cluster: diff --git a/tests/integration/simulacron/test_policies.py b/tests/integration/simulacron/test_policies.py index 3f94a41222..96653b9e45 100644 --- a/tests/integration/simulacron/test_policies.py +++ b/tests/integration/simulacron/test_policies.py @@ -19,14 +19,12 @@ from cassandra.policies import ConstantSpeculativeExecutionPolicy, RoundRobinPolicy, RetryPolicy, WriteType from cassandra.protocol import OverloadedErrorMessage, IsBootstrappingErrorMessage, TruncateError, ServerError -from tests.integration import greaterthancass21, requiressimulacron, SIMULACRON_JAR, \ - CASSANDRA_VERSION +from tests.integration import requiressimulacron, SIMULACRON_JAR from tests.integration.simulacron import PROTOCOL_VERSION from tests.integration.simulacron.utils import start_and_prime_singledc, prime_query, \ stop_simulacron, NO_THEN, clear_queries from itertools import count -from packaging.version import Version import pytest @@ -48,7 +46,7 @@ class SpecExecTest(unittest.TestCase): @classmethod def setUpClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return start_and_prime_singledc() @@ -73,7 +71,7 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return cls.cluster.shutdown() @@ -82,7 +80,6 @@ def tearDownClass(cls): def tearDown(self): clear_queries() - @greaterthancass21 def test_speculative_execution(self): """ Test to ensure that speculative execution honors LBP, and that they retry appropriately. @@ -254,13 +251,13 @@ def reset_counters(self): class RetryPolicyTests(unittest.TestCase): @classmethod def setUpClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return start_and_prime_singledc() @classmethod def tearDownClass(cls): - if SIMULACRON_JAR is None or CASSANDRA_VERSION < Version("2.1"): + if SIMULACRON_JAR is None: return stop_simulacron() diff --git a/tests/integration/standard/test_authentication.py b/tests/integration/standard/test_authentication.py index eb8019bf65..a3ff97e1c7 100644 --- a/tests/integration/standard/test_authentication.py +++ b/tests/integration/standard/test_authentication.py @@ -19,7 +19,7 @@ from cassandra.cluster import NoHostAvailable from cassandra.auth import PlainTextAuthProvider, SASLClient, SaslAuthProvider -from tests.integration import use_singledc, get_cluster, remove_cluster, PROTOCOL_VERSION, \ +from tests.integration import use_singledc, get_cluster, remove_cluster, \ CASSANDRA_IP, CASSANDRA_VERSION, USE_CASS_EXTERNAL, start_cluster_wait_for_up, TestCluster from tests.integration.util import assert_quiescent_pool_state @@ -62,19 +62,12 @@ class AuthenticationTests(unittest.TestCase): """ def get_authentication_provider(self, username, password): """ - Return correct authentication provider based on protocol version. - There is a difference in the semantics of authentication provider argument with protocol versions 1 and 2 - For protocol version 2 and higher it should be a PlainTextAuthProvider object. - For protocol version 1 it should be a function taking hostname as an argument and returning a dictionary - containing username and password. + Return correct authentication provider. :param username: authentication username :param password: authentication password :return: authentication object suitable for Cluster.connect() """ - if PROTOCOL_VERSION < 2: - return lambda hostname: dict(username=username, password=password) - else: - return PlainTextAuthProvider(username=username, password=password) + return PlainTextAuthProvider(username=username, password=password) def cluster_as(self, usr, pwd): # test we can connect at least once with creds @@ -161,8 +154,6 @@ class SaslAuthenticatorTests(AuthenticationTests): Test SaslAuthProvider as PlainText """ def setUp(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest('Sasl authentication not available for protocol v1') if SASLClient is None: raise unittest.SkipTest('pure-sasl is not installed') diff --git a/tests/integration/standard/test_client_warnings.py b/tests/integration/standard/test_client_warnings.py index 781b5b7860..83572af2df 100644 --- a/tests/integration/standard/test_client_warnings.py +++ b/tests/integration/standard/test_client_warnings.py @@ -17,7 +17,7 @@ from cassandra.query import BatchStatement -from tests.integration import (use_singledc, PROTOCOL_VERSION, local, TestCluster, +from tests.integration import (use_singledc, local, TestCluster, requires_custom_payload, xfail_scylla) from tests.util import assertRegex, assertDictEqual @@ -30,9 +30,6 @@ class ClientWarningTests(unittest.TestCase): @classmethod def setUpClass(cls): - if PROTOCOL_VERSION < 4: - return - cls.cluster = TestCluster() cls.session = cls.cluster.connect() @@ -47,17 +44,8 @@ def setUpClass(cls): @classmethod def tearDownClass(cls): - if PROTOCOL_VERSION < 4: - return - cls.cluster.shutdown() - def setUp(self): - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest( - "Native protocol 4,0+ is required for client warnings, currently using %r" - % (PROTOCOL_VERSION,)) - def test_warning_basic(self): """ Test to validate that client warnings can be surfaced diff --git a/tests/integration/standard/test_cluster.py b/tests/integration/standard/test_cluster.py index 1208edb9d2..f02b48008c 100644 --- a/tests/integration/standard/test_cluster.py +++ b/tests/integration/standard/test_cluster.py @@ -260,27 +260,9 @@ def test_protocol_negotiation(self): if CASSANDRA_VERSION >= Version('4.0-beta5'): assert updated_protocol_version == cassandra.ProtocolVersion.V5 assert updated_cluster_version == cassandra.ProtocolVersion.V5 - elif CASSANDRA_VERSION >= Version('4.0-a'): - assert updated_protocol_version == cassandra.ProtocolVersion.V4 - assert updated_cluster_version == cassandra.ProtocolVersion.V4 - elif CASSANDRA_VERSION >= Version('3.11'): - assert updated_protocol_version == cassandra.ProtocolVersion.V4 - assert updated_cluster_version == cassandra.ProtocolVersion.V4 - elif CASSANDRA_VERSION >= Version('3.0'): + else: assert updated_protocol_version == cassandra.ProtocolVersion.V4 assert updated_cluster_version == cassandra.ProtocolVersion.V4 - elif CASSANDRA_VERSION >= Version('2.2'): - assert updated_protocol_version == 4 - assert updated_cluster_version == 4 - elif CASSANDRA_VERSION >= Version('2.1'): - assert updated_protocol_version == 3 - assert updated_cluster_version == 3 - elif CASSANDRA_VERSION >= Version('2.0'): - assert updated_protocol_version == 2 - assert updated_cluster_version == 2 - else: - assert updated_protocol_version == 1 - assert updated_cluster_version == 1 cluster.shutdown() @@ -376,19 +358,19 @@ def test_auth_provider_is_callable(self): Ensure that auth_providers are always callable """ with pytest.raises(TypeError): - Cluster(auth_provider=1, protocol_version=1) - c = TestCluster(protocol_version=1) + Cluster(auth_provider=1, protocol_version=4) + c = TestCluster(protocol_version=4) with pytest.raises(TypeError): setattr(c, 'auth_provider', 1) - def test_v2_auth_provider(self): + def test_auth_provider(self): """ - Check for v2 auth_provider compliance + Check for auth_provider compliance """ bad_auth_provider = lambda x: {'username': 'foo', 'password': 'bar'} with pytest.raises(TypeError): - Cluster(auth_provider=bad_auth_provider, protocol_version=2) - c = TestCluster(protocol_version=2) + Cluster(auth_provider=bad_auth_provider, protocol_version=4) + c = TestCluster(protocol_version=4) with pytest.raises(TypeError): setattr(c, 'auth_provider', bad_auth_provider) @@ -462,10 +444,6 @@ def test_refresh_schema_type(self): if get_server_versions()[0] < (2, 1, 0): raise unittest.SkipTest('UDTs were introduced in Cassandra 2.1') - if PROTOCOL_VERSION < 3: - raise unittest.SkipTest('UDTs are not specified in change events for protocol v2') - # We may want to refresh types on keyspace change events in that case(?) - cluster = TestCluster() session = cluster.connect() @@ -1093,21 +1071,21 @@ def test_stale_connections_after_shutdown(self): Originates from https://github.com/scylladb/python-driver/issues/120 """ for _ in range(10): - with TestCluster(protocol_version=3) as cluster: + with TestCluster() as cluster: cluster.connect().execute("SELECT * FROM system_schema.keyspaces") time.sleep(1) - with TestCluster(protocol_version=3) as cluster: + with TestCluster() as cluster: session = cluster.connect() for _ in range(5): session.execute("SELECT * FROM system_schema.keyspaces") for _ in range(10): - with TestCluster(protocol_version=3) as cluster: + with TestCluster() as cluster: cluster.connect().execute("SELECT * FROM system_schema.keyspaces") for _ in range(10): - with TestCluster(protocol_version=3) as cluster: + with TestCluster() as cluster: cluster.connect() result = subprocess.run(["lsof -nP | awk '$3 ~ \":9042\" {print $0}' | grep ''"], shell=True, capture_output=True) diff --git a/tests/integration/standard/test_concurrent.py b/tests/integration/standard/test_concurrent.py index 5e6b1ffd59..5d464b9b23 100644 --- a/tests/integration/standard/test_concurrent.py +++ b/tests/integration/standard/test_concurrent.py @@ -22,7 +22,7 @@ from cassandra.policies import HostDistance from cassandra.query import dict_factory, tuple_factory, SimpleStatement -from tests.integration import use_singledc, PROTOCOL_VERSION, TestCluster +from tests.integration import use_singledc, TestCluster import unittest import pytest @@ -178,11 +178,6 @@ def test_execute_concurrent_with_args_generator(self): next(results) def test_execute_concurrent_paged_result(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2+ is required for Paging, currently testing against %r" - % (PROTOCOL_VERSION,)) - num_statements = 201 statement = SimpleStatement( "INSERT INTO test3rf.test (k, v) VALUES (%s, %s)", @@ -221,11 +216,6 @@ def test_execute_concurrent_paged_result_generator(self): @test_category paging """ - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2+ is required for Paging, currently testing against %r" - % (PROTOCOL_VERSION,)) - num_statements = 201 statement = SimpleStatement( "INSERT INTO test3rf.test (k, v) VALUES (%s, %s)", diff --git a/tests/integration/standard/test_connection.py b/tests/integration/standard/test_connection.py index 630e5e6ba0..a21feb5db8 100644 --- a/tests/integration/standard/test_connection.py +++ b/tests/integration/standard/test_connection.py @@ -31,7 +31,7 @@ from tests import is_monkey_patched from tests.integration import use_singledc, get_node, CASSANDRA_IP, local, \ - requiresmallclockgranularity, greaterthancass20, TestCluster + requiresmallclockgranularity, TestCluster try: import cassandra.io.asyncorereactor @@ -125,7 +125,6 @@ def tearDown(self): self.cluster.shutdown() @local - @greaterthancass20 def test_heart_beat_timeout(self): # Setup a host listener to ensure the nodes don't go down test_listener = TestHostListener() diff --git a/tests/integration/standard/test_control_connection.py b/tests/integration/standard/test_control_connection.py index 2788a1d837..52d3f08cc4 100644 --- a/tests/integration/standard/test_control_connection.py +++ b/tests/integration/standard/test_control_connection.py @@ -23,7 +23,7 @@ from cassandra.protocol import ConfigurationException -from tests.integration import use_singledc, PROTOCOL_VERSION, TestCluster, greaterthanorequalcass40, \ +from tests.integration import use_singledc, TestCluster, greaterthanorequalcass40, \ xfail_scylla_version_lt from tests.integration.datatype_utils import update_datatypes @@ -35,10 +35,6 @@ def setup_module(): class ControlConnectionTests(unittest.TestCase): def setUp(self): - if PROTOCOL_VERSION < 3: - raise unittest.SkipTest( - "Native protocol 3,0+ is required for UDTs using %r" - % (PROTOCOL_VERSION,)) self.cluster = TestCluster() def tearDown(self): diff --git a/tests/integration/standard/test_custom_payload.py b/tests/integration/standard/test_custom_payload.py index fc58081070..2179c4225d 100644 --- a/tests/integration/standard/test_custom_payload.py +++ b/tests/integration/standard/test_custom_payload.py @@ -17,7 +17,7 @@ from cassandra.query import (SimpleStatement, BatchStatement, BatchType) -from tests.integration import (use_singledc, PROTOCOL_VERSION, local, TestCluster, +from tests.integration import (use_singledc, local, TestCluster, requires_custom_payload) import pytest diff --git a/tests/integration/standard/test_custom_protocol_handler.py b/tests/integration/standard/test_custom_protocol_handler.py index 239f7e7336..1273f834ad 100644 --- a/tests/integration/standard/test_custom_protocol_handler.py +++ b/tests/integration/standard/test_custom_protocol_handler.py @@ -203,7 +203,7 @@ class CustomResultMessageRaw(ResultMessage): my_type_codes[0xc] = UUIDType type_codes = my_type_codes - def recv_results_rows(self, f, protocol_version, user_type_map, result_metadata, column_encryption_policy): + def recv_results_rows(self, f, user_type_map, result_metadata, column_encryption_policy): self.recv_results_metadata(f, user_type_map) column_metadata = self.column_metadata or result_metadata rowcount = read_int(f) @@ -232,7 +232,7 @@ class CustomResultMessageTracked(ResultMessage): type_codes = my_type_codes checked_rev_row_set = set() - def recv_results_rows(self, f, protocol_version, user_type_map, result_metadata, column_encryption_policy): + def recv_results_rows(self, f, user_type_map, result_metadata, column_encryption_policy): self.recv_results_metadata(f, user_type_map) column_metadata = self.column_metadata or result_metadata rowcount = read_int(f) @@ -241,7 +241,7 @@ def recv_results_rows(self, f, protocol_version, user_type_map, result_metadata, self.column_types = [c[3] for c in column_metadata] self.checked_rev_row_set.update(self.column_types) self.parsed_rows = [ - tuple(ctype.from_binary(val, protocol_version) + tuple(ctype.from_binary(val) for ctype, val in zip(self.column_types, row)) for row in rows] diff --git a/tests/integration/standard/test_cython_protocol_handlers.py b/tests/integration/standard/test_cython_protocol_handlers.py index f44d613c64..6033b84ad9 100644 --- a/tests/integration/standard/test_cython_protocol_handlers.py +++ b/tests/integration/standard/test_cython_protocol_handlers.py @@ -12,8 +12,8 @@ from cassandra.protocol import ProtocolHandler, LazyProtocolHandler, NumpyProtocolHandler from cassandra.query import tuple_factory from tests import VERIFY_CYTHON -from tests.integration import use_singledc, notprotocolv1, \ - drop_keyspace_shutdown_cluster, BasicSharedKeyspaceUnitTestCase, greaterthancass21, TestCluster +from tests.integration import use_singledc, \ + drop_keyspace_shutdown_cluster, BasicSharedKeyspaceUnitTestCase, TestCluster from tests.integration.datatype_utils import update_datatypes from tests.integration.standard.utils import ( create_table_with_all_types, get_all_primitive_params, get_primitive_datatypes) @@ -78,7 +78,6 @@ def test_cython_lazy_results_paged(self): cluster.shutdown() - @notprotocolv1 @numpytest def test_numpy_parser(self): """ @@ -89,7 +88,6 @@ def test_numpy_parser(self): assert not result.has_more_pages self._verify_numpy_page(result[0]) - @notprotocolv1 @numpytest def test_numpy_results_paged(self): """ @@ -251,7 +249,6 @@ def setUpClass(cls): def tearDownClass(cls): drop_keyspace_shutdown_cluster("test_wide_table", cls.session, cls.cluster) - @notprotocolv1 @numpytest def test_numpy_wide_table_paging(self): """ @@ -287,7 +284,6 @@ def test_numpy_wide_table_paging(self): cluster.shutdown() - @notprotocolv1 @numpytest def test_numpy_wide_table_no_fetch_size(self): """ @@ -328,7 +324,6 @@ def setUpClass(cls): cls.common_setup(1, execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(row_factory=tuple_factory)}) @numpytest - @greaterthancass21 def test_null_types(self): """ Test to validate that the numpy protocol handler can deal with null values. diff --git a/tests/integration/standard/test_metadata.py b/tests/integration/standard/test_metadata.py index c30e369d83..b5f98792f4 100644 --- a/tests/integration/standard/test_metadata.py +++ b/tests/integration/standard/test_metadata.py @@ -36,12 +36,12 @@ from cassandra.protocol import QueryMessage, ProtocolHandler from cassandra.util import SortedSet -from tests.integration import (get_cluster, use_singledc, PROTOCOL_VERSION, execute_until_pass, +from tests.integration import (get_cluster, use_singledc, execute_until_pass, BasicSegregatedKeyspaceUnitTestCase, BasicSharedKeyspaceUnitTestCase, BasicExistingKeyspaceUnitTestCase, drop_keyspace_shutdown_cluster, CASSANDRA_VERSION, - greaterthanorequalcass30, lessthancass30, local, - get_supported_protocol_versions, greaterthancass20, - greaterthancass21, greaterthanorequalcass40, + greaterthanorequalcass30, local, + get_supported_protocol_versions, + greaterthanorequalcass40, lessthancass40, TestCluster, requires_java_udf, requires_composite_type, requires_collection_indexes, SCYLLA_VERSION, xfail_scylla, xfail_scylla_version_lt, @@ -385,28 +385,6 @@ def test_composite_in_compound_primary_key_compact(self): self.check_create_statement(tablemeta, create_statement) - @lessthancass30 - def test_cql_compatibility(self): - - # having more than one non-PK column is okay if there aren't any - # clustering columns - create_statement = self.make_create_statement(["a"], [], ["b", "c", "d"]) - self.session.execute(create_statement) - tablemeta = self.get_table_metadata() - - assert [u'a'] == [c.name for c in tablemeta.partition_key] - assert [] == tablemeta.clustering_key - assert [u'a', u'b', u'c', u'd'] == sorted(tablemeta.columns.keys()) - - assert tablemeta.is_cql_compatible - - # It will be cql compatible after CASSANDRA-10857 - # since compact storage is being dropped - tablemeta.clustering_key = ["foo", "bar"] - tablemeta.columns["foo"] = None - tablemeta.columns["bar"] = None - assert tablemeta.is_cql_compatible - def test_compound_primary_keys_ordering(self): create_statement = self.make_create_statement(["a"], ["b"], ["c"]) create_statement += " WITH CLUSTERING ORDER BY (b DESC)" @@ -508,7 +486,6 @@ def test_indexes(self): assert 'CREATE INDEX d_index' in statement assert 'CREATE INDEX e_index' in statement - @greaterthancass21 @requires_collection_indexes @xfail_scylla('scylladb/scylladb#22013 - scylla does not show full index in system_schema.indexes') def test_collection_indexes(self): @@ -529,16 +506,15 @@ def test_collection_indexes(self): target = ' (b)' if CASSANDRA_VERSION < Version("3.0") else 'values(b))' # explicit values in C* 3+ assert target in tablemeta.export_as_string() - # test full indexes on frozen collections, if available - if CASSANDRA_VERSION >= Version("2.1.3"): - self.session.execute("DROP TABLE %s.%s" % (self.keyspace_name, self.function_table_name)) - self.session.execute("CREATE TABLE %s.%s (a int PRIMARY KEY, b frozen>)" - % (self.keyspace_name, self.function_table_name)) - self.session.execute("CREATE INDEX index3 ON %s.%s (full(b))" - % (self.keyspace_name, self.function_table_name)) + # test full indexes on frozen collections + self.session.execute("DROP TABLE %s.%s" % (self.keyspace_name, self.function_table_name)) + self.session.execute("CREATE TABLE %s.%s (a int PRIMARY KEY, b frozen>)" + % (self.keyspace_name, self.function_table_name)) + self.session.execute("CREATE INDEX index3 ON %s.%s (full(b))" + % (self.keyspace_name, self.function_table_name)) - tablemeta = self.get_table_metadata() - assert '(full(b))' in tablemeta.export_as_string() + tablemeta = self.get_table_metadata() + assert '(full(b))' in tablemeta.export_as_string() def test_compression_disabled(self): create_statement = self.make_create_statement(["a"], ["b"], ["c"]) @@ -623,34 +599,32 @@ def test_refresh_schema_metadata(self): cluster2.refresh_schema_metadata() assert "c" in cluster2.metadata.keyspaces[self.keyspace_name].tables[table_name].columns - if PROTOCOL_VERSION >= 3: - # UDT metadata modification - self.session.execute("CREATE TYPE {0}.user (age int, name text)".format(self.keyspace_name)) - assert cluster2.metadata.keyspaces[self.keyspace_name].user_types == {} - cluster2.refresh_schema_metadata() - assert "user" in cluster2.metadata.keyspaces[self.keyspace_name].user_types + # UDT metadata modification + self.session.execute("CREATE TYPE {0}.user (age int, name text)".format(self.keyspace_name)) + assert cluster2.metadata.keyspaces[self.keyspace_name].user_types == {} + cluster2.refresh_schema_metadata() + assert "user" in cluster2.metadata.keyspaces[self.keyspace_name].user_types - if PROTOCOL_VERSION >= 4: - # UDF metadata modification - self.session.execute("""CREATE FUNCTION {0}.sum_int(key int, val int) - RETURNS NULL ON NULL INPUT - RETURNS int - LANGUAGE java AS 'return key+val;';""".format(self.keyspace_name)) + # UDF metadata modification + self.session.execute("""CREATE FUNCTION {0}.sum_int(key int, val int) + RETURNS NULL ON NULL INPUT + RETURNS int + LANGUAGE java AS 'return key+val;';""".format(self.keyspace_name)) - assert cluster2.metadata.keyspaces[self.keyspace_name].functions == {} - cluster2.refresh_schema_metadata() - assert "sum_int(int,int)" in cluster2.metadata.keyspaces[self.keyspace_name].functions + assert cluster2.metadata.keyspaces[self.keyspace_name].functions == {} + cluster2.refresh_schema_metadata() + assert "sum_int(int,int)" in cluster2.metadata.keyspaces[self.keyspace_name].functions - # UDA metadata modification - self.session.execute("""CREATE AGGREGATE {0}.sum_agg(int) - SFUNC sum_int - STYPE int - INITCOND 0""" - .format(self.keyspace_name)) + # UDA metadata modification + self.session.execute("""CREATE AGGREGATE {0}.sum_agg(int) + SFUNC sum_int + STYPE int + INITCOND 0""" + .format(self.keyspace_name)) - assert cluster2.metadata.keyspaces[self.keyspace_name].aggregates == {} - cluster2.refresh_schema_metadata() - assert "sum_agg(int)" in cluster2.metadata.keyspaces[self.keyspace_name].aggregates + assert cluster2.metadata.keyspaces[self.keyspace_name].aggregates == {} + cluster2.refresh_schema_metadata() + assert "sum_agg(int)" in cluster2.metadata.keyspaces[self.keyspace_name].aggregates # Cluster metadata modification self.session.execute("DROP KEYSPACE new_keyspace") @@ -799,9 +773,6 @@ def test_refresh_user_type_metadata(self): @test_category metadata """ - if PROTOCOL_VERSION < 3: - raise unittest.SkipTest("Protocol 3+ is required for UDTs, currently testing against {0}".format(PROTOCOL_VERSION)) - cluster2 = TestCluster(schema_event_refresh_window=-1) cluster2.connect() @@ -814,41 +785,6 @@ def test_refresh_user_type_metadata(self): cluster2.shutdown() - @greaterthancass20 - def test_refresh_user_type_metadata_proto_2(self): - """ - Test to insure that protocol v1/v2 surface UDT metadata changes - - @since 3.7.0 - @jira_ticket PYTHON-106 - @expected_result UDT metadata in the keyspace should be updated regardless of protocol version - - @test_category metadata - """ - supported_versions = get_supported_protocol_versions() - if 2 not in supported_versions: # 1 and 2 were dropped in the same version - raise unittest.SkipTest("Protocol versions 1 and 2 are not supported in Cassandra version ".format(CASSANDRA_VERSION)) - - for protocol_version in (1, 2): - cluster = TestCluster() - session = cluster.connect() - assert cluster.metadata.keyspaces[self.keyspace_name].user_types == {} - - session.execute("CREATE TYPE {0}.user (age int, name text)".format(self.keyspace_name)) - assert "user" in cluster.metadata.keyspaces[self.keyspace_name].user_types - assert "age" in cluster.metadata.keyspaces[self.keyspace_name].user_types["user"].field_names - assert "name" in cluster.metadata.keyspaces[self.keyspace_name].user_types["user"].field_names - - session.execute("ALTER TYPE {0}.user ADD flag boolean".format(self.keyspace_name)) - assert "flag" in cluster.metadata.keyspaces[self.keyspace_name].user_types["user"].field_names - - session.execute("ALTER TYPE {0}.user RENAME flag TO something".format(self.keyspace_name)) - assert "something" in cluster.metadata.keyspaces[self.keyspace_name].user_types["user"].field_names - - session.execute("DROP TYPE {0}.user".format(self.keyspace_name)) - assert cluster.metadata.keyspaces[self.keyspace_name].user_types == {} - cluster.shutdown() - @requires_java_udf def test_refresh_user_function_metadata(self): """ @@ -868,9 +804,6 @@ def test_refresh_user_function_metadata(self): @test_category metadata """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol 4+ is required for UDFs, currently testing against {0}".format(PROTOCOL_VERSION)) - cluster2 = TestCluster(schema_event_refresh_window=-1) cluster2.connect() @@ -905,9 +838,6 @@ def test_refresh_user_aggregate_metadata(self): @test_category metadata """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Protocol 4+ is required for UDAs, currently testing against {0}".format(PROTOCOL_VERSION)) - cluster2 = TestCluster(schema_event_refresh_window=-1) cluster2.connect() @@ -1119,17 +1049,11 @@ def test_export_keyspace_schema(self): assert isinstance(keyspace_metadata.as_cql_query(), str) cluster.shutdown() - @greaterthancass20 def test_export_keyspace_schema_udts(self): """ Test udt exports """ - if PROTOCOL_VERSION < 3: - raise unittest.SkipTest( - "Protocol 3.0+ is required for UDT change events, currently testing against %r" - % (PROTOCOL_VERSION,)) - if sys.version_info[0:2] != (2, 7): raise unittest.SkipTest('This test compares static strings generated from dict items, which may change orders. Test with 2.7.') @@ -1195,7 +1119,6 @@ def test_export_keyspace_schema_udts(self): cluster.shutdown() - @greaterthancass21 @xfail_scylla_version_lt(reason='scylladb/scylladb#10707 - Column name in CREATE INDEX is not quoted', oss_scylla_version="5.2", ent_scylla_version="2023.1.1") def test_case_sensitivity(self): @@ -1522,34 +1445,24 @@ class FunctionTest(unittest.TestCase): Base functionality for Function and Aggregate metadata test classes """ - def setUp(self): - """ - Tests are skipped if run with native protocol version < 4 - """ - - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Function metadata requires native protocol version 4+") - @property def function_name(self): return self._testMethodName.lower() @classmethod def setup_class(cls): - if PROTOCOL_VERSION >= 4: - cls.cluster = TestCluster() - cls.keyspace_name = cls.__name__.lower() - cls.session = cls.cluster.connect() - cls.session.execute("CREATE KEYSPACE IF NOT EXISTS %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}" % cls.keyspace_name) - cls.session.set_keyspace(cls.keyspace_name) - cls.keyspace_function_meta = cls.cluster.metadata.keyspaces[cls.keyspace_name].functions - cls.keyspace_aggregate_meta = cls.cluster.metadata.keyspaces[cls.keyspace_name].aggregates + cls.cluster = TestCluster() + cls.keyspace_name = cls.__name__.lower() + cls.session = cls.cluster.connect() + cls.session.execute("CREATE KEYSPACE IF NOT EXISTS %s WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}" % cls.keyspace_name) + cls.session.set_keyspace(cls.keyspace_name) + cls.keyspace_function_meta = cls.cluster.metadata.keyspaces[cls.keyspace_name].functions + cls.keyspace_aggregate_meta = cls.cluster.metadata.keyspaces[cls.keyspace_name].aggregates @classmethod def teardown_class(cls): - if PROTOCOL_VERSION >= 4: - cls.session.execute("DROP KEYSPACE IF EXISTS %s" % cls.keyspace_name) - cls.cluster.shutdown() + cls.session.execute("DROP KEYSPACE IF EXISTS %s" % cls.keyspace_name) + cls.cluster.shutdown() class Verified(object): @@ -1749,34 +1662,33 @@ class AggregateMetadata(FunctionTest): @classmethod def setup_class(cls): - if PROTOCOL_VERSION >= 4: - super(AggregateMetadata, cls).setup_class() - - cls.session.execute("""CREATE OR REPLACE FUNCTION sum_int(s int, i int) - RETURNS NULL ON NULL INPUT - RETURNS int - LANGUAGE java AS 'return s + i;';""") - cls.session.execute("""CREATE OR REPLACE FUNCTION sum_int_two(s int, i int, j int) - RETURNS NULL ON NULL INPUT - RETURNS int - LANGUAGE java AS 'return s + i + j;';""") - cls.session.execute("""CREATE OR REPLACE FUNCTION "List_As_String"(l list) - RETURNS NULL ON NULL INPUT - RETURNS int - LANGUAGE java AS 'return l.size();';""") - cls.session.execute("""CREATE OR REPLACE FUNCTION extend_list(s list, i int) - CALLED ON NULL INPUT - RETURNS list - LANGUAGE java AS 'if (i != null) s.add(i.toString()); return s;';""") - cls.session.execute("""CREATE OR REPLACE FUNCTION update_map(s map, i int) - RETURNS NULL ON NULL INPUT - RETURNS map - LANGUAGE java AS 's.put(new Integer(i), new Integer(i)); return s;';""") - cls.session.execute("""CREATE TABLE IF NOT EXISTS t - (k int PRIMARY KEY, v int)""") - for x in range(4): - cls.session.execute("INSERT INTO t (k,v) VALUES (%s, %s)", (x, x)) - cls.session.execute("INSERT INTO t (k) VALUES (%s)", (4,)) + super(AggregateMetadata, cls).setup_class() + + cls.session.execute("""CREATE OR REPLACE FUNCTION sum_int(s int, i int) + RETURNS NULL ON NULL INPUT + RETURNS int + LANGUAGE java AS 'return s + i;';""") + cls.session.execute("""CREATE OR REPLACE FUNCTION sum_int_two(s int, i int, j int) + RETURNS NULL ON NULL INPUT + RETURNS int + LANGUAGE java AS 'return s + i + j;';""") + cls.session.execute("""CREATE OR REPLACE FUNCTION "List_As_String"(l list) + RETURNS NULL ON NULL INPUT + RETURNS int + LANGUAGE java AS 'return l.size();';""") + cls.session.execute("""CREATE OR REPLACE FUNCTION extend_list(s list, i int) + CALLED ON NULL INPUT + RETURNS list + LANGUAGE java AS 'if (i != null) s.add(i.toString()); return s;';""") + cls.session.execute("""CREATE OR REPLACE FUNCTION update_map(s map, i int) + RETURNS NULL ON NULL INPUT + RETURNS map + LANGUAGE java AS 's.put(new Integer(i), new Integer(i)); return s;';""") + cls.session.execute("""CREATE TABLE IF NOT EXISTS t + (k int PRIMARY KEY, v int)""") + for x in range(4): + cls.session.execute("INSERT INTO t (k,v) VALUES (%s, %s)", (x, x)) + cls.session.execute("INSERT INTO t (k) VALUES (%s)", (4,)) def make_aggregate_kwargs(self, state_func, state_type, final_func=None, init_cond=None): return {'keyspace': self.keyspace_name, @@ -1821,7 +1733,7 @@ def test_init_cond(self): """ # This is required until the java driver bundled with C* is updated to support v4 - c = TestCluster(protocol_version=3) + c = TestCluster() s = c.connect(self.keyspace_name) encoder = Encoder() @@ -2048,7 +1960,6 @@ def test_bad_index(self): assert m._exc_info[0] is self.BadMetaException assert "/*\nWarning:" in m.export_as_string() - @greaterthancass20 def test_bad_user_type(self): self.session.execute('CREATE TYPE %s (i int, d double)' % self.function_name) with patch.object(self.parser_class, '_build_user_type', side_effect=self.BadMetaException): @@ -2057,7 +1968,6 @@ def test_bad_user_type(self): assert m._exc_info[0] is self.BadMetaException assert "/*\nWarning:" in m.export_as_string() - @greaterthancass21 @requires_java_udf def test_bad_user_function(self): self.session.execute("""CREATE FUNCTION IF NOT EXISTS %s (key int, val int) @@ -2076,7 +1986,6 @@ def test_bad_user_function(self): assert m._exc_info[0] is self.BadMetaException assert "/*\nWarning:" in m.export_as_string() - @greaterthancass21 @requires_java_udf def test_bad_user_aggregate(self): self.session.execute("""CREATE FUNCTION IF NOT EXISTS sum_int (key int, val int) @@ -2390,59 +2299,6 @@ def test_base_table_column_addition_mv(self): mv_alltime_fouls_comumn = self.cluster.metadata.keyspaces[self.keyspace_name].views["alltimehigh"].columns['fouls'] assert mv_alltime_fouls_comumn.cql_type == 'int' - @lessthancass30 - def test_base_table_type_alter_mv(self): - """ - test to ensure that materialized view metadata is properly updated when a type in the base table - is updated. - - test_create_view_metadata tests that materialized views metadata is properly updated when the type of base table - column is changed. - - Support for alter type was removed in CASSANDRA-12443 - - @since 3.0.0 - @jira_ticket CASSANDRA-10424 - @expected_result Materialized view metadata should be updated correctly - - @test_category metadata - """ - create_table = """CREATE TABLE {0}.scores( - user TEXT, - game TEXT, - year INT, - month INT, - day INT, - score TEXT, - PRIMARY KEY (user, game, year, month, day) - )""".format(self.keyspace_name) - - self.session.execute(create_table) - - create_mv = """CREATE MATERIALIZED VIEW {0}.monthlyhigh AS - SELECT game, year, month, score, user, day FROM {0}.scores - WHERE game IS NOT NULL AND year IS NOT NULL AND month IS NOT NULL AND score IS NOT NULL AND user IS NOT NULL AND day IS NOT NULL - PRIMARY KEY ((game, year, month), score, user, day) - WITH CLUSTERING ORDER BY (score DESC, user ASC, day ASC)""".format(self.keyspace_name) - - self.session.execute(create_mv) - assert len(self.cluster.metadata.keyspaces[self.keyspace_name].views) == 1 - alter_scores = """ALTER TABLE {0}.scores ALTER score TYPE blob""".format((self.keyspace_name)) - self.session.execute(alter_scores) - assert len(self.cluster.metadata.keyspaces[self.keyspace_name].views) == 1 - - score_column = self.cluster.metadata.keyspaces[self.keyspace_name].tables['scores'].columns['score'] - assert score_column.cql_type == 'blob' - - # until CASSANDRA-9920+CASSANDRA-10500 MV updates are only available later with an async event - for i in range(10): - score_mv_column = self.cluster.metadata.keyspaces[self.keyspace_name].views["monthlyhigh"].columns['score'] - if "blob" == score_mv_column.cql_type: - break - time.sleep(.2) - - assert score_mv_column.cql_type == 'blob' - def test_metadata_with_quoted_identifiers(self): """ test to ensure that materialized view metadata is properly constructed when quoted identifiers are used diff --git a/tests/integration/standard/test_prepared_statements.py b/tests/integration/standard/test_prepared_statements.py index 3f63b881ef..c825b1c6bc 100644 --- a/tests/integration/standard/test_prepared_statements.py +++ b/tests/integration/standard/test_prepared_statements.py @@ -199,23 +199,14 @@ def test_imprecise_bind_values_dicts(self): prepared.bind({'k': 1, 'v': 2, 'v2': 3}) # right number, but one does not belong - if PROTOCOL_VERSION < 4: - # pre v4, the driver bails with key error when 'v' is found missing - with pytest.raises(KeyError): - prepared.bind({'k': 1, 'v2': 3}) - else: - # post v4, the driver uses UNSET_VALUE for 'v' and 'v2' is ignored - prepared.bind({'k': 1, 'v2': 3}) + # the driver uses UNSET_VALUE for 'v' and 'v2' is ignored + prepared.bind({'k': 1, 'v2': 3}) # also catch too few variables with dicts assert isinstance(prepared, PreparedStatement) - if PROTOCOL_VERSION < 4: - with pytest.raises(KeyError): - prepared.bind({}) - else: - # post v4, the driver attempts to use UNSET_VALUE for unspecified keys - with pytest.raises(ValueError): - prepared.bind({}) + # the driver attempts to use UNSET_VALUE for unspecified keys + with pytest.raises(ValueError): + prepared.bind({}) def test_none_values(self): """ @@ -255,8 +246,6 @@ def test_unset_values(self): @test_category prepared_statements:binding """ - if PROTOCOL_VERSION < 4: - raise unittest.SkipTest("Binding UNSET values is not supported in protocol version < 4") # table with at least two values so one can be used as a marker self.session.execute("CREATE TABLE IF NOT EXISTS test1rf.test_unset_values (k int PRIMARY KEY, v0 int, v1 int)") diff --git a/tests/integration/standard/test_query.py b/tests/integration/standard/test_query.py index 9cebc22b05..acf32f4a31 100644 --- a/tests/integration/standard/test_query.py +++ b/tests/integration/standard/test_query.py @@ -24,8 +24,8 @@ BatchStatement, BatchType, dict_factory, TraceUnavailable) from cassandra.cluster import NoHostAvailable, ExecutionProfile, EXEC_PROFILE_DEFAULT, Cluster from cassandra.policies import HostDistance, RoundRobinPolicy, WhiteListRoundRobinPolicy -from tests.integration import use_singledc, PROTOCOL_VERSION, BasicSharedKeyspaceUnitTestCase, \ - greaterthanprotocolv3, MockLoggingHandler, get_supported_protocol_versions, local, get_cluster, setup_keyspace, \ +from tests.integration import use_singledc, BasicSharedKeyspaceUnitTestCase, \ + MockLoggingHandler, get_supported_protocol_versions, local, get_cluster, setup_keyspace, \ USE_CASS_EXTERNAL, greaterthanorequalcass40, TestCluster, xfail_scylla from tests import notwindows from tests.integration import greaterthanorequalcass30, get_node @@ -136,7 +136,6 @@ def test_trace_ignores_row_factory(self): str(event) @local - @greaterthanprotocolv3 def test_client_ip_in_trace(self): """ Test to validate that client trace contains client ip information. @@ -492,10 +491,7 @@ def test_prepared_metadata_generation(self): session = cluster.connect() select_statement = session.prepare("SELECT * FROM system.local WHERE key='local'") - if proto_version == 1: - assert select_statement.result_metadata == None - else: - assert select_statement.result_metadata != None + assert select_statement.result_metadata != None future = session.execute_async(select_statement) results = future.result() if base_line is None: @@ -659,11 +655,6 @@ def test_prepared_statement(self): class BatchStatementTests(BasicSharedKeyspaceUnitTestCase): def setUp(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2.0+ is required for BATCH operations, currently testing against %r" - % (PROTOCOL_VERSION,)) - self.cluster = TestCluster() self.session = self.cluster.connect(wait_for_all_pools=True) @@ -793,11 +784,6 @@ def test_too_many_statements(self): class SerialConsistencyTests(unittest.TestCase): def setUp(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2.0+ is required for Serial Consistency, currently testing against %r" - % (PROTOCOL_VERSION,)) - self.cluster = TestCluster() self.session = self.cluster.connect() @@ -880,15 +866,6 @@ def test_bad_consistency_level(self): class LightweightTransactionTests(unittest.TestCase): def setUp(self): - """ - Test is skipped if run with cql version < 2 - - """ - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2.0+ is required for Lightweight transactions, currently testing against %r" - % (PROTOCOL_VERSION,)) - serial_profile = ExecutionProfile(consistency_level=ConsistencyLevel.SERIAL) self.cluster = TestCluster(execution_profiles={'serial': serial_profile}) self.session = self.cluster.connect() @@ -1072,10 +1049,6 @@ class BatchStatementDefaultRoutingKeyTests(unittest.TestCase): # Test for PYTHON-126: BatchStatement.add() should set the routing key of the first added prepared statement def setUp(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2.0+ is required for BATCH operations, currently testing against %r" - % (PROTOCOL_VERSION,)) self.cluster = TestCluster() self.session = self.cluster.connect() query = """ diff --git a/tests/integration/standard/test_query_paging.py b/tests/integration/standard/test_query_paging.py index e0c67cd309..6694c0c284 100644 --- a/tests/integration/standard/test_query_paging.py +++ b/tests/integration/standard/test_query_paging.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from tests.integration import use_singledc, PROTOCOL_VERSION, TestCluster +from tests.integration import use_singledc, TestCluster import logging log = logging.getLogger(__name__) @@ -38,11 +38,6 @@ def setup_module(): class QueryPagingTests(unittest.TestCase): def setUp(self): - if PROTOCOL_VERSION < 2: - raise unittest.SkipTest( - "Protocol 2.0+ is required for Paging state, currently testing against %r" - % (PROTOCOL_VERSION,)) - self.cluster = TestCluster( execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(consistency_level=ConsistencyLevel.LOCAL_QUORUM)} ) diff --git a/tests/integration/standard/test_row_factories.py b/tests/integration/standard/test_row_factories.py index 187f35704a..198b518d2c 100644 --- a/tests/integration/standard/test_row_factories.py +++ b/tests/integration/standard/test_row_factories.py @@ -201,9 +201,6 @@ def test_can_select_using_alias(self): """ can SELECT "" AS aliases """ - if self._cass_version < (2, 0, 0): - raise unittest.SkipTest("Alias in SELECT not supported before 2.0") - try: self.session.execute('SELECT key, "626972746864617465" AS my_col from test1rf.table_num_col') except ValueError as e: diff --git a/tests/integration/standard/test_single_interface.py b/tests/integration/standard/test_single_interface.py index 5fd9ef45d3..22776f4232 100644 --- a/tests/integration/standard/test_single_interface.py +++ b/tests/integration/standard/test_single_interface.py @@ -19,7 +19,7 @@ from cassandra.query import SimpleStatement from packaging.version import Version -from tests.integration import use_singledc, PROTOCOL_VERSION, \ +from tests.integration import use_singledc, \ remove_cluster, greaterthanorequalcass40, \ CASSANDRA_VERSION, TestCluster, DEFAULT_SINGLE_INTERFACE_PORT diff --git a/tests/integration/standard/test_types.py b/tests/integration/standard/test_types.py index ad69fbada9..bdcced3870 100644 --- a/tests/integration/standard/test_types.py +++ b/tests/integration/standard/test_types.py @@ -38,8 +38,8 @@ from tests.unit.cython.utils import cythontest from tests.util import assertEqual -from tests.integration import use_singledc, execute_until_pass, notprotocolv1, \ - BasicSharedKeyspaceUnitTestCase, greaterthancass21, lessthancass30, \ +from tests.integration import use_singledc, execute_until_pass, \ + BasicSharedKeyspaceUnitTestCase, \ greaterthanorequalcass3_10, TestCluster, requires_composite_type, greaterthanorequalcass50 from tests.integration.datatype_utils import update_datatypes, PRIMITIVE_DATATYPES, COLLECTION_TYPES, PRIMITIVE_DATATYPES_KEYS, \ get_sample, get_all_samples, get_collection_sample @@ -430,9 +430,6 @@ def test_can_insert_tuples(self): Basic test of tuple functionality """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - c = TestCluster() s = c.connect(self.keyspace_name) @@ -483,9 +480,6 @@ def test_can_insert_tuples_with_varying_lengths(self): as expected. """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - c = TestCluster( execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(row_factory=dict_factory)} ) @@ -523,9 +517,6 @@ def test_can_insert_tuples_all_primitive_datatypes(self): Ensure tuple subtypes are appropriately handled. """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - c = TestCluster() s = c.connect(self.keyspace_name) s.encoder.mapping[tuple] = s.encoder.cql_encode_tuple @@ -551,9 +542,6 @@ def test_can_insert_tuples_all_collection_datatypes(self): Ensure tuple subtypes are appropriately handled for maps, sets, and lists. """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - c = TestCluster( execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(row_factory=dict_factory)} ) @@ -650,9 +638,6 @@ def test_can_insert_nested_tuples(self): Ensure nested are appropriately handled. """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - c = TestCluster( execution_profiles={EXEC_PROFILE_DEFAULT: ExecutionProfile(row_factory=dict_factory)} ) @@ -690,9 +675,6 @@ def test_can_insert_tuples_with_nulls(self): Test tuples with null and empty string fields. """ - if self.cass_version < (2, 1, 0): - raise unittest.SkipTest("The tuple type was introduced in Cassandra 2.1") - s = self.session s.execute("CREATE TABLE tuples_nulls (k int PRIMARY KEY, t frozen>)") @@ -792,7 +774,6 @@ def test_can_read_composite_type(self): assert 0 == result.a assert ('abc',) == result.b - @notprotocolv1 def test_special_float_cql_encoding(self): """ Test to insure that Infinity -Infinity and NaN are supported by the python driver. @@ -905,85 +886,6 @@ def test_smoke_duration_values(self): self.session.execute(prepared, (1, Duration(int("8FFFFFFFFFFFFFF0", 16), 0, 0))) -class TypeTestsProtocol(BasicSharedKeyspaceUnitTestCase): - - @greaterthancass21 - @lessthancass30 - def test_nested_types_with_protocol_version(self): - """ - Test to validate that nested type serialization works on various protocol versions. Provided - the version of cassandra is greater the 2.1.3 we would expect to nested to types to work at all protocol versions. - - @since 3.0.0 - @jira_ticket PYTHON-215 - @expected_result no exceptions are thrown - - @test_category data_types serialization - """ - ddl = '''CREATE TABLE {0}.t ( - k int PRIMARY KEY, - v list>>)'''.format(self.keyspace_name) - - self.session.execute(ddl) - ddl = '''CREATE TABLE {0}.u ( - k int PRIMARY KEY, - v set>>)'''.format(self.keyspace_name) - self.session.execute(ddl) - ddl = '''CREATE TABLE {0}.v ( - k int PRIMARY KEY, - v map>, frozen>>, - v1 frozen>)'''.format(self.keyspace_name) - self.session.execute(ddl) - - self.session.execute("CREATE TYPE {0}.typ (v0 frozen>>>, v1 frozen>)".format(self.keyspace_name)) - - ddl = '''CREATE TABLE {0}.w ( - k int PRIMARY KEY, - v frozen)'''.format(self.keyspace_name) - - self.session.execute(ddl) - - for pvi in range(3, 5): - self.run_inserts_at_version(pvi) - for pvr in range(3, 5): - self.read_inserts_at_level(pvr) - - def read_inserts_at_level(self, proto_ver): - session = TestCluster(protocol_version=proto_ver).connect(self.keyspace_name) - try: - results = session.execute('select * from t').one() - assert "[SortedSet([1, 2]), SortedSet([3, 5])]" == str(results.v) - - results = session.execute('select * from u').one() - assert "SortedSet([[1, 2], [3, 5]])" == str(results.v) - - results = session.execute('select * from v').one() - assert "{SortedSet([1, 2]): [1, 2, 3], SortedSet([3, 5]): [4, 5, 6]}" == str(results.v) - - results = session.execute('select * from w').one() - assert "typ(v0=OrderedMapSerializedKey([(1, [1, 2, 3]), (2, [4, 5, 6])]), v1=[7, 8, 9])" == str(results.v) - - finally: - session.cluster.shutdown() - - def run_inserts_at_version(self, proto_ver): - session = TestCluster(protocol_version=proto_ver).connect(self.keyspace_name) - try: - p = session.prepare('insert into t (k, v) values (?, ?)') - session.execute(p, (0, [{1, 2}, {3, 5}])) - - p = session.prepare('insert into u (k, v) values (?, ?)') - session.execute(p, (0, {(1, 2), (3, 5)})) - - p = session.prepare('insert into v (k, v, v1) values (?, ?, ?)') - session.execute(p, (0, {(1, 2): [1, 2, 3], (3, 5): [4, 5, 6]}, (123, 'four'))) - - p = session.prepare('insert into w (k, v) values (?, ?)') - session.execute(p, (0, ({1: [1, 2, 3], 2: [4, 5, 6]}, [7, 8, 9]))) - - finally: - session.cluster.shutdown() - @greaterthanorequalcass50 class TypeTestsVector(BasicSharedKeyspaceUnitTestCase): diff --git a/tests/integration/standard/test_udts.py b/tests/integration/standard/test_udts.py index dd696ea0e9..769f6bcdc4 100644 --- a/tests/integration/standard/test_udts.py +++ b/tests/integration/standard/test_udts.py @@ -22,7 +22,7 @@ from cassandra.util import OrderedMap from tests.integration import use_singledc, execute_until_pass, \ - BasicSegregatedKeyspaceUnitTestCase, greaterthancass20, lessthancass30, greaterthanorequalcass36, TestCluster + BasicSegregatedKeyspaceUnitTestCase, greaterthanorequalcass36, TestCluster from tests.integration.datatype_utils import update_datatypes, PRIMITIVE_DATATYPES, PRIMITIVE_DATATYPES_KEYS, \ COLLECTION_TYPES, get_sample, get_collection_sample import pytest @@ -36,7 +36,6 @@ def setup_module(): update_datatypes() -@greaterthancass20 class UDTTests(BasicSegregatedKeyspaceUnitTestCase): @property @@ -608,9 +607,6 @@ def test_can_insert_nested_collections(self): Test for inserting various types of nested COLLECTION_TYPES into tables and UDTs """ - if self.cass_version < (2, 1, 3): - raise unittest.SkipTest("Support for nested collections was introduced in Cassandra 2.1.3") - c = TestCluster() s = c.connect(self.keyspace_name, wait_for_all_pools=True) s.encoder.mapping[tuple] = s.encoder.cql_encode_tuple @@ -679,72 +675,3 @@ def test_non_alphanum_identifiers(self): assert k.__class__ != tuple # should be the namedtuple type assert k[0] == 'alphanum' assert k.field_0_ == 'alphanum' # named tuple with positional field name - - @lessthancass30 - def test_type_alteration(self): - """ - Support for ALTER TYPE was removed in CASSANDRA-12443 - """ - s = self.session - type_name = "type_name" - assert type_name not in s.cluster.metadata.keyspaces['udttests'].user_types - s.execute('CREATE TYPE %s (v0 int)' % (type_name,)) - assert type_name in s.cluster.metadata.keyspaces['udttests'].user_types - - s.execute('CREATE TABLE %s (k int PRIMARY KEY, v frozen<%s>)' % (self.table_name, type_name)) - s.execute('INSERT INTO %s (k, v) VALUES (0, {v0 : 1})' % (self.table_name,)) - - s.cluster.register_user_type('udttests', type_name, dict) - - val = s.execute('SELECT v FROM %s' % self.table_name).one()[0] - assert val['v0'] == 1 - - # add field - s.execute('ALTER TYPE %s ADD v1 text' % (type_name,)) - val = s.execute('SELECT v FROM %s' % self.table_name).one()[0] - assert val['v0'] == 1 - assert val['v1'] is None - s.execute("INSERT INTO %s (k, v) VALUES (0, {v0 : 2, v1 : 'sometext'})" % (self.table_name,)) - val = s.execute('SELECT v FROM %s' % self.table_name).one()[0] - assert val['v0'] == 2 - assert val['v1'] == 'sometext' - - # alter field type - s.execute('ALTER TYPE %s ALTER v1 TYPE blob' % (type_name,)) - s.execute("INSERT INTO %s (k, v) VALUES (0, {v0 : 3, v1 : 0xdeadbeef})" % (self.table_name,)) - val = s.execute('SELECT v FROM %s' % self.table_name).one()[0] - assert val['v0'] == 3 - assert val['v1'] == b'\xde\xad\xbe\xef' - - @lessthancass30 - def test_alter_udt(self): - """ - Test to ensure that altered UDT's are properly surfaced without needing to restart the underlying session. - - @since 3.0.0 - @jira_ticket PYTHON-226 - @expected_result UDT's will reflect added columns without a session restart. - - @test_category data_types, udt - """ - - # Create udt ensure it has the proper column names. - self.session.set_keyspace(self.keyspace_name) - self.session.execute("CREATE TYPE typetoalter (a int)") - typetoalter = namedtuple('typetoalter', ('a')) - self.session.execute("CREATE TABLE {0} (pk int primary key, typetoalter frozen)".format(self.function_table_name)) - insert_statement = self.session.prepare("INSERT INTO {0} (pk, typetoalter) VALUES (?, ?)".format(self.function_table_name)) - self.session.execute(insert_statement, [1, typetoalter(1)]) - results = self.session.execute("SELECT * from {0}".format(self.function_table_name)) - for result in results: - assert hasattr(result.typetoalter, 'a') - assert not hasattr(result.typetoalter, 'b') - - # Alter UDT and ensure the alter is honored in results - self.session.execute("ALTER TYPE typetoalter add b int") - typetoalter = namedtuple('typetoalter', ('a', 'b')) - self.session.execute(insert_statement, [2, typetoalter(2, 2)]) - results = self.session.execute("SELECT * from {0}".format(self.function_table_name)) - for result in results: - assert hasattr(result.typetoalter, 'a') - assert hasattr(result.typetoalter, 'b') diff --git a/tests/integration/util.py b/tests/integration/util.py index 7cbdfdb22d..5f091d9508 100644 --- a/tests/integration/util.py +++ b/tests/integration/util.py @@ -14,7 +14,6 @@ from itertools import chain -from tests.integration import PROTOCOL_VERSION import time @@ -53,5 +52,3 @@ def assert_quiescent_pool_state(cluster, wait=None): assert len(req_ids) == len(set(req_ids)) assert connection.highest_request_id == len(req_ids) + len(orphan_ids) - 1 assert connection.highest_request_id == max(chain(req_ids, orphan_ids)) - if PROTOCOL_VERSION < 3: - assert connection.highest_request_id == connection.max_request_id diff --git a/tests/unit/advanced/test_geometry.py b/tests/unit/advanced/test_geometry.py index 1927b51da7..c102ac9119 100644 --- a/tests/unit/advanced/test_geometry.py +++ b/tests/unit/advanced/test_geometry.py @@ -17,7 +17,6 @@ import struct import math from cassandra.cqltypes import lookup_casstype -from cassandra.protocol import ProtocolVersion from cassandra.cqltypes import PointType, LineStringType, PolygonType, WKBGeometryType from cassandra.util import Point, LineString, Polygon, _LinearRing, Distance, _HAS_GEOMET import pytest @@ -25,23 +24,19 @@ wkb_be = 0 wkb_le = 1 -protocol_versions = ProtocolVersion.SUPPORTED_VERSIONS - class GeoTypes(unittest.TestCase): samples = (Point(1, 2), LineString(((1, 2), (3, 4), (5, 6))), Polygon([(10.1, 10.0), (110.0, 10.0), (110., 110.0), (10., 110.0), (10., 10.0)], [[(20., 20.0), (20., 30.0), (30., 30.0), (30., 20.0), (20., 20.0)], [(40., 20.0), (40., 30.0), (50., 30.0), (50., 20.0), (40., 20.0)]])) def test_marshal_platform(self): - for proto_ver in protocol_versions: - for geo in self.samples: - cql_type = lookup_casstype(geo.__class__.__name__ + 'Type') - assert cql_type.from_binary(cql_type.to_binary(geo, proto_ver), proto_ver) == geo + for geo in self.samples: + cql_type = lookup_casstype(geo.__class__.__name__ + 'Type') + assert cql_type.from_binary(cql_type.to_binary(geo)) == geo def _verify_both_endian(self, typ, body_fmt, params, expected): - for proto_ver in protocol_versions: - assert typ.from_binary(struct.pack(">BI" + body_fmt, wkb_be, *params), proto_ver) == expected - assert typ.from_binary(struct.pack("BI" + body_fmt, wkb_be, *params)) == expected + assert typ.from_binary(struct.pack(" 0 diff --git a/tests/unit/io/utils.py b/tests/unit/io/utils.py index f43224058c..817a0791d6 100644 --- a/tests/unit/io/utils.py +++ b/tests/unit/io/utils.py @@ -200,7 +200,7 @@ def get_socket(self, connection): def set_socket(self, connection, obj): return setattr(connection, self.socket_attr_name, obj) - def make_header_prefix(self, message_class, version=3, stream_id=0): + def make_header_prefix(self, message_class, version=4, stream_id=0): return bytes().join(map(uint8_pack, [ 0xff & (HEADER_DIRECTION_TO_CLIENT | version), 0, # flags (compression) diff --git a/tests/unit/test_cluster.py b/tests/unit/test_cluster.py index 49208ac53e..d0d6073963 100644 --- a/tests/unit/test_cluster.py +++ b/tests/unit/test_cluster.py @@ -257,8 +257,6 @@ def test_protocol_downgrade_test(self): lower = ProtocolVersion.get_lower_supported(ProtocolVersion.V5) assert ProtocolVersion.V4 == lower lower = ProtocolVersion.get_lower_supported(ProtocolVersion.V4) - assert ProtocolVersion.V3 == lower - lower = ProtocolVersion.get_lower_supported(ProtocolVersion.V3) assert 0 == lower assert not ProtocolVersion.uses_error_code_map(ProtocolVersion.V4) diff --git a/tests/unit/test_marshalling.py b/tests/unit/test_marshalling.py index e4b415ac69..5ff6157367 100644 --- a/tests/unit/test_marshalling.py +++ b/tests/unit/test_marshalling.py @@ -13,8 +13,6 @@ # limitations under the License. import sys -from cassandra import ProtocolVersion - import unittest import platform @@ -75,7 +73,7 @@ (b'', 'MapType(AsciiType, BooleanType)', None), (b'', 'ListType(FloatType)', None), (b'', 'SetType(LongType)', None), - (b'\x00\x00\x00\x00', 'MapType(DecimalType, BooleanType)', OrderedMapSerializedKey(DecimalType, 3)), + (b'\x00\x00\x00\x00', 'MapType(DecimalType, BooleanType)', OrderedMapSerializedKey(DecimalType)), (b'\x00\x00\x00\x00', 'ListType(FloatType)', []), (b'\x00\x00\x00\x00', 'SetType(IntegerType)', sortedset()), (b'\x00\x00\x00\x01\x00\x00\x00\x10\xafYC\xa3\xea<\x11\xe1\xabc\xc4,\x03"y\xf0', 'ListType(TimeUUIDType)', [UUID(bytes=b'\xafYC\xa3\xea<\x11\xe1\xabc\xc4,\x03"y\xf0')]), @@ -88,7 +86,7 @@ (b'\x80\x00', 'ShortType', -32768) ) -ordered_map_value = OrderedMapSerializedKey(UTF8Type, 3) +ordered_map_value = OrderedMapSerializedKey(UTF8Type) ordered_map_value._insert(u'\u307fbob', 199) ordered_map_value._insert(u'', -1) ordered_map_value._insert(u'\\', 0) @@ -111,27 +109,26 @@ class UnmarshalTest(unittest.TestCase): def test_unmarshalling(self): for serializedval, valtype, nativeval in marshalled_value_pairs: unmarshaller = lookup_casstype(valtype) - whatwegot = unmarshaller.from_binary(serializedval, 3) + whatwegot = unmarshaller.from_binary(serializedval) assert whatwegot == nativeval, 'Unmarshaller for %s (%s) failed: unmarshal(%r) got %r instead of %r' % (valtype, unmarshaller, serializedval, whatwegot, nativeval) assert type(whatwegot) == type(nativeval), 'Unmarshaller for %s (%s) gave wrong type (%s instead of %s)' % (valtype, unmarshaller, type(whatwegot), type(nativeval)) def test_marshalling(self): for serializedval, valtype, nativeval in marshalled_value_pairs: marshaller = lookup_casstype(valtype) - whatwegot = marshaller.to_binary(nativeval, 3) + whatwegot = marshaller.to_binary(nativeval) assert whatwegot == serializedval, 'Marshaller for %s (%s) failed: marshal(%r) got %r instead of %r' % (valtype, marshaller, nativeval, whatwegot, serializedval) assert type(whatwegot) == type(serializedval), 'Marshaller for %s (%s) gave wrong type (%s instead of %s)' % (valtype, marshaller, type(whatwegot), type(serializedval)) def test_date(self): # separate test because it will deserialize as datetime - assert DateType.from_binary(DateType.to_binary(date(2015, 11, 2), 3), 3) == datetime(2015, 11, 2) + assert DateType.from_binary(DateType.to_binary(date(2015, 11, 2))) == datetime(2015, 11, 2) def test_decimal(self): # testing implicit numeric conversion # int, tuple(sign, digits, exp), float converted_types = (10001, (0, (1, 0, 0, 0, 0, 1), -3), 100.1, -87.629798) - for proto_ver in range(3, ProtocolVersion.MAX_SUPPORTED + 1): - for n in converted_types: - expected = Decimal(n) - assert DecimalType.from_binary(DecimalType.to_binary(n, proto_ver), proto_ver) == expected + for n in converted_types: + expected = Decimal(n) + assert DecimalType.from_binary(DecimalType.to_binary(n)) == expected diff --git a/tests/unit/test_orderedmap.py b/tests/unit/test_orderedmap.py index 156bbd5f30..3afa17af3b 100644 --- a/tests/unit/test_orderedmap.py +++ b/tests/unit/test_orderedmap.py @@ -167,17 +167,16 @@ def test_delitem(self): class OrderedMapSerializedKeyTest(unittest.TestCase): def test_init(self): - om = OrderedMapSerializedKey(UTF8Type, 3) + om = OrderedMapSerializedKey(UTF8Type) assert om == {} def test_normalized_lookup(self): key_type = lookup_casstype('MapType(UTF8Type, Int32Type)') - protocol_version = 3 - om = OrderedMapSerializedKey(key_type, protocol_version) + om = OrderedMapSerializedKey(key_type) key_ascii = {'one': 1} key_unicode = {u'two': 2} - om._insert_unchecked(key_ascii, key_type.serialize(key_ascii, protocol_version), object()) - om._insert_unchecked(key_unicode, key_type.serialize(key_unicode, protocol_version), object()) + om._insert_unchecked(key_ascii, key_type.serialize(key_ascii), object()) + om._insert_unchecked(key_unicode, key_type.serialize(key_unicode), object()) # type lookup is normalized by key_type # PYTHON-231 diff --git a/tests/unit/test_parameter_binding.py b/tests/unit/test_parameter_binding.py index 5416ac461d..dd26f22ddb 100644 --- a/tests/unit/test_parameter_binding.py +++ b/tests/unit/test_parameter_binding.py @@ -73,8 +73,6 @@ def test_float_precision(self): class BoundStatementTestV3(unittest.TestCase): - protocol_version = 3 - @classmethod def setUpClass(cls): column_metadata = [ColumnMetadata('keyspace', 'cf', 'rk0', Int32Type), @@ -86,7 +84,7 @@ def setUpClass(cls): routing_key_indexes=[1, 0], query=None, keyspace='keyspace', - protocol_version=cls.protocol_version, result_metadata=None, + result_metadata=None, result_metadata_id=None) cls.bound = BoundStatement(prepared_statement=cls.prepared) @@ -122,7 +120,6 @@ def test_inherit_fetch_size(self): routing_key_indexes=[], query=None, keyspace=keyspace, - protocol_version=self.protocol_version, result_metadata=None, result_metadata_id=None) prepared_statement.fetch_size = 1234 @@ -137,14 +134,21 @@ def test_too_few_parameters_for_routing_key(self): assert bound.keyspace == 'keyspace' def test_dict_missing_routing_key(self): - with pytest.raises(KeyError): + # UNSET_VALUE is ValueError for routing keys + with pytest.raises(ValueError): self.bound.bind({'rk0': 0, 'ck0': 0, 'v0': 0}) - with pytest.raises(KeyError): + with pytest.raises(ValueError): self.bound.bind({'rk1': 0, 'ck0': 0, 'v0': 0}) def test_missing_value(self): - with pytest.raises(KeyError): - self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0}) + # missing values are UNSET_VALUE + self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0}) + assert self.bound.values[-1] == UNSET_VALUE + + old_values = self.bound.values + self.bound.bind((0, 0, 0)) + assert self.bound.values is not old_values + assert self.bound.values[-1] == UNSET_VALUE def test_extra_value(self): self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0, 'v0': 0, 'should_not_be_here': 123}) # okay to have extra keys in dict @@ -163,7 +167,6 @@ def test_values_none(self): routing_key_indexes=[], query=None, keyspace='whatever', - protocol_version=self.protocol_version, result_metadata=None, result_metadata_id=None) bound = prepared_statement.bind(None) @@ -178,34 +181,6 @@ def test_bind_none(self): assert self.bound.values is not old_values assert self.bound.values[-1] == None - def test_unset_value(self): - with pytest.raises(ValueError): - self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0, 'v0': UNSET_VALUE}) - with pytest.raises(ValueError): - self.bound.bind((0, 0, 0, UNSET_VALUE)) - - -class BoundStatementTestV4(BoundStatementTestV3): - protocol_version = 4 - - def test_dict_missing_routing_key(self): - # in v4 it implicitly binds UNSET_VALUE for missing items, - # UNSET_VALUE is ValueError for routing keys - with pytest.raises(ValueError): - self.bound.bind({'rk0': 0, 'ck0': 0, 'v0': 0}) - with pytest.raises(ValueError): - self.bound.bind({'rk1': 0, 'ck0': 0, 'v0': 0}) - - def test_missing_value(self): - # in v4 missing values are UNSET_VALUE - self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0}) - assert self.bound.values[-1] == UNSET_VALUE - - old_values = self.bound.values - self.bound.bind((0, 0, 0)) - assert self.bound.values is not old_values - assert self.bound.values[-1] == UNSET_VALUE - def test_unset_value(self): self.bound.bind({'rk0': 0, 'rk1': 0, 'ck0': 0, 'v0': UNSET_VALUE}) assert self.bound.values[-1] == UNSET_VALUE @@ -214,5 +189,9 @@ def test_unset_value(self): assert self.bound.values[-1] == UNSET_VALUE +class BoundStatementTestV4(BoundStatementTestV3): + pass + + class BoundStatementTestV5(BoundStatementTestV4): - protocol_version = 5 + pass diff --git a/tests/unit/test_query.py b/tests/unit/test_query.py index 6b0ebe690e..44c7d14cf1 100644 --- a/tests/unit/test_query.py +++ b/tests/unit/test_query.py @@ -76,7 +76,6 @@ def _make_prepared_statement(self, is_lwt=False): routing_key_indexes=[], query="INSERT INTO test.table (id) VALUES (1)", keyspace=None, - protocol_version=4, result_metadata=[], result_metadata_id=None, is_lwt=is_lwt, diff --git a/tests/unit/test_types.py b/tests/unit/test_types.py index a5bd028b26..f5a67301d1 100644 --- a/tests/unit/test_types.py +++ b/tests/unit/test_types.py @@ -218,28 +218,28 @@ def test_datetype(self): now_timestamp = now_time_seconds * 1e3 # same results serialized - assert DateType.serialize(now_datetime, 0) == DateType.serialize(now_timestamp, 0) + assert DateType.serialize(now_datetime) == DateType.serialize(now_timestamp) # deserialize # epoc expected = 0 - assert DateType.deserialize(int64_pack(1000 * expected), 0) == datetime.datetime.fromtimestamp(expected, tz=datetime.timezone.utc).replace(tzinfo=None) + assert DateType.deserialize(int64_pack(1000 * expected)) == datetime.datetime.fromtimestamp(expected, tz=datetime.timezone.utc).replace(tzinfo=None) # beyond 32b expected = 2 ** 33 - assert DateType.deserialize(int64_pack(1000 * expected), 0) == datetime.datetime(2242, 3, 16, 12, 56, 32, tzinfo=datetime.timezone.utc).replace(tzinfo=None) + assert DateType.deserialize(int64_pack(1000 * expected)) == datetime.datetime(2242, 3, 16, 12, 56, 32, tzinfo=datetime.timezone.utc).replace(tzinfo=None) # less than epoc (PYTHON-119) expected = -770172256 - assert DateType.deserialize(int64_pack(1000 * expected), 0) == datetime.datetime(1945, 8, 5, 23, 15, 44, tzinfo=datetime.timezone.utc).replace(tzinfo=None) + assert DateType.deserialize(int64_pack(1000 * expected)) == datetime.datetime(1945, 8, 5, 23, 15, 44, tzinfo=datetime.timezone.utc).replace(tzinfo=None) # work around rounding difference among Python versions (PYTHON-230) expected = 1424817268.274 - assert DateType.deserialize(int64_pack(int(1000 * expected)), 0) == datetime.datetime(2015, 2, 24, 22, 34, 28, 274000, tzinfo=datetime.timezone.utc).replace(tzinfo=None) + assert DateType.deserialize(int64_pack(int(1000 * expected))) == datetime.datetime(2015, 2, 24, 22, 34, 28, 274000, tzinfo=datetime.timezone.utc).replace(tzinfo=None) # Large date overflow (PYTHON-452) expected = 2177403010.123 - assert DateType.deserialize(int64_pack(int(1000 * expected)), 0) == datetime.datetime(2038, 12, 31, 10, 10, 10, 123000, tzinfo=datetime.timezone.utc).replace(tzinfo=None) + assert DateType.deserialize(int64_pack(int(1000 * expected))) == datetime.datetime(2038, 12, 31, 10, 10, 10, 123000, tzinfo=datetime.timezone.utc).replace(tzinfo=None) def test_collection_null_support(self): """ @@ -254,10 +254,10 @@ def test_collection_null_support(self): int32_pack(4) + # size of item2 int32_pack(42) # item2 ) - assert [None, 42] == int_list.deserialize(value, 3) + assert [None, 42] == int_list.deserialize(value) set_list = SetType.apply_parameters([Int32Type]) - assert {None, 42} == set(set_list.deserialize(value, 3)) + assert {None, 42} == set(set_list.deserialize(value)) value = ( int32_pack(2) + # num items @@ -271,7 +271,7 @@ def test_collection_null_support(self): map_list = MapType.apply_parameters([Int32Type, Int32Type]) - assert [(42, None), (None, 42)] == map_list.deserialize(value, 3)._items # OrderedMapSerializedKey + assert [(42, None), (None, 42)] == map_list.deserialize(value)._items # OrderedMapSerializedKey def test_write_read_string(self): with tempfile.TemporaryFile() as f: @@ -340,11 +340,11 @@ def _round_trip_compare_fn(self, first, second): def _round_trip_test(self, data, ctype_str): ctype = parse_casstype_args(ctype_str) - data_bytes = ctype.serialize(data, 0) + data_bytes = ctype.serialize(data) serialized_size = ctype.subtype.serial_size() if serialized_size: assert serialized_size * len(data) == len(data_bytes) - result = ctype.deserialize(data_bytes, 0) + result = ctype.deserialize(data_bytes) assert len(data) == len(result) for idx in range(0,len(data)): self._round_trip_compare_fn(data[idx], result[idx]) @@ -464,50 +464,50 @@ def test_cql_parameterized_type(self): def test_serialization_fixed_size_too_small(self): ctype = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 5)") with pytest.raises(ValueError, match="Expected sequence of size 5 for vector of type float and dimension 5, observed sequence of length 4"): - ctype.serialize([1.2, 3.4, 5.6, 7.8], 0) + ctype.serialize([1.2, 3.4, 5.6, 7.8]) def test_serialization_fixed_size_too_big(self): ctype = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 4)") with pytest.raises(ValueError, match="Expected sequence of size 4 for vector of type float and dimension 4, observed sequence of length 5"): - ctype.serialize([1.2, 3.4, 5.6, 7.8, 9.10], 0) + ctype.serialize([1.2, 3.4, 5.6, 7.8, 9.10]) def test_serialization_variable_size_too_small(self): ctype = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 5)") with pytest.raises(ValueError, match="Expected sequence of size 5 for vector of type varint and dimension 5, observed sequence of length 4"): - ctype.serialize([1, 2, 3, 4], 0) + ctype.serialize([1, 2, 3, 4]) def test_serialization_variable_size_too_big(self): ctype = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 4)") with pytest.raises(ValueError, match="Expected sequence of size 4 for vector of type varint and dimension 4, observed sequence of length 5"): - ctype.serialize([1, 2, 3, 4, 5], 0) + ctype.serialize([1, 2, 3, 4, 5]) def test_deserialization_fixed_size_too_small(self): ctype_four = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 4)") - ctype_four_bytes = ctype_four.serialize([1.2, 3.4, 5.6, 7.8], 0) + ctype_four_bytes = ctype_four.serialize([1.2, 3.4, 5.6, 7.8]) ctype_five = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 5)") with pytest.raises(ValueError, match="Expected vector of type float and dimension 5 to have serialized size 20; observed serialized size of 16 instead"): - ctype_five.deserialize(ctype_four_bytes, 0) + ctype_five.deserialize(ctype_four_bytes) def test_deserialization_fixed_size_too_big(self): ctype_five = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 5)") - ctype_five_bytes = ctype_five.serialize([1.2, 3.4, 5.6, 7.8, 9.10], 0) + ctype_five_bytes = ctype_five.serialize([1.2, 3.4, 5.6, 7.8, 9.10]) ctype_four = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.FloatType, 4)") with pytest.raises(ValueError, match="Expected vector of type float and dimension 4 to have serialized size 16; observed serialized size of 20 instead"): - ctype_four.deserialize(ctype_five_bytes, 0) + ctype_four.deserialize(ctype_five_bytes) def test_deserialization_variable_size_too_small(self): ctype_four = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 4)") - ctype_four_bytes = ctype_four.serialize([1, 2, 3, 4], 0) + ctype_four_bytes = ctype_four.serialize([1, 2, 3, 4]) ctype_five = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 5)") with pytest.raises(ValueError, match="Error reading additional data during vector deserialization after successfully adding 4 elements"): - ctype_five.deserialize(ctype_four_bytes, 0) + ctype_five.deserialize(ctype_four_bytes) def test_deserialization_variable_size_too_big(self): ctype_five = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 5)") - ctype_five_bytes = ctype_five.serialize([1, 2, 3, 4, 5], 0) + ctype_five_bytes = ctype_five.serialize([1, 2, 3, 4, 5]) ctype_four = parse_casstype_args("org.apache.cassandra.db.marshal.VectorType(org.apache.cassandra.db.marshal.IntegerType, 4)") with pytest.raises(ValueError, match="Additional bytes remaining after vector deserialization completed"): - ctype_four.deserialize(ctype_five_bytes, 0) + ctype_four.deserialize(ctype_five_bytes) ZERO = datetime.timedelta(0) @@ -575,7 +575,7 @@ def test_deserialize_single_value(self): serialized = (int8_pack(0) + int64_pack(self.timestamp) + int8_pack(3)) - assert DateRangeType.deserialize(serialized, 5) == util.DateRange(value=util.DateRangeBound( + assert DateRangeType.deserialize(serialized) == util.DateRange(value=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 15, 42, 12, 404000), precision='HOUR') ) @@ -586,7 +586,7 @@ def test_deserialize_closed_range(self): int8_pack(2) + int64_pack(self.timestamp) + int8_pack(6)) - assert DateRangeType.deserialize(serialized, 5) == util.DateRange( + assert DateRangeType.deserialize(serialized) == util.DateRange( lower_bound=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 0, 0), precision='DAY' @@ -601,7 +601,7 @@ def test_deserialize_open_high(self): serialized = (int8_pack(2) + int64_pack(self.timestamp) + int8_pack(3)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 15, 0), @@ -614,7 +614,7 @@ def test_deserialize_open_low(self): serialized = (int8_pack(3) + int64_pack(self.timestamp) + int8_pack(4)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.OPEN_BOUND, upper_bound=util.DateRangeBound( @@ -624,13 +624,13 @@ def test_deserialize_open_low(self): ) def test_deserialize_single_open(self): - assert util.DateRange(value=util.OPEN_BOUND) == DateRangeType.deserialize(int8_pack(5), 5) + assert util.DateRange(value=util.OPEN_BOUND) == DateRangeType.deserialize(int8_pack(5)) def test_serialize_single_value(self): serialized = (int8_pack(0) + int64_pack(self.timestamp) + int8_pack(5)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( value=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 15, 42, 12), @@ -644,7 +644,7 @@ def test_serialize_closed_range(self): int8_pack(5) + int64_pack(self.timestamp) + int8_pack(0)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 15, 42, 12), @@ -660,7 +660,7 @@ def test_serialize_open_high(self): serialized = (int8_pack(2) + int64_pack(self.timestamp) + int8_pack(2)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.DateRangeBound( value=datetime.datetime(2017, 2, 1), @@ -673,7 +673,7 @@ def test_serialize_open_low(self): serialized = (int8_pack(2) + int64_pack(self.timestamp) + int8_pack(3)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.DateRangeBound( value=datetime.datetime(2017, 2, 1, 15), @@ -684,7 +684,7 @@ def test_serialize_open_low(self): def test_deserialize_both_open(self): serialized = (int8_pack(4)) - deserialized = DateRangeType.deserialize(serialized, 5) + deserialized = DateRangeType.deserialize(serialized) assert deserialized == util.DateRange( lower_bound=util.OPEN_BOUND, upper_bound=util.OPEN_BOUND @@ -693,31 +693,31 @@ def test_deserialize_both_open(self): def test_serialize_single_open(self): serialized = DateRangeType.serialize(util.DateRange( value=util.OPEN_BOUND, - ), 5) + )) assert int8_pack(5) == serialized def test_serialize_both_open(self): serialized = DateRangeType.serialize(util.DateRange( lower_bound=util.OPEN_BOUND, upper_bound=util.OPEN_BOUND - ), 5) + )) assert int8_pack(4) == serialized def test_failure_to_serialize_no_value_object(self): with pytest.raises(ValueError): - DateRangeType.serialize(object(), 5) + DateRangeType.serialize(object()) def test_failure_to_serialize_no_bounds_object(self): class no_bounds_object(object): value = lower_bound = None with pytest.raises(ValueError): - DateRangeType.serialize(no_bounds_object, 5) + DateRangeType.serialize(no_bounds_object) def test_serialized_value_round_trip(self): vals = [b'\x01\x00\x00\x01%\xe9a\xf9\xd1\x06\x00\x00\x01v\xbb>o\xff\x00', b'\x01\x00\x00\x00\xdcm\x03-\xd1\x06\x00\x00\x01v\xbb>o\xff\x00'] for serialized in vals: - assert serialized == DateRangeType.serialize(DateRangeType.deserialize(serialized, 0), 0) + assert serialized == DateRangeType.serialize(DateRangeType.deserialize(serialized)) def test_serialize_zero_datetime(self): """ @@ -734,7 +734,7 @@ def test_serialize_zero_datetime(self): DateRangeType.serialize(util.DateRange( lower_bound=(datetime.datetime(1970, 1, 1), 'YEAR'), upper_bound=(datetime.datetime(1970, 1, 1), 'YEAR') - ), 5) + )) def test_deserialize_zero_datetime(self): """ @@ -751,8 +751,7 @@ def test_deserialize_zero_datetime(self): DateRangeType.deserialize( (int8_pack(1) + int64_pack(0) + int8_pack(0) + - int64_pack(0) + int8_pack(0)), - 5 + int64_pack(0) + int8_pack(0)) )