Skip to content

Commit 558910e

Browse files
committed
All marshaling is working by supported pythons (26, 27, 33, pypy).
Have taken the approach of replacing methods at module load time (using if six.PY2). Much of this has been required where the assumption has been made that strings are not unicode, this of course is not true of Python 3
1 parent 714ef32 commit 558910e

9 files changed

Lines changed: 150 additions & 112 deletions

File tree

cassandra/cqltypes.py

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535

3636
if six.PY3:
3737
_number_types = frozenset((int, float))
38+
long = int
3839
else:
3940
_number_types = frozenset((int, long, float))
4041

@@ -217,7 +218,7 @@ def to_binary(cls, val):
217218
more information. This method differs in that if None is passed in,
218219
the result is the empty string.
219220
"""
220-
return six.binary_type() if val is None else cls.serialize(val)
221+
return b'' if val is None else cls.serialize(val)
221222

222223
@staticmethod
223224
def deserialize(byts):
@@ -278,7 +279,8 @@ def apply_parameters(cls, subtypes, names=None):
278279
if cls.num_subtypes != 'UNKNOWN' and len(subtypes) != cls.num_subtypes:
279280
raise ValueError("%s types require %d subtypes (%d given)"
280281
% (cls.typename, cls.num_subtypes, len(subtypes)))
281-
newname = cls.cass_parameterized_type_with(subtypes).encode('utf8')
282+
# newname = cls.cass_parameterized_type_with(subtypes).encode('utf8')
283+
newname = cls.cass_parameterized_type_with(subtypes)
282284
return type(newname, (cls,), {'subtypes': subtypes, 'cassname': cls.cassname})
283285

284286
@classmethod
@@ -309,10 +311,16 @@ class _UnrecognizedType(_CassandraType):
309311
num_subtypes = 'UNKNOWN'
310312

311313

312-
def mkUnrecognizedType(casstypename):
313-
return CassandraTypeType(casstypename.encode('utf8'),
314-
(_UnrecognizedType,),
315-
{'typename': "'%s'" % casstypename})
314+
if six.PY3:
315+
def mkUnrecognizedType(casstypename):
316+
return CassandraTypeType(casstypename,
317+
(_UnrecognizedType,),
318+
{'typename': "'%s'" % casstypename})
319+
else:
320+
def mkUnrecognizedType(casstypename):
321+
return CassandraTypeType(casstypename.encode('utf8'),
322+
(_UnrecognizedType,),
323+
{'typename': "'%s'" % casstypename})
316324

317325

318326
class BytesType(_CassandraType):
@@ -321,11 +329,11 @@ class BytesType(_CassandraType):
321329

322330
@staticmethod
323331
def validate(val):
324-
return buffer(val)
332+
return bytearray(val)
325333

326334
@staticmethod
327335
def serialize(val):
328-
return str(val)
336+
return six.binary_type(val)
329337

330338

331339
class DecimalType(_CassandraType):
@@ -386,9 +394,25 @@ def serialize(truth):
386394
return int8_pack(truth)
387395

388396

389-
class AsciiType(_CassandraType):
390-
typename = 'ascii'
391-
empty_binary_ok = True
397+
if six.PY2:
398+
class AsciiType(_CassandraType):
399+
typename = 'ascii'
400+
empty_binary_ok = True
401+
else:
402+
class AsciiType(_CassandraType):
403+
typename = 'ascii'
404+
empty_binary_ok = True
405+
406+
@staticmethod
407+
def deserialize(byts):
408+
return byts.decode('ascii')
409+
410+
@staticmethod
411+
def serialize(var):
412+
try:
413+
return var.encode('ascii')
414+
except UnicodeDecodeError:
415+
return var
392416

393417

394418
class FloatType(_CassandraType):
@@ -683,7 +707,7 @@ def serialize_safe(cls, themap):
683707
buf = six.BytesIO()
684708
buf.write(uint16_pack(len(themap)))
685709
try:
686-
items = themap.iteritems()
710+
items = six.iteritems(themap)
687711
except AttributeError:
688712
raise TypeError("Got a non-map object for a map value")
689713
for key, val in items:

cassandra/encoder.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88

99
from cassandra.util import OrderedDict
1010

11-
# if six.PY3:
12-
# unicode = str
13-
# long = int
11+
if six.PY3:
12+
long = int
1413

1514

1615
def cql_quote(term):
17-
if isinstance(term, unicode):
18-
return "'%s'" % term.encode('utf8').replace("'", "''")
19-
elif isinstance(term, (str, bool)):
16+
if isinstance(term, (str, bool)):
2017
return "'%s'" % str(term).replace("'", "''")
18+
elif isinstance(term, six.text_type):
19+
return "'%s'" % term.encode('utf8').replace("'", "''")
2120
else:
2221
return str(term)
2322

@@ -62,11 +61,10 @@ def cql_encode_sequence(val):
6261

6362

6463
def cql_encode_map_collection(val):
65-
return '{ %s }' % ' , '.join(
66-
'%s : %s' % (
67-
cql_encode_all_types(k),
68-
cql_encode_all_types(v))
69-
for k, v in val.iteritems())
64+
return '{ %s }' % ' , '.join('%s : %s' % (
65+
cql_encode_all_types(k),
66+
cql_encode_all_types(v)
67+
) for k, v in six.iteritems(val))
7068

7169

7270
def cql_encode_list_collection(val):
@@ -82,7 +80,6 @@ def cql_encode_all_types(val):
8280

8381

8482
cql_encoders = {
85-
six.binary_type: cql_encode_bytes,
8683
float: cql_encode_object,
8784
bytearray: cql_encode_bytes,
8885
str: cql_encode_str,
@@ -101,13 +98,13 @@ def cql_encode_all_types(val):
10198

10299
if six.PY2:
103100
cql_encoders.update({
104-
buffer: cql_encode_bytes,
105101
unicode: cql_encode_unicode,
102+
buffer: cql_encode_bytes,
106103
long: cql_encode_object,
107104
types.NoneType: cql_encode_none,
108105
})
109106
else:
110107
cql_encoders.update({
111108
memoryview: cql_encode_bytes,
112-
None: cql_encode_none,
109+
type(None): cql_encode_none,
113110
})

cassandra/marshal.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import six
12
import struct
23

34

@@ -29,11 +30,18 @@ def _make_packer(format_string):
2930
header_unpack = header_struct.unpack
3031

3132

32-
def varint_unpack(term):
33-
val = int(term.encode('hex'), 16)
34-
if (ord(term[0]) & 128) != 0:
35-
val = val - (1 << (len(term) * 8))
36-
return val
33+
if six.PY3:
34+
def varint_unpack(term):
35+
val = int(''.join("%02x" % i for i in term), 16)
36+
if (term[0] & 128) != 0:
37+
val -= 1 << (len(term) * 8)
38+
return val
39+
else:
40+
def varint_unpack(term):
41+
val = int(term.encode('hex'), 16)
42+
if (ord(term[0]) & 128) != 0:
43+
val = val - (1 << (len(term) * 8))
44+
return val
3745

3846

3947
def bitlength(n):
@@ -44,19 +52,25 @@ def bitlength(n):
4452
return bitlen
4553

4654

55+
if six.PY3:
56+
byte_val = int
57+
else:
58+
byte_val = ord
59+
60+
4761
def varint_pack(big):
4862
pos = True
4963
if big == 0:
50-
return '\x00'
64+
return b'\x00'
5165
if big < 0:
52-
bytelength = bitlength(abs(big) - 1) / 8 + 1
66+
bytelength = bitlength(abs(big) - 1) // 8 + 1
5367
big = (1 << bytelength * 8) + big
5468
pos = False
55-
revbytes = []
69+
revbytes = bytearray()
5670
while big > 0:
57-
revbytes.append(chr(big & 0xff))
71+
revbytes.append(big & 0xff)
5872
big >>= 8
59-
if pos and ord(revbytes[-1]) & 0x80:
60-
revbytes.append('\x00')
73+
if pos and revbytes[-1] & 0x80:
74+
revbytes.append(0)
6175
revbytes.reverse()
62-
return ''.join(revbytes)
76+
return six.binary_type(revbytes)

cassandra/metadata.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -779,14 +779,18 @@ def _make_option_strings(self):
779779
return list(sorted(ret))
780780

781781

782-
def protect_name(name):
783-
if isinstance(name, six.text_type):
784-
name = name.encode('utf8')
785-
return maybe_escape_name(name)
782+
if six.PY3:
783+
def protect_name(name):
784+
return maybe_escape_name(name)
785+
else:
786+
def protect_name(name):
787+
if isinstance(name, six.text_type):
788+
name = name.encode('utf8')
789+
return maybe_escape_name(name)
786790

787791

788792
def protect_names(names):
789-
return map(protect_name, names)
793+
return [protect_name(n) for n in names]
790794

791795

792796
def protect_value(value):
@@ -998,7 +1002,7 @@ def __hash__(self):
9981002
return hash(self.value)
9991003

10001004
def __repr__(self):
1001-
return "<%s: %r>" % (self.__class__.__name__, self.value)
1005+
return "<%s: %s>" % (self.__class__.__name__, self.value)
10021006
__str__ = __repr__
10031007

10041008
MIN_LONG = -(2 ** 63)
@@ -1017,7 +1021,7 @@ class Murmur3Token(Token):
10171021
@classmethod
10181022
def hash_fn(cls, key):
10191023
if murmur3 is not None:
1020-
h = murmur3(key)
1024+
h = int(murmur3(key))
10211025
return h if h != MIN_LONG else MAX_LONG
10221026
else:
10231027
raise NoMurmur3()
@@ -1034,6 +1038,8 @@ class MD5Token(Token):
10341038

10351039
@classmethod
10361040
def hash_fn(cls, key):
1041+
if isinstance(key, six.text_type):
1042+
key = key.encode('UTF-8')
10371043
return abs(varint_unpack(md5(key).digest()))
10381044

10391045
def __init__(self, token):

cassandra/policies.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
from random import randint
44
from threading import Lock
5+
import six
56

67
from cassandra import ConsistencyLevel
78

@@ -250,7 +251,7 @@ def make_query_plan(self, working_keyspace=None, query=None):
250251
for host in islice(cycle(local_live), pos, pos + len(local_live)):
251252
yield host
252253

253-
for dc, current_dc_hosts in self._dc_live_hosts.iteritems():
254+
for dc, current_dc_hosts in six.iteritems(self._dc_live_hosts):
254255
if dc == self.local_dc:
255256
continue
256257

cassandra/query.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -408,11 +408,9 @@ def __str__(self):
408408

409409
def bind_params(query, params):
410410
if isinstance(params, dict):
411-
return query % dict((k, cql_encoders.get(type(v), cql_encode_object)(v))
412-
for k, v in params.iteritems())
411+
return query % dict((k, cql_encoders.get(type(v), cql_encode_object)(v)) for k, v in six.iteritems(params))
413412
else:
414-
return query % tuple(cql_encoders.get(type(v), cql_encode_object)(v)
415-
for v in params)
413+
return query % tuple(cql_encoders.get(type(v), cql_encode_object)(v) for v in params)
416414

417415

418416
class TraceUnavailable(Exception):

0 commit comments

Comments
 (0)