Skip to content

Commit c4a2d46

Browse files
authored
Merge pull request apache#707 from datastax/PYTHON-714
add total_ordering to Time, Date, & Host
2 parents 3c25965 + c6df661 commit c4a2d46

4 files changed

Lines changed: 143 additions & 8 deletions

File tree

cassandra/metadata.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from binascii import unhexlify
1616
from bisect import bisect_right
1717
from collections import defaultdict, Mapping
18+
from functools import total_ordering
1819
from hashlib import md5
1920
from itertools import islice, cycle
2021
import json
@@ -1492,6 +1493,7 @@ def get_replicas(self, keyspace, token):
14921493
return []
14931494

14941495

1496+
@total_ordering
14951497
class Token(object):
14961498
"""
14971499
Abstract class representing a token.
@@ -1512,14 +1514,6 @@ def from_key(cls, key):
15121514
def from_string(cls, token_string):
15131515
raise NotImplementedError()
15141516

1515-
def __cmp__(self, other):
1516-
if self.value < other.value:
1517-
return -1
1518-
elif self.value == other.value:
1519-
return 0
1520-
else:
1521-
return 1
1522-
15231517
def __eq__(self, other):
15241518
return self.value == other.value
15251519

cassandra/pool.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
Connection pooling and host management.
1717
"""
1818

19+
from functools import total_ordering
1920
import logging
2021
import socket
2122
import time
@@ -41,6 +42,7 @@ class NoConnectionsAvailable(Exception):
4142
pass
4243

4344

45+
@total_ordering
4446
class Host(object):
4547
"""
4648
Represents a single Cassandra node.

cassandra/util.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from __future__ import with_statement
1616
import calendar
1717
import datetime
18+
from functools import total_ordering
1819
import random
1920
import six
2021
import uuid
@@ -861,6 +862,7 @@ def _serialize_key(self, key):
861862
long = int
862863

863864

865+
@total_ordering
864866
class Time(object):
865867
'''
866868
Idealized time, independent of day.
@@ -985,6 +987,7 @@ def __str__(self):
985987
self.second, self.nanosecond)
986988

987989

990+
@total_ordering
988991
class Date(object):
989992
'''
990993
Idealized date: year, month, day

tests/unit/test_types.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
read_stringmap, read_inet, write_inet,
3434
read_string, write_longstring)
3535
from cassandra.query import named_tuple_factory
36+
from cassandra.pool import Host
37+
from cassandra.policies import SimpleConvictionPolicy, ConvictionPolicy
38+
from cassandra.util import Date, Time
39+
from cassandra.metadata import Token
3640

3741

3842
class TypeTests(unittest.TestCase):
@@ -248,3 +252,135 @@ def test_cql_quote(self):
248252
self.assertEqual(cql_quote(u'test'), "'test'")
249253
self.assertEqual(cql_quote('test'), "'test'")
250254
self.assertEqual(cql_quote(0), '0')
255+
256+
257+
class TestOrdering(unittest.TestCase):
258+
def _check_order_consistency(self, smaller, bigger, equal=False):
259+
self.assertLessEqual(smaller, bigger)
260+
self.assertGreaterEqual(bigger, smaller)
261+
if equal:
262+
self.assertEqual(smaller, bigger)
263+
else:
264+
self.assertNotEqual(smaller, bigger)
265+
self.assertLess(smaller, bigger)
266+
self.assertGreater(bigger, smaller)
267+
268+
def _shuffle_lists(self, *args):
269+
return [item for sublist in zip(*args) for item in sublist]
270+
271+
def _check_sequence_consistency(self, ordered_sequence, equal=False):
272+
for i, el in enumerate(ordered_sequence):
273+
for previous in ordered_sequence[:i]:
274+
self._check_order_consistency(previous, el, equal)
275+
for posterior in ordered_sequence[i + 1:]:
276+
self._check_order_consistency(el, posterior, equal)
277+
278+
def test_host_order(self):
279+
"""
280+
Test Host class is ordered consistently
281+
282+
@since 3.9
283+
@jira_ticket PYTHON-714
284+
@expected_result the hosts are ordered correctly
285+
286+
@test_category data_types
287+
"""
288+
hosts = [Host(addr, SimpleConvictionPolicy) for addr in
289+
("127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.0.4")]
290+
hosts_equal = [Host(addr, SimpleConvictionPolicy) for addr in
291+
("127.0.0.1", "127.0.0.1")]
292+
hosts_equal_conviction = [Host("127.0.0.1", SimpleConvictionPolicy), Host("127.0.0.1", ConvictionPolicy)]
293+
self._check_sequence_consistency(hosts)
294+
self._check_sequence_consistency(hosts_equal, equal=True)
295+
self._check_sequence_consistency(hosts_equal_conviction, equal=True)
296+
297+
def test_date_order(self):
298+
"""
299+
Test Date class is ordered consistently
300+
301+
@since 3.9
302+
@jira_ticket PYTHON-714
303+
@expected_result the dates are ordered correctly
304+
305+
@test_category data_types
306+
"""
307+
dates_from_string = [Date("2017-01-01"), Date("2017-01-05"), Date("2017-01-09"), Date("2017-01-13")]
308+
dates_from_string_equal = [Date("2017-01-01"), Date("2017-01-01")]
309+
self._check_sequence_consistency(dates_from_string)
310+
self._check_sequence_consistency(dates_from_string_equal, equal=True)
311+
312+
date_format = "%Y-%m-%d"
313+
314+
dates_from_value = [
315+
Date((datetime.datetime.strptime(dtstr, date_format) -
316+
datetime.datetime(1970, 1, 1)).days)
317+
for dtstr in ("2017-01-02", "2017-01-06", "2017-01-10", "2017-01-14")
318+
]
319+
dates_from_value_equal = [Date(1), Date(1)]
320+
self._check_sequence_consistency(dates_from_value)
321+
self._check_sequence_consistency(dates_from_value_equal, equal=True)
322+
323+
dates_from_datetime = [Date(datetime.datetime.strptime(dtstr, date_format))
324+
for dtstr in ("2017-01-03", "2017-01-07", "2017-01-11", "2017-01-15")]
325+
dates_from_datetime_equal = [Date(datetime.datetime.strptime("2017-01-01", date_format)),
326+
Date(datetime.datetime.strptime("2017-01-01", date_format))]
327+
self._check_sequence_consistency(dates_from_datetime)
328+
self._check_sequence_consistency(dates_from_datetime_equal, equal=True)
329+
330+
dates_from_date = [
331+
Date(datetime.datetime.strptime(dtstr, date_format).date()) for dtstr in
332+
("2017-01-04", "2017-01-08", "2017-01-12", "2017-01-16")
333+
]
334+
dates_from_date_equal = [datetime.datetime.strptime(dtstr, date_format) for dtstr in
335+
("2017-01-09", "2017-01-9")]
336+
337+
self._check_sequence_consistency(dates_from_date)
338+
self._check_sequence_consistency(dates_from_date_equal, equal=True)
339+
340+
self._check_sequence_consistency(self._shuffle_lists(dates_from_string, dates_from_value,
341+
dates_from_datetime, dates_from_date))
342+
343+
def test_timer_order(self):
344+
"""
345+
Test Time class is ordered consistently
346+
347+
@since 3.9
348+
@jira_ticket PYTHON-714
349+
@expected_result the times are ordered correctly
350+
351+
@test_category data_types
352+
"""
353+
time_from_int = [Time(1000), Time(4000), Time(7000), Time(10000)]
354+
time_from_int_equal = [Time(1), Time(1)]
355+
self._check_sequence_consistency(time_from_int)
356+
self._check_sequence_consistency(time_from_int_equal, equal=True)
357+
358+
time_from_datetime = [Time(datetime.time(hour=0, minute=0, second=0, microsecond=us))
359+
for us in (2, 5, 8, 11)]
360+
time_from_datetime_equal = [Time(datetime.time(hour=0, minute=0, second=0, microsecond=us))
361+
for us in (1, 1)]
362+
self._check_sequence_consistency(time_from_datetime)
363+
self._check_sequence_consistency(time_from_datetime_equal, equal=True)
364+
365+
time_from_string = [Time("00:00:00.000003000"), Time("00:00:00.000006000"),
366+
Time("00:00:00.000009000"), Time("00:00:00.000012000")]
367+
time_from_string_equal = [Time("00:00:00.000004000"), Time("00:00:00.000004000")]
368+
self._check_sequence_consistency(time_from_string)
369+
self._check_sequence_consistency(time_from_string_equal, equal=True)
370+
371+
self._check_sequence_consistency(self._shuffle_lists(time_from_int, time_from_datetime, time_from_string))
372+
373+
def test_token_order(self):
374+
"""
375+
Test Token class is ordered consistently
376+
377+
@since 3.9
378+
@jira_ticket PYTHON-714
379+
@expected_result the tokens are ordered correctly
380+
381+
@test_category data_types
382+
"""
383+
tokens = [Token(1), Token(2), Token(3), Token(4)]
384+
tokens_equal = [Token(1), Token(1)]
385+
self._check_sequence_consistency(tokens)
386+
self._check_sequence_consistency(tokens_equal, equal=True)

0 commit comments

Comments
 (0)