diff --git a/cassandra/cluster.py b/cassandra/cluster.py index e23a7491..3a96b5a8 100644 --- a/cassandra/cluster.py +++ b/cassandra/cluster.py @@ -2,14 +2,17 @@ This module houses the main classes you will interact with, :class:`.Cluster` and :class:`.Session`. """ - from concurrent.futures import ThreadPoolExecutor import logging import socket import sys import time from threading import Lock, RLock, Thread, Event -import Queue + +import six +from six.moves import xrange +from six.moves import queue as Queue + import weakref from weakref import WeakValueDictionary try: @@ -51,6 +54,9 @@ try: except ImportError: from cassandra.io.asyncorereactor import AsyncoreConnection as DefaultConnection # NOQA +## Python 3 support ######### +############################# + # Forces load of utf8 encoding module to avoid deadlock that occurs # if code that is being imported tries to import the module in a seperate # thread. @@ -1060,7 +1066,7 @@ class Session(object): prepared_statement = None - if isinstance(query, basestring): + if isinstance(query, six.string_types): query = SimpleStatement(query) elif isinstance(query, PreparedStatement): query = query.bind(parameters) diff --git a/cassandra/connection.py b/cassandra/connection.py index d8275042..a1c42c2e 100644 --- a/cassandra/connection.py +++ b/cassandra/connection.py @@ -2,7 +2,8 @@ import errno from functools import wraps, partial import logging from threading import Event, RLock -from Queue import Queue + +from six.moves.queue import Queue from cassandra import ConsistencyLevel, AuthenticationFailed, OperationTimedOut from cassandra.marshal import int8_unpack, int32_pack diff --git a/cassandra/cqltypes.py b/cassandra/cqltypes.py index 012ba500..192e0187 100644 --- a/cassandra/cqltypes.py +++ b/cassandra/cqltypes.py @@ -22,10 +22,9 @@ from datetime import datetime from uuid import UUID import warnings -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO # NOQA +import six +from six.moves import cStringIO as StringIO +from six.moves import xrange from cassandra.marshal import (int8_pack, int8_unpack, uint16_pack, uint16_unpack, int32_pack, int32_unpack, int64_pack, int64_unpack, @@ -35,7 +34,12 @@ from cassandra.util import OrderedDict apache_cassandra_type_prefix = 'org.apache.cassandra.db.marshal.' -_number_types = frozenset((int, long, float)) +## Python 3 support ######### +if six.PY3: + _number_types = frozenset((int, float)) +else: + _number_types = frozenset((int, long, float)) +############################# try: from blist import sortedset @@ -482,7 +486,7 @@ class DateType(_CassandraType): @classmethod def validate(cls, date): - if isinstance(date, basestring): + if isinstance(date, six.string_types): date = cls.interpret_datestring(date) return date @@ -624,7 +628,7 @@ class _SimpleParameterizedType(_ParameterizedType): @classmethod def serialize_safe(cls, items): - if isinstance(items, basestring): + if isinstance(items, six.string_types): raise TypeError("Received a string for a type that expects a sequence") subtype, = cls.subtypes @@ -733,7 +737,7 @@ class ReversedType(_ParameterizedType): def is_counter_type(t): - if isinstance(t, basestring): + if isinstance(t, six.string_types): t = lookup_casstype(t) return issubclass(t, CounterColumnType) diff --git a/cassandra/decoder.py b/cassandra/decoder.py index d806a28a..28aaa99a 100644 --- a/cassandra/decoder.py +++ b/cassandra/decoder.py @@ -2,10 +2,8 @@ import logging import socket from uuid import UUID -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO # ignore flake8 warning: # NOQA +from six.moves import cStringIO as StringIO +from six.moves import xrange from cassandra import (Unavailable, WriteTimeout, ReadTimeout, AlreadyExists, InvalidRequest, Unauthorized) @@ -17,6 +15,8 @@ from cassandra.cqltypes import (AsciiType, BytesType, BooleanType, InetAddressType, IntegerType, ListType, LongType, MapType, SetType, TimeUUIDType, UTF8Type, UUIDType, lookup_casstype) +import six + log = logging.getLogger(__name__) @@ -564,7 +564,7 @@ class BatchMessage(_MessageType): write_byte(f, self.batch_type.value) write_short(f, len(self.queries)) for string_or_query_id, params in self.queries: - if isinstance(string_or_query_id, basestring): + if isinstance(string_or_query_id, six.string_types): write_byte(f, 0) write_longstring(f, string_or_query_id) else: @@ -679,7 +679,7 @@ def read_binary_string(f): def write_string(f, s): - if isinstance(s, unicode): + if isinstance(s, six.text_type): s = s.encode('utf8') write_short(f, len(s)) f.write(s) @@ -692,7 +692,7 @@ def read_longstring(f): def write_longstring(f, s): - if isinstance(s, unicode): + if isinstance(s, six.text_type): s = s.encode('utf8') write_int(f, len(s)) f.write(s) diff --git a/cassandra/encoder.py b/cassandra/encoder.py index ae1873a1..5662ff45 100644 --- a/cassandra/encoder.py +++ b/cassandra/encoder.py @@ -4,9 +4,14 @@ import datetime import sys import types from uuid import UUID +import six from cassandra.util import OrderedDict +if six.PY3: + unicode = str + long = int + def cql_quote(term): if isinstance(term, unicode): @@ -78,13 +83,10 @@ def cql_encode_all_types(val): cql_encoders = { float: cql_encode_object, - buffer: cql_encode_bytes, bytearray: cql_encode_bytes, str: cql_encode_str, - unicode: cql_encode_unicode, types.NoneType: cql_encode_none, int: cql_encode_object, - long: cql_encode_object, UUID: cql_encode_object, datetime.datetime: cql_encode_datetime, datetime.date: cql_encode_date, @@ -96,3 +98,10 @@ cql_encoders = { frozenset: cql_encode_set_collection, types.GeneratorType: cql_encode_list_collection } + +if six.PY2: + cql_encoders.update({ + buffer: cql_encode_bytes, + unicode: cql_encode_unicode, + long: cql_encode_object, + }) diff --git a/cassandra/io/asyncorereactor.py b/cassandra/io/asyncorereactor.py index f3f9f4e4..a89d09a6 100644 --- a/cassandra/io/asyncorereactor.py +++ b/cassandra/io/asyncorereactor.py @@ -7,16 +7,14 @@ import sys from threading import Event, Lock, Thread import time import traceback -import Queue + +from six.moves import queue as Queue +from six.moves import cStringIO as StringIO +from six.moves import xrange from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, EINVAL, EISCONN, errorcode import asyncore -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO # ignore flake8 warning: # NOQA - try: import ssl except ImportError: @@ -381,7 +379,7 @@ class AsyncoreConnection(Connection, asyncore.dispatcher): return waiter.deliver(timeout) except OperationTimedOut: raise - except Exception, exc: + except Exception as exc: self.defunct(exc) raise diff --git a/cassandra/io/libevreactor.py b/cassandra/io/libevreactor.py index be5fbc9b..ce9da427 100644 --- a/cassandra/io/libevreactor.py +++ b/cassandra/io/libevreactor.py @@ -6,7 +6,10 @@ import socket from threading import Event, Lock, Thread import time import traceback -import Queue + +from six.moves.queue import Queue +from six.moves import cStringIO as StringIO +from six.moves import xrange from cassandra import OperationTimedOut from cassandra.connection import (Connection, ResponseWaiter, ConnectionShutdown, @@ -25,10 +28,6 @@ except ImportError: "for instructions on installing build dependencies and building " "the C extension.") -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO # ignore flake8 warning: # NOQA try: import ssl @@ -436,7 +435,7 @@ class LibevConnection(Connection): return waiter.deliver(timeout) except OperationTimedOut: raise - except Exception, exc: + except Exception as exc: self.defunct(exc) raise diff --git a/cassandra/murmur3.c b/cassandra/murmur3.c index 3617819d..5526d008 100644 --- a/cassandra/murmur3.c +++ b/cassandra/murmur3.c @@ -202,6 +202,11 @@ initmurmur3(void) #else +PyMODINIT_FUNC +PyInit_murmur3(void) +{ + +} /* Python 3.x */ // TODO diff --git a/cassandra/policies.py b/cassandra/policies.py index 44fdae23..a5ff5458 100644 --- a/cassandra/policies.py +++ b/cassandra/policies.py @@ -5,6 +5,8 @@ from threading import Lock from cassandra import ConsistencyLevel +from six.moves import xrange + log = logging.getLogger(__name__) diff --git a/cassandra/pool.py b/cassandra/pool.py index 974b803a..1bbd1f1f 100644 --- a/cassandra/pool.py +++ b/cassandra/pool.py @@ -360,7 +360,7 @@ class HostConnectionPool(object): def _create_new_connection(self): try: self._add_conn_if_under_max() - except (ConnectionException, socket.error), exc: + except (ConnectionException, socket.error) as exc: log.warn("Failed to create new connection to %s: %s", self.host, exc) except Exception: log.exception("Unexpectedly failed to create new connection") diff --git a/cassandra/query.py b/cassandra/query.py index 323e885d..0cde646a 100644 --- a/cassandra/query.py +++ b/cassandra/query.py @@ -9,6 +9,7 @@ from datetime import datetime, timedelta import re import struct import time +import six from cassandra import ConsistencyLevel, OperationTimedOut from cassandra.cqltypes import unix_time_from_uuid1 @@ -354,7 +355,7 @@ class BatchStatement(Statement): Statement.__init__(self, retry_policy=retry_policy, consistency_level=consistency_level) def add(self, statement, parameters=None): - if isinstance(statement, basestring): + if isinstance(statement, six.string_types): if parameters: statement = bind_params(statement, parameters) self._statements_and_parameters.append((statement, ())) diff --git a/cassandra/util.py b/cassandra/util.py index 0b52e8b2..6e2aa84a 100644 --- a/cassandra/util.py +++ b/cassandra/util.py @@ -1,7 +1,5 @@ from __future__ import with_statement -from UserDict import DictMixin - try: from collections import OrderedDict except ImportError: @@ -28,6 +26,7 @@ except ImportError: # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. + from UserDict import DictMixin class OrderedDict(dict, DictMixin): # noqa """ A dictionary which maintains the insertion order of keys. """ diff --git a/requirements.txt b/requirements.txt index 1f4212c2..762b6e22 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ blist futures scales +six >=1.6 diff --git a/setup.py b/setup.py index 9fddd960..a9443b6f 100644 --- a/setup.py +++ b/setup.py @@ -149,7 +149,7 @@ def run_setup(extensions): kw['cmdclass']['build_ext'] = build_extensions kw['ext_modules'] = extensions - dependencies = ['futures', 'scales', 'blist', 'six'] + dependencies = ['futures', 'scales', 'blist', 'six >=1.6'] if platform.python_implementation() != "CPython": dependencies.remove('blist') diff --git a/tests/unit/io/test_asyncorereactor.py b/tests/unit/io/test_asyncorereactor.py index 5f00c22d..d63b4507 100644 --- a/tests/unit/io/test_asyncorereactor.py +++ b/tests/unit/io/test_asyncorereactor.py @@ -5,10 +5,9 @@ except ImportError: import errno import os -try: - from StringIO import StringIO -except ImportError: - from io import StringIO + +from six.moves import StringIO + import socket from socket import error as socket_error diff --git a/tests/unit/io/test_libevreactor.py b/tests/unit/io/test_libevreactor.py index 5490b549..a1c0c876 100644 --- a/tests/unit/io/test_libevreactor.py +++ b/tests/unit/io/test_libevreactor.py @@ -5,10 +5,9 @@ except ImportError: import errno import os -try: - from StringIO import StringIO -except ImportError: - from io import StringIO + +from six.moves import StringIO + from socket import error as socket_error from mock import patch, Mock diff --git a/tests/unit/test_connection.py b/tests/unit/test_connection.py index fa0ee925..74af32da 100644 --- a/tests/unit/test_connection.py +++ b/tests/unit/test_connection.py @@ -3,10 +3,7 @@ try: except ImportError: import unittest # noqa -try: - from StringIO import StringIO -except ImportError: - from io import StringIO +from six.moves import StringIO from mock import Mock, ANY diff --git a/tests/unit/test_parameter_binding.py b/tests/unit/test_parameter_binding.py index 975ef386..43f566d4 100644 --- a/tests/unit/test_parameter_binding.py +++ b/tests/unit/test_parameter_binding.py @@ -1,5 +1,3 @@ -import six - try: import unittest2 as unittest except ImportError: @@ -10,8 +8,7 @@ from cassandra.query import PreparedStatement, BoundStatement from cassandra.cqltypes import Int32Type from cassandra.util import OrderedDict -if six.PY3: - xrange = range +from six.moves import xrange class ParamBindingTest(unittest.TestCase): diff --git a/tests/unit/test_policies.py b/tests/unit/test_policies.py index 0cafbc75..0e85b2ae 100644 --- a/tests/unit/test_policies.py +++ b/tests/unit/test_policies.py @@ -1,5 +1,3 @@ -import six - try: import unittest2 as unittest except ImportError: @@ -24,8 +22,7 @@ from cassandra.policies import (RoundRobinPolicy, DCAwareRoundRobinPolicy, from cassandra.pool import Host from cassandra.query import Statement -if six.PY3: - xrange = range +from six.moves import xrange class TestLoadBalancingPolicy(unittest.TestCase):