You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ca...@codespot.com on 2012/01/04 01:22:29 UTC

[cassandra-dbapi2] 13 new revisions pushed by pcannon@gmail.com on 2012-01-04 00:19 GMT

13 new revisions:

Revision: e916933631f3
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Nov 15 07:21:23 2011
Log:      fix marshallers under python2.4
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=e916933631f3

Revision: 6996c9251137
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 11:51:25 2011
Log:      fix test_truncate_columnfamily...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=6996c9251137

Revision: e108e06ba267
Author:   Eric Evans <ee...@sym-link.com>
Date:     Tue Dec 13 18:16:58 2011
Log:      unittest.TestCase.skipTest is Python >= 2.7
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=e108e06ba267

Revision: 21aab4e89390
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 13 14:36:44 2011
Log:      fix overzealous named param regex...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=21aab4e89390

Revision: ac8f1dc5458d
Author:   Eric Evans <ee...@sym-link.com>
Date:     Wed Dec 14 14:45:39 2011
Log:      print number of results when assert fails
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=ac8f1dc5458d

Revision: 318469bef40d
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 13 14:56:06 2011
Log:      fix/add to test_query_preparation for last
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=318469bef40d

Revision: ef794492c0fc
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:05:00 2011
Log:      Merge branch 'master' into issue-12...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=ef794492c0fc

Revision: fe7ed9c1c4b9
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:15:46 2011
Log:      use unittest.TestCase.assertRaises...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=fe7ed9c1c4b9

Revision: 0c6559fbd400
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:50:09 2011
Log:      use unittest.TestCase.assertEqual...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=0c6559fbd400

Revision: 626f935c9d6e
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 13:28:57 2011
Log:      Merge branch 'master' into issue-11...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=626f935c9d6e

Revision: 2b2c179272ce
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 27 14:55:01 2011
Log:      Comply with ASF licensing requirements...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=2b2c179272ce

Revision: 9a3b065e6f41
Author:   paul cannon <pa...@riptano.com>
Date:     Tue Dec 27 15:48:04 2011
Log:      distribute NOTICE and LICENSE in sdist...
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=9a3b065e6f41

Revision: 350590f4501d
Author:   paul cannon <pa...@riptano.com>
Date:     Tue Dec 27 15:17:14 2011
Log:      release 1.0.7
http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=350590f4501d

==============================================================================
Revision: e916933631f3
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Nov 15 07:21:23 2011
Log:      fix marshallers under python2.4

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=e916933631f3

Modified:
  /cql/marshal.py

=======================================
--- /cql/marshal.py	Mon Nov  7 12:32:03 2011
+++ /cql/marshal.py	Tue Nov 15 07:21:23 2011
@@ -118,7 +118,7 @@
              return None
          return _float_packer.unpack(bytestr)[0]
  else:
-    def unmarshal_long(bytestr):
+    def unmarshal_float(bytestr):
          if not bytestr:
              return None
          return struct.unpack(">f", bytestr)[0]
@@ -129,7 +129,7 @@
              return None
          return _double_packer.unpack(bytestr)[0]
  else:
-    def unmarshal_long(bytestr):
+    def unmarshal_double(bytestr):
          if not bytestr:
              return None
          return struct.unpack(">d", bytestr)[0]

==============================================================================
Revision: 6996c9251137
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 11:51:25 2011
Log:      fix test_truncate_columnfamily

in order not to depend on fake-empty-row behavior, as caused by
CASSANDRA-3424 and reported by CASSANDRA-3505, since it's not yet
determined whether it will change. shouldn't matter here anyway.

Fixes issue-12.

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=6996c9251137

Modified:
  /test/test_cql.py

=======================================
--- /test/test_cql.py	Mon Nov  7 13:42:10 2011
+++ /test/test_cql.py	Thu Dec 15 11:51:25 2011
@@ -427,8 +427,10 @@
      def test_truncate_columnfamily(self):
          "truncating a column family"
          cursor = self.cursor
+        cursor.execute("SELECT * FROM StandardString1")
+        assert cursor.rowcount > 0
          cursor.execute('TRUNCATE StandardString1;')
-        cursor.execute("SELECT 'cd1' FROM StandardString1 WHERE KEY  
= 'kd'")
+        cursor.execute("SELECT * FROM StandardString1")
          assert cursor.rowcount == 0

          # truncate against non-existing CF

==============================================================================
Revision: e108e06ba267
Author:   Eric Evans <ee...@sym-link.com>
Date:     Tue Dec 13 18:16:58 2011
Log:      unittest.TestCase.skipTest is Python >= 2.7

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=e108e06ba267

Modified:
  /test/test_cql.py

=======================================
--- /test/test_cql.py	Mon Nov  7 13:42:10 2011
+++ /test/test_cql.py	Tue Dec 13 18:16:58 2011
@@ -221,7 +221,10 @@
          "retrieve a range of rows with columns"

          if self.get_partitioner().split('.')[-1] == 'RandomPartitioner':
-            self.skipTest("Key ranges don't make sense under RP")
+            # skipTest is >= Python 2.7
+            if hasattr(self, 'skipTest'):
+                self.skipTest("Key ranges don't make sense under RP")
+            else: return None

          # everything
          cursor = self.cursor
@@ -382,7 +385,10 @@
          "indexed scan with a starting key"

          if self.get_partitioner().split('.')[-1] == 'RandomPartitioner':
-            self.skipTest("Key ranges don't make sense under RP")
+            # skipTest is Python >= 2.7
+            if hasattr(self, 'skipTest'):
+                self.skipTest("Key ranges don't make sense under RP")
+            else: return None

          cursor = self.cursor
          cursor.execute("""

==============================================================================
Revision: 21aab4e89390
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 13 14:36:44 2011
Log:      fix overzealous named param regex

named params immediately preceded by identifiers or string literals will
no longer be recognized. it wouldn't make much sense to be using named
params in that way, anyway.

this solves the problem with new :-delimited columnfamily attributes in
CQL, as explained in issue-11.

remove the notion of backslash-escaping colons, since the colon is not a
valid character in CQL outside of option identifiers anyway (where it
must be immediately preceded and followed by identifier characters).

verified that other DB-API2.0 libs implementing paramstyle='named' treat
substitution markers the same way: ignore markers in string literals,
and markers immediately following identifiers or string literals.

also don't throw an error when more params are provided than requested
in the query string; this situation could occur lots of ways in practice
without it being an error. compare (str % dict) behavior.

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=21aab4e89390

Modified:
  /cql/marshal.py

=======================================
--- /cql/marshal.py	Tue Nov 15 07:21:23 2011
+++ /cql/marshal.py	Tue Dec 13 14:36:44 2011
@@ -21,7 +21,7 @@

  import cql

-__all__ = ['prepare', 'marshal', 'unmarshal_noop', 'unmarshallers']
+__all__ = ['prepare', 'cql_quote', 'unmarshal_noop', 'unmarshallers']

  if hasattr(struct, 'Struct'): # new in Python 2.5
     _have_struct = True
@@ -39,7 +39,23 @@
          def __init__(self, bytes):
              self.bytes = bytes

-_param_re =  
re.compile(r"(?<!strategy_options)(?<!\\)(:[a-zA-Z_][a-zA-Z0-9_]*)", re.M)
+_param_re = re.compile(r"""
+    (                           # stuff that is not substitution markers
+      (?:  ' [^']* '            # string literal; ignore colons in here
+        |  [^']                 # eat anything else
+      )*?
+    )
+    (?<! [a-zA-Z0-9_'] )        # no colons immediately preceded by an  
ident or str literal
+    :
+    ( [a-zA-Z_][a-zA-Z0-9_]* )  # the param name
+""", re.S | re.X)
+
+_comment_re = re.compile(r"""
+    (?:  /\* .*? \*/
+      |  // [^\n]*
+      |  -- [^\n]*
+    )
+""", re.S | re.X)

  BYTES_TYPE = "org.apache.cassandra.db.marshal.BytesType"
  ASCII_TYPE = "org.apache.cassandra.db.marshal.AsciiType"
@@ -58,15 +74,19 @@
  COUNTER_COLUMN_TYPE = "org.apache.cassandra.db.marshal.CounterColumnType"

  def prepare(query, params):
-    # For every match of the form ":param_name", call marshal
-    # on kwargs['param_name'] and replace that section of the query
-    # with the result
-    new, count = re.subn(_param_re, lambda m:  
marshal(params[m.group(1)[1:]]), query)
-    if len(params) > count:
-        raise cql.ProgrammingError("More keywords were provided than  
parameters")
-    return new.replace("\:", ":")
-
-def marshal(term):
+    """
+    For every match of the form ":param_name", call cql_quote
+    on kwargs['param_name'] and replace that section of the query
+    with the result
+    """
+
+    # kill comments first, so that we don't have to try to parse around  
them.
+    # but keep the character count the same, so that location-tagged error
+    # messages still work
+    query = _comment_re.sub(lambda m: ' ' * len(m.group(0)), query)
+    return _param_re.sub(lambda m: m.group(1) +  
cql_quote(params[m.group(2)]), query)
+
+def cql_quote(term):
      if isinstance(term, unicode):
          return "'%s'" % __escape_quotes(term.encode('utf8'))
      elif isinstance(term, str):
@@ -177,5 +197,5 @@
      return val

  def __escape_quotes(term):
-    assert isinstance(term, (str, unicode))
-    return term.replace("\'", "''")
+    assert isinstance(term, basestring)
+    return term.replace("'", "''")

==============================================================================
Revision: ac8f1dc5458d
Author:   Eric Evans <ee...@sym-link.com>
Date:     Wed Dec 14 14:45:39 2011
Log:      print number of results when assert fails

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=ac8f1dc5458d

Modified:
  /test/test_cql.py

=======================================
--- /test/test_cql.py	Tue Dec 13 18:16:58 2011
+++ /test/test_cql.py	Wed Dec 14 14:45:39 2011
@@ -435,7 +435,8 @@
          cursor = self.cursor
          cursor.execute('TRUNCATE StandardString1;')
          cursor.execute("SELECT 'cd1' FROM StandardString1 WHERE KEY  
= 'kd'")
-        assert cursor.rowcount == 0
+        assert cursor.rowcount == 0, \
+            "expected empty resultset, got %d rows" % cursor.rowcount

          # truncate against non-existing CF
          assert_raises(cql.ProgrammingError,

==============================================================================
Revision: 318469bef40d
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 13 14:56:06 2011
Log:      fix/add to test_query_preparation for last

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=318469bef40d

Modified:
  /test/test_query_preparation.py

=======================================
--- /test/test_query_preparation.py	Wed Aug 24 11:18:52 2011
+++ /test/test_query_preparation.py	Tue Dec 13 14:56:06 2011
@@ -30,12 +30,24 @@
  """
  SELECT :a..:b FROM ColumnFamily;
  """,
+"""
+CREATE KEYSPACE foo WITH strategy_class='SimpleStrategy' AND  
strategy_options:replication_factor = :_a_;
+""",
+"""
+CREATE COLUMNFAMILY blah WITH somearg:another=:opt AND foo='bar':baz AND  
option=:value:suffix;
+""",
+"""
+SELECT :lo..:hi FROM ColumnFamily WHERE KEY=':dontsubstthis' AND col > /*  
ignore :this */ :colval23;
+""",
  )

  ARGUMENTS = (
      {'a': 1, 'b': 3, 'c': long(1000), 'd': long(3000), 'e': "key", 'f':  
unicode("val")},
      {},
      {'a': "a'b", 'b': "c'd'e"},
+    {'_a_': 12},
+    {'opt': "abc'", 'unused': 'thatsok', 'value': '\n'},
+    {'lo': ' ', 'hi': ':hi', 'colval23': 0.2},
  )

  STANDARDS = (
@@ -48,18 +60,25 @@
  """
  SELECT 'a''b'..'c''d''e' FROM ColumnFamily;
  """,
+"""
+CREATE KEYSPACE foo WITH strategy_class='SimpleStrategy' AND  
strategy_options:replication_factor = 12;
+""",
+"""
+CREATE COLUMNFAMILY blah WITH somearg:another='abc''' AND foo='bar':baz  
AND option='
+':suffix;
+""",
+"""
+SELECT ' '..':hi' FROM ColumnFamily WHERE KEY=':dontsubstthis' AND col  
>                    0.2;
+""",
  )

  class TestPrepare(unittest.TestCase):
      def test_prepares(self):
          "test prepared queries against known standards"
-        for (i, test) in enumerate(TESTS):
-            a = prepare(test, ARGUMENTS[i])
-            b = STANDARDS[i]
-            assert a == b, "\n%s !=\n%s" % (a, b)
+        for test, args, standard in zip(TESTS, ARGUMENTS, STANDARDS):
+            prepared = prepare(test, args)
+            self.assertEqual(prepared, standard)

      def test_bad(self):
          "ensure bad calls raise exceptions"
          self.assertRaises(KeyError, prepare, ":a :b", {'a': 1})
-        self.assertRaises(cql.ProgrammingError, prepare, ":a :b", {'a':  
1, 'b': 2, 'c': 3})
-        self.assertRaises(cql.ProgrammingError, prepare, "none", {'a': 1})

==============================================================================
Revision: ef794492c0fc
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:05:00 2011
Log:      Merge branch 'master' into issue-12

Conflicts:
	test/test_cql.py

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=ef794492c0fc

Modified:
  /test/test_cql.py

=======================================
--- /test/test_cql.py	Thu Dec 15 11:51:25 2011
+++ /test/test_cql.py	Thu Dec 15 12:05:00 2011
@@ -221,7 +221,10 @@
          "retrieve a range of rows with columns"

          if self.get_partitioner().split('.')[-1] == 'RandomPartitioner':
-            self.skipTest("Key ranges don't make sense under RP")
+            # skipTest is >= Python 2.7
+            if hasattr(self, 'skipTest'):
+                self.skipTest("Key ranges don't make sense under RP")
+            else: return None

          # everything
          cursor = self.cursor
@@ -382,7 +385,10 @@
          "indexed scan with a starting key"

          if self.get_partitioner().split('.')[-1] == 'RandomPartitioner':
-            self.skipTest("Key ranges don't make sense under RP")
+            # skipTest is Python >= 2.7
+            if hasattr(self, 'skipTest'):
+                self.skipTest("Key ranges don't make sense under RP")
+            else: return None

          cursor = self.cursor
          cursor.execute("""
@@ -431,7 +437,8 @@
          assert cursor.rowcount > 0
          cursor.execute('TRUNCATE StandardString1;')
          cursor.execute("SELECT * FROM StandardString1")
-        assert cursor.rowcount == 0
+        assert cursor.rowcount == 0, \
+            "expected empty resultset, got %d rows" % cursor.rowcount

          # truncate against non-existing CF
          assert_raises(cql.ProgrammingError,

==============================================================================
Revision: fe7ed9c1c4b9
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:15:46 2011
Log:      use unittest.TestCase.assertRaises

instead of assert_raises, because no need to duplicate code.

also, in case we decide to require py2.5 (at least for running tests),
it allows a bit of extra flexibility and expressibility if used as a
context object, and allows postinspection of the exception

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=fe7ed9c1c4b9

Modified:
  /test/test_cql.py

=======================================
--- /test/test_cql.py	Thu Dec 15 12:05:00 2011
+++ /test/test_cql.py	Thu Dec 15 12:15:46 2011
@@ -51,13 +51,6 @@
      return client
  thrift_client = get_thrift_client()

-def assert_raises(exception, method, *args, **kwargs):
-    try:
-        method(*args, **kwargs)
-    except exception:
-        return
-    raise AssertionError("failed to see expected exception")
-
  def uuid1bytes_to_millis(uuidbytes):
      return (uuid.UUID(bytes=uuidbytes).get_time() / 10000) -  
12219292800000L

@@ -420,15 +413,15 @@
          assert r[0] == 7, "expected 7 results, got %d" % (r and r or 0)

          # count(*) and count(1) are only supported operations
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT COUNT(name) FROM StandardLongA")
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT COUNT(1..2) FROM StandardLongA")
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT COUNT(1, 2, 3) FROM StandardLongA")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT COUNT(name) FROM StandardLongA")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT COUNT(1..2) FROM StandardLongA")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT COUNT(1, 2, 3) FROM StandardLongA")

      def test_truncate_columnfamily(self):
          "truncating a column family"
@@ -441,9 +434,9 @@
              "expected empty resultset, got %d rows" % cursor.rowcount

          # truncate against non-existing CF
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "TRUNCATE notExistingCFAAAABB")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "TRUNCATE notExistingCFAAAABB")

      def test_delete_columns(self):
          "delete columns from a row"
@@ -542,9 +535,9 @@

          # Technically this should throw a ttypes.NotFound(), but this is
          # temporary and so not worth requiring it on PYTHONPATH.
-        assert_raises(Exception,
-                      thrift_client.describe_keyspace,
-                      "Keyspace4Drop")
+        self.assertRaises(Exception,
+                          thrift_client.describe_keyspace,
+                          "Keyspace4Drop")

      def test_create_column_family(self):
          "create a new column family"
@@ -578,16 +571,16 @@
          assert cfam.key_validation_class  
== "org.apache.cassandra.db.marshal.IntegerType"

          # Missing primary key
-        assert_raises(cql.ProgrammingError, cursor.execute, "CREATE  
COLUMNFAMILY NewCf2")
+        self.assertRaises(cql.ProgrammingError, cursor.execute, "CREATE  
COLUMNFAMILY NewCf2")

          # column name should not match key alias
-        assert_raises(cql.ProgrammingError, cursor.execute, "CREATE  
COLUMNFAMILY NewCf2 (id 'utf8' primary key, id bigint)")
+        self.assertRaises(cql.ProgrammingError, cursor.execute, "CREATE  
COLUMNFAMILY NewCf2 (id 'utf8' primary key, id bigint)")

          # Too many primary keys
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      """CREATE COLUMNFAMILY NewCf2
-                             (KEY varint PRIMARY KEY, KEY text PRIMARY  
KEY)""")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          """CREATE COLUMNFAMILY NewCf2
+                                 (KEY varint PRIMARY KEY, KEY text PRIMARY  
KEY)""")

          # No column defs
          cursor.execute("""CREATE COLUMNFAMILY NewCf3
@@ -650,9 +643,9 @@
          assert stuff.index_type == 0, "missing index"

          # already indexed
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "CREATE INDEX ON CreateIndex1 (stuff)")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "CREATE INDEX ON CreateIndex1 (stuff)")

      def test_drop_indexes(self):
          "droping indexes on columns"
@@ -678,9 +671,9 @@
          assert columns[0].index_type == None
          assert columns[0].index_name == None

-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "DROP INDEX undefIndex")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "DROP INDEX undefIndex")

      def test_time_uuid(self):
          "store and retrieve time-based (type 1) uuids"
@@ -874,16 +867,16 @@
          # Bad writes.

          # Too many column values
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "INSERT INTO StandardUtf82 (KEY, :c1) VALUES  
(:key, :v1, :v2)",
-                      dict(c1="name1", key="key0", v1="value1",  
v2="value2"))
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "INSERT INTO StandardUtf82 (KEY, :c1) VALUES  
(:key, :v1, :v2)",
+                          dict(c1="name1", key="key0", v1="value1",  
v2="value2"))

          # Too many column names, (not enough column values)
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "INSERT INTO StandardUtf82 (KEY, :c1, :c2) VALUES  
(:key, :v1)",
-                      dict(c1="name1", c2="name2", key="key0",  
v1="value1"))
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "INSERT INTO StandardUtf82 (KEY, :c1, :c2)  
VALUES (:key, :v1)",
+                          dict(c1="name1", c2="name2", key="key0",  
v1="value1"))

      def test_compression_disabled(self):
          "reading and writing w/ compression disabled"
@@ -953,31 +946,33 @@
          """)

          # BATCH should not allow setting individual timestamp when global  
timestamp is set
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      """
-                        BEGIN BATCH USING TIMESTAMP 1303743619771456
-                          UPDATE USING TIMESTAMP 1303743619771318  
StandardString1 SET name = 'name here' WHERE KEY = 'TimestampedUser4'
-                        APPLY BATCH
-                      """)
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          """
+                            BEGIN BATCH USING TIMESTAMP 1303743619771456
+                              UPDATE USING TIMESTAMP 1303743619771318  
StandardString1
+                                     SET name = 'name here'
+                                     WHERE KEY = 'TimestampedUser4'
+                            APPLY BATCH
+                          """)

          # BATCH should not allow setting global TTL
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      """
-                        BEGIN BATCH USING TTL 130374
-                          UPDATE StandardString1 SET name = 'name here'  
WHERE KEY = 'TimestampedUser4'
-                        APPLY BATCH
-                      """)
-
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      """
-                      BEGIN BATCH USING CONSISTENCY ONE
-                          UPDATE USING CONSISTENCY QUORUM StandardString1  
SET 'name' = 'value' WHERE KEY = 'bKey4'
-                          DELETE 'name' FROM StandardString1 WHERE KEY  
= 'bKey4'
-                      APPLY BATCH
-                      """)
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          """
+                            BEGIN BATCH USING TTL 130374
+                              UPDATE StandardString1 SET name = 'name  
here' WHERE KEY = 'TimestampedUser4'
+                            APPLY BATCH
+                          """)
+
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          """
+                          BEGIN BATCH USING CONSISTENCY ONE
+                              UPDATE USING CONSISTENCY QUORUM  
StandardString1 SET 'name' = 'value' WHERE KEY = 'bKey4'
+                              DELETE 'name' FROM StandardString1 WHERE KEY  
= 'bKey4'
+                          APPLY BATCH
+                          """)

      def test_multiple_keys_on_select_and_update(self):
          "select/update statements should support multiple keys by KEY IN  
construction"
@@ -1010,9 +1005,9 @@
          assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount

          # select with different KEYs AND'ed
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT * FROM StandardString1 WHERE KEY = 'mUser1'  
AND KEY = 'mUser2'")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT * FROM StandardString1 WHERE KEY  
= 'mUser1' AND KEY = 'mUser2'")

          # select with same KEY repeated in IN
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY IN  
('mUser1', 'mUser1')")
@@ -1282,9 +1277,9 @@
          assert columns[0].validation_class  
== 'org.apache.cassandra.db.marshal.AsciiType'

          # alter column with unknown validator
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "ALTER COLUMNFAMILY NewCf1 ADD name utf8")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "ALTER COLUMNFAMILY NewCf1 ADD name utf8")

          # testing 'drop an existing column'
          cursor.execute("ALTER COLUMNFAMILY NewCf1 DROP name")
@@ -1297,24 +1292,24 @@
          assert len(columns) == 0

          # add column with unknown validator
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "ALTER COLUMNFAMILY NewCf1 ADD name utf8")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "ALTER COLUMNFAMILY NewCf1 ADD name utf8")

          # alter not existing column
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "ALTER COLUMNFAMILY NewCf1 ALTER name TYPE uuid")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "ALTER COLUMNFAMILY NewCf1 ALTER name TYPE uuid")

          # drop not existing column
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "ALTER COLUMNFAMILY NewCf1 DROP name")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "ALTER COLUMNFAMILY NewCf1 DROP name")

          # should raise error when column name equals key alias
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "ALTER COLUMNFAMILY NewCf1 ADD id_key utf8")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "ALTER COLUMNFAMILY NewCf1 ADD id_key utf8")


      def test_counter_column_support(self):
@@ -1381,19 +1376,19 @@
          assert len(r) == 1

          # can't mix counter and normal statements
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "UPDATE CounterCF SET count_me = count_me + 2, x  
= 'a' WHERE key = 'counter1'")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "UPDATE CounterCF SET count_me = count_me + 2, x  
= 'a' WHERE key = 'counter1'")

          # column names must match
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "UPDATE CounterCF SET count_me = count_not_me + 2  
WHERE key = 'counter1'")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "UPDATE CounterCF SET count_me = count_not_me +  
2 WHERE key = 'counter1'")

          # counters can't do ANY
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "UPDATE CounterCF USING CONSISTENCY ANY SET count_me  
= count_me + 2 WHERE key = 'counter1'")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "UPDATE CounterCF USING CONSISTENCY ANY SET  
count_me = count_me + 2 WHERE key = 'counter1'")

      def test_key_alias_support(self):
          "should be possible to use alias instead of KEY keyword"
@@ -1459,25 +1454,25 @@
          assert r[0] == 2, "expected id = 2, got %d" % r[0]

          # if alias was set you can't use KEY keyword anymore
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "INSERT INTO KeyAliasCF (KEY, username) VALUES (6,  
jbellis)")
-
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "UPDATE KeyAliasCF SET username = 'xedin' WHERE KEY  
= 7")
-
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "DELETE FROM KeyAliasCF WHERE KEY = 2")
-
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT * FROM KeyAliasCF WHERE KEY = 2")
-
-        assert_raises(cql.ProgrammingError,
-                      cursor.execute,
-                      "SELECT * FROM KeyAliasCF WHERE KEY IN (1, 2)")
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "INSERT INTO KeyAliasCF (KEY, username) VALUES  
(6, jbellis)")
+
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "UPDATE KeyAliasCF SET username = 'xedin' WHERE  
KEY = 7")
+
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "DELETE FROM KeyAliasCF WHERE KEY = 2")
+
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT * FROM KeyAliasCF WHERE KEY = 2")
+
+        self.assertRaises(cql.ProgrammingError,
+                          cursor.execute,
+                          "SELECT * FROM KeyAliasCF WHERE KEY IN (1, 2)")

          cursor.execute("USE " + self.keyspace)
          cursor.execute("DROP KEYSPACE KeyAliasKeyspace")

==============================================================================
Revision: 0c6559fbd400
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 12:50:09 2011
Log:      use unittest.TestCase.assertEqual

instead of bare "assert a == b, 'redundant message about how a != b'"

assertEqual will provide an appropriate message describing both values
when they're not equal, so that saves a lot of redundancy and makes
tests more clear.

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=0c6559fbd400

Modified:
  /test/test_cql.py
  /test/test_query_compression.py
  /test/test_query_preparation.py

=======================================
--- /test/test_cql.py	Thu Dec 15 12:15:46 2011
+++ /test/test_cql.py	Thu Dec 15 12:50:09 2011
@@ -192,11 +192,11 @@
          r = cursor.fetchone()
          d = cursor.description

-        assert d[0][0] == 'KEY'
-        assert r[0] == 'ka'
-
-        assert d[1][0] == 'ca1'
-        assert r[1] == 'va1'
+        self.assertEqual(d[0][0], 'KEY')
+        self.assertEqual(r[0], 'ka')
+
+        self.assertEqual(d[1][0], 'ca1')
+        self.assertEqual(r[1], 'va1')

          # retrieve multiple columns
          # (we deliberately request columns in non-comparator order)
@@ -205,10 +205,10 @@
          """)

          d = cursor.description
-        assert ['ca1', 'col', 'cd1'] == [col_dscptn[0] for col_dscptn in  
d], d
+        self.assertEqual(['ca1', 'col', 'cd1'], [col_dscptn[0] for  
col_dscptn in d])
          row = cursor.fetchone()
          # check that the column that didn't exist in the row comes back as  
null
-        assert [None, 'val', 'vd1'] == row, row
+        self.assertEqual([None, 'val', 'vd1'], row)

      def test_select_row_range(self):
          "retrieve a range of rows with columns"
@@ -223,64 +223,64 @@
          cursor = self.cursor
          cursor.execute("SELECT * FROM StandardLongA")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'] == keys, keys
+        self.assertEqual(['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'], keys)

          # [start, end], mid-row
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY >= 'ad' AND  
KEY <= 'ag'")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['ad', 'ae', 'af', 'ag'] == keys, keys
+        self.assertEqual(['ad', 'ae', 'af', 'ag'], keys)

          # (start, end), mid-row
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'ad' AND  
KEY < 'ag'")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['ae', 'af'] == keys, keys
+        self.assertEqual(['ae', 'af'], keys)

          # [start, end], full-row
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY >= 'aa' AND  
KEY <= 'ag'")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'] == keys, keys
+        self.assertEqual(['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'], keys)

          # (start, end), full-row
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'a' AND  
KEY < 'g'")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'] == keys, keys
+        self.assertEqual(['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag'], keys)

          # LIMIT tests

          # no WHERE
          cursor.execute("SELECT * FROM StandardLongA LIMIT 1")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa'] == keys, keys
+        self.assertEqual(['aa'], keys)

          # with >=, non-existing key
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY >= 'a' LIMIT  
1")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa'] == keys, keys
+        self.assertEqual(['aa'], keys)

          # with >=, existing key
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY >= 'aa'  
LIMIT 1")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa'] == keys, keys
+        self.assertEqual(['aa'], keys)

          # with >, non-existing key
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'a' LIMIT  
1")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa'] == keys, keys
+        self.assertEqual(['aa'], keys)

          # with >, existing key
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'aa' LIMIT  
1")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['ab'] == keys, keys
+        self.assertEqual(['ab'], keys)

          # with both > and <, existing keys
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'aa' and  
KEY < 'ag' LIMIT 5")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['ab', 'ac', 'ad', 'ae', 'af'] == keys, keys
+        self.assertEqual(['ab', 'ac', 'ad', 'ae', 'af'], keys)

          # with both > and <, non-existing keys
          cursor.execute("SELECT * FROM StandardLongA WHERE KEY > 'a' and  
KEY < 'b' LIMIT 5")
          keys = [row[0] for row in cursor.fetchall()]
-        assert ['aa', 'ab', 'ac', 'ad', 'ae'] == keys, keys
+        self.assertEqual(['aa', 'ab', 'ac', 'ad', 'ae'], keys)

      def test_select_columns_slice(self):
          "column slice tests"
@@ -289,29 +289,29 @@
          # * includes row key, explicit slice does not
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'ka';")
          row = cursor.fetchone()
-        assert ['ka', 'va1', 'val'] == row, row
+        self.assertEqual(['ka', 'va1', 'val'], row)

          cursor.execute("SELECT ''..'' FROM StandardString1 WHERE KEY  
= 'ka';")
          row = cursor.fetchone()
-        assert ['va1', 'val'] == row, row
+        self.assertEqual(['va1', 'val'], row)

          # column subsets
          cursor.execute("SELECT 1..3 FROM StandardLongA WHERE KEY = 'aa';")
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          row = cursor.fetchone()
-        assert ['1', '2', '3'] == row, row
+        self.assertEqual(['1', '2', '3'], row)

          # range of columns (slice) by row with FIRST
          cursor.execute("SELECT FIRST 1 1..3 FROM StandardLongA WHERE KEY  
= 'aa'")
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          row = cursor.fetchone()
-        assert ['1'] == row, row
+        self.assertEqual(['1'], row)

          # range of columns (slice) by row reversed
          cursor.execute("SELECT FIRST 2 REVERSED 3..1 FROM StandardLongA  
WHERE KEY = 'aa'")
-        assert cursor.rowcount == 1, "%d != 1" % cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          row = cursor.fetchone()
-        assert ['3', '2'] == row, row
+        self.assertEqual(['3', '2'], row)


      def test_select_range_with_single_column_results(self):
@@ -329,7 +329,7 @@
            SELECT KEY, name FROM StandardString2
          """)

-        assert cursor.rowcount == 3, "expected 3 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 3, msg="expected 3 results,  
got %d" % cursor.rowcount)

          # if using RP, these won't be sorted, so we'll sort. other tests  
take care of
          # checking sorted-ness under non-RP partitioners anyway.
@@ -338,14 +338,14 @@
          # two of three results should contain one column "name", third  
should be empty
          for i in range(1, 3):
              r = rows[i - 1]
-            assert len(r) == 2
-            assert r[0] == "user%d" % i, r
-            assert r[1] == "%s" % i, r
+            self.assertEqual(len(r), 2)
+            self.assertEqual(r[0], "user%d" % i)
+            self.assertEqual(r[1], "%s" % i)

          r = rows[2]
-        assert len(r) == 2
-        assert r[0] == "user3"
-        assert r[1] == None
+        self.assertEqual(len(r), 2, msg='r is %r, but expected length 2' %  
(r,))
+        self.assertEqual(r[0], "user3")
+        self.assertEqual(r[1], None)

      def test_index_scan_equality(self):
          "indexed scan where column equals value"
@@ -353,15 +353,15 @@
          cursor.execute("""
              SELECT KEY, birthdate FROM IndexedA WHERE birthdate = 100
          """)
-        assert cursor.rowcount == 2
+        self.assertEqual(cursor.rowcount, 2)

          r = cursor.fetchone()
-        assert r[0] == "asmith"
-        assert len(r) == 2
+        self.assertEqual(r[0], "asmith")
+        self.assertEqual(len(r), 2, msg='r is %r, but expected length 2' %  
(r,))

          r = cursor.fetchone()
-        assert r[0] == "dozer"
-        assert len(r) == 2
+        self.assertEqual(r[0], "dozer")
+        self.assertEqual(len(r), 2, msg='r is %r, but expected length 2' %  
(r,))

      def test_index_scan_greater_than(self):
          "indexed scan where a column is greater than a value"
@@ -370,9 +370,9 @@
              SELECT KEY, 'birthdate' FROM IndexedA
              WHERE 'birthdate' = 100 AND 'unindexed' > 200
          """)
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          row = cursor.fetchone()
-        assert row[0] == "asmith", row
+        self.assertEqual(row[0], "asmith")

      def test_index_scan_with_start_key(self):
          "indexed scan with a starting key"
@@ -388,29 +388,29 @@
              SELECT KEY, 'birthdate' FROM IndexedA
              WHERE 'birthdate' = 100 AND KEY >= 'asmithZ'
          """)
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          r = cursor.fetchone()
-        assert r[0] == "dozer"
+        self.assertEqual(r[0], "dozer")

      def test_no_where_clause(self):
          "empty where clause (range query w/o start key)"
          cursor = self.cursor
          cursor.execute("SELECT KEY, 'col' FROM StandardString1 LIMIT 3")
-        assert cursor.rowcount == 3
+        self.assertEqual(cursor.rowcount, 3)
          rows = sorted(cursor.fetchmany(3))
-        assert rows[0][0] == "ka"
-        assert rows[1][0] == "kb"
-        assert rows[2][0] == "kc"
+        self.assertEqual(rows[0][0], "ka")
+        self.assertEqual(rows[1][0], "kb")
+        self.assertEqual(rows[2][0], "kc")

      def test_column_count(self):
          "getting a result count instead of results"
          cursor = self.cursor
          cursor.execute("SELECT COUNT(*) FROM StandardLongA")
          r = cursor.fetchone()
-        assert r[0] == 7, "expected 7 results, got %d" % (r and r or 0)
+        self.assertEqual(r[0], 7)
          cursor.execute("SELECT COUNT(1) FROM StandardLongA")
          r = cursor.fetchone()
-        assert r[0] == 7, "expected 7 results, got %d" % (r and r or 0)
+        self.assertEqual(r[0], 7)

          # count(*) and count(1) are only supported operations
          self.assertRaises(cql.ProgrammingError,
@@ -430,8 +430,7 @@
          assert cursor.rowcount > 0
          cursor.execute('TRUNCATE StandardString1;')
          cursor.execute("SELECT * FROM StandardString1")
-        assert cursor.rowcount == 0, \
-            "expected empty resultset, got %d rows" % cursor.rowcount
+        self.assertEqual(cursor.rowcount, 0)

          # truncate against non-existing CF
          self.assertRaises(cql.ProgrammingError,
@@ -445,7 +444,7 @@
              SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
          """)
          desc = [col_d[0] for col_d in cursor.description]
-        assert ['cd1', 'col'] == desc, desc
+        self.assertEqual(['cd1', 'col'], desc)

          cursor.execute("""
              DELETE 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
@@ -454,7 +453,7 @@
              SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
          """)
          row = cursor.fetchone()
-        assert [None, None] == row, row
+        self.assertEqual([None, None], row)

      def test_delete_columns_multi_rows(self):
          "delete columns from multiple rows"
@@ -463,10 +462,10 @@
          # verify rows exist initially
          cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY  
= 'kc'")
          row = cursor.fetchone()
-        assert ['val'] == row, row
+        self.assertEqual(['val'], row)
          cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY  
= 'kd'")
          row = cursor.fetchone()
-        assert ['val'] == row, row
+        self.assertEqual(['val'], row)

          # delete and verify data is gone
          cursor.execute("""
@@ -474,10 +473,10 @@
          """)
          cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY  
= 'kc'")
          row = cursor.fetchone()
-        assert [None] == row, row
+        self.assertEqual([None], row)
          cursor.execute("SELECT 'col' FROM StandardString1 WHERE KEY  
= 'kd'")
          r = cursor.fetchone()
-        assert [None] == r, r
+        self.assertEqual([None], r)

      def test_delete_rows(self):
          "delete entire rows"
@@ -485,13 +484,13 @@
          cursor.execute("""
              SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
          """)
-        assert ['cd1', 'col'] == [col_d[0] for col_d in cursor.description]
+        self.assertEqual(['cd1', 'col'], [col_d[0] for col_d in  
cursor.description])
          cursor.execute("DELETE FROM StandardString1 WHERE KEY = 'kd'")
          cursor.execute("""
              SELECT 'cd1', 'col' FROM StandardString1 WHERE KEY = 'kd'
          """)
          row = cursor.fetchone()
-        assert [None, None] == row, row
+        self.assertEqual([None, None], row)

      def test_create_keyspace(self):
          "create a new keyspace"
@@ -510,15 +509,15 @@
          ksdef = thrift_client.describe_keyspace("TestKeyspace42")

          strategy_class  
= "org.apache.cassandra.locator.NetworkTopologyStrategy"
-        assert ksdef.strategy_class == strategy_class
-        assert ksdef.strategy_options['DC1'] == "1"
+        self.assertEqual(ksdef.strategy_class, strategy_class)
+        self.assertEqual(ksdef.strategy_options['DC1'], "1")

          ksdef = thrift_client.describe_keyspace("TestKeyspace43")

          strategy_class  
= "org.apache.cassandra.locator.NetworkTopologyStrategy"
-        assert ksdef.strategy_class == strategy_class
-        assert ksdef.strategy_options['1'] == '2'
-        assert ksdef.strategy_options['2'] == '3'
+        self.assertEqual(ksdef.strategy_class, strategy_class)
+        self.assertEqual(ksdef.strategy_options['1'], '2')
+        self.assertEqual(ksdef.strategy_options['2'], '3')

      def test_drop_keyspace(self):
          "removing a keyspace"
@@ -560,15 +559,13 @@

          # TODO: temporary (until this can be done with CQL).
          ksdef = thrift_client.describe_keyspace("CreateCFKeyspace")
-        assert len(ksdef.cf_defs) == 1, \
-            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 1)
          cfam= ksdef.cf_defs[0]
-        assert len(cfam.column_metadata) == 4, \
-            "expected 4 columns, found %d" % len(cfam.column_metadata)
-        assert cfam.comment == "shiny, new, cf"
-        assert cfam.default_validation_class  
== "org.apache.cassandra.db.marshal.AsciiType"
-        assert cfam.comparator_type  
== "org.apache.cassandra.db.marshal.UTF8Type"
-        assert cfam.key_validation_class  
== "org.apache.cassandra.db.marshal.IntegerType"
+        self.assertEqual(len(cfam.column_metadata), 4)
+        self.assertEqual(cfam.comment, "shiny, new, cf")
+         
self.assertEqual(cfam.default_validation_class, "org.apache.cassandra.db.marshal.AsciiType")
+         
self.assertEqual(cfam.comparator_type, "org.apache.cassandra.db.marshal.UTF8Type")
+         
self.assertEqual(cfam.key_validation_class, "org.apache.cassandra.db.marshal.IntegerType")

          # Missing primary key
          self.assertRaises(cql.ProgrammingError, cursor.execute, "CREATE  
COLUMNFAMILY NewCf2")
@@ -586,21 +583,18 @@
          cursor.execute("""CREATE COLUMNFAMILY NewCf3
                              (KEY varint PRIMARY KEY) WITH comparator =  
bigint""")
          ksdef = thrift_client.describe_keyspace("CreateCFKeyspace")
-        assert len(ksdef.cf_defs) == 2, \
-            "expected 3 column families total, found %d" %  
len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 2)
          cfam = [i for i in ksdef.cf_defs if i.name == "NewCf3"][0]
-        assert cfam.comparator_type  
== "org.apache.cassandra.db.marshal.LongType"
+         
self.assertEqual(cfam.comparator_type, "org.apache.cassandra.db.marshal.LongType")

          # Column defs, defaults otherwise
          cursor.execute("""CREATE COLUMNFAMILY NewCf4
                              (KEY varint PRIMARY KEY, 'a' varint, 'b'  
varint)
                              WITH comparator = text;""")
          ksdef = thrift_client.describe_keyspace("CreateCFKeyspace")
-        assert len(ksdef.cf_defs) == 3, \
-            "expected 4 column families total, found %d" %  
len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 3)
          cfam = [i for i in ksdef.cf_defs if i.name == "NewCf4"][0]
-        assert len(cfam.column_metadata) == 2, \
-            "expected 2 columns, found %d" % len(cfam.column_metadata)
+        self.assertEqual(len(cfam.column_metadata), 2)
          for coldef in cfam.column_metadata:
              assert coldef.name in ("a", "b"), "Unknown column name " +  
coldef.name
              assert coldef.validation_class.endswith("marshal.IntegerType")
@@ -637,10 +631,9 @@
          cfam = [i for i in ksdef.cf_defs if i.name == "CreateIndex1"][0]
          items = [i for i in cfam.column_metadata if i.name == "items"][0]
          stuff = [i for i in cfam.column_metadata if i.name == "stuff"][0]
-        assert items.index_name == "namedIndex", items.index_name
-        assert items.index_type == 0, "missing index"
-        assert stuff.index_name != None, "index_name should be set"
-        assert stuff.index_type == 0, "missing index"
+        self.assertEqual(items.index_name, "namedIndex")
+        self.assertEqual(items.index_type, 0, msg="missing index")
+        self.assertNotEqual(stuff.index_name, None, msg="index_name should  
be set")

          # already indexed
          self.assertRaises(cql.ProgrammingError,
@@ -659,8 +652,8 @@
          ksdef = thrift_client.describe_keyspace("DropIndexTests")
          columns = ksdef.cf_defs[0].column_metadata

-        assert columns[0].index_name == "namedIndex"
-        assert columns[0].index_type == 0
+        self.assertEqual(columns[0].index_name, "namedIndex")
+        self.assertEqual(columns[0].index_type, 0)

          # testing "DROP INDEX <INDEX_NAME>"
          cursor.execute("DROP INDEX namedIndex")
@@ -668,8 +661,8 @@
          ksdef = thrift_client.describe_keyspace("DropIndexTests")
          columns = ksdef.cf_defs[0].column_metadata

-        assert columns[0].index_type == None
-        assert columns[0].index_name == None
+        self.assertEqual(columns[0].index_type, None)
+        self.assertEqual(columns[0].index_name, None)

          self.assertRaises(cql.ProgrammingError,
                            cursor.execute,
@@ -689,7 +682,7 @@
              SELECT '%s' FROM StandardTimeUUID WHERE KEY = 'uuidtest'
          """ % str(timeuuid))
          d = cursor.description
-        assert d[0][0] == timeuuid, "%s, %s" % (str(d[1][0]),  
str(timeuuid))
+        self.assertEqual(d[0][0], timeuuid)

          # Tests a node-side conversion from bigint to UUID.
          ms = uuid1bytes_to_millis(uuid.uuid1().bytes)
@@ -701,7 +694,7 @@
              SELECT 'id' FROM StandardTimeUUIDValues WHERE KEY = 'uuidtest'
          """)
          r = cursor.fetchone()
-        assert uuid1bytes_to_millis(r[0].bytes) == ms
+        self.assertEqual(uuid1bytes_to_millis(r[0].bytes), ms)

          # Tests a node-side conversion from ISO8601 to UUID.
          cursor.execute("""
@@ -715,8 +708,7 @@
          # 2011-01-31 17:00:00-0000 == 1296493200000ms
          r = cursor.fetchone()
          ms = uuid1bytes_to_millis(r[0].bytes)
-        assert ms == 1296493200000, \
-                "%d != 1296493200000 (2011-01-31 17:00:00-0000)" % ms
+        self.assertEqual(ms, 1296493200000, msg="%d != 1296493200000  
(2011-01-31 17:00:00-0000)" % ms)

          # Tests node-side conversion of timeuuid("now") to UUID
          cursor.execute("""
@@ -743,7 +735,7 @@
              """, dict(start=uuid_range[0],  
finish=uuid_range[len(uuid_range)-1]))
          d = cursor.description
          for (i, col_d) in enumerate(d):
-            assert uuid_range[i] == col_d[0]
+            self.assertEqual(uuid_range[i], col_d[0])


      def test_lexical_uuid(self):
@@ -756,8 +748,7 @@
          cursor.execute("SELECT :name FROM StandardUUID WHERE KEY  
= 'uuidtest'",
                         dict(name=uid))
          d = cursor.description
-        assert d[0][0] == uid, "expected %s, got %s (%s)" % \
-                (uid.bytes.encode('hex'), str(d[1][0]).encode('hex'),  
d[1][1])
+        self.assertEqual(d[0][0], uid, msg="expected %s, got %s (%s)" %  
(uid, d[0][0], d[0][1]))

          # TODO: slices of uuids from cf w/ LexicalUUIDType comparator

@@ -772,19 +763,19 @@

          cursor.execute("SELECT * FROM StandardUtf82 WHERE KEY = k1")
          d = cursor.description
-        assert d[0][0] == 'KEY', d[0][0]
-        assert d[1][0] == u"¢", d[1][0]
-        assert d[2][0] == u"©", d[2][0]
-        assert d[3][0] == u"®", d[3][0]
-        assert d[4][0] == u"¿", d[4][0]
+        self.assertEqual(d[0][0], 'KEY')
+        self.assertEqual(d[1][0], u"¢")
+        self.assertEqual(d[2][0], u"©")
+        self.assertEqual(d[3][0], u"®")
+        self.assertEqual(d[4][0], u"¿")

          cursor.execute("SELECT :start..'' FROM StandardUtf82 WHERE KEY =  
k1", dict(start="©"))
          row = cursor.fetchone()
-        assert len(row) == 3, row
+        self.assertEqual(len(row), 3, msg='expected length 3, but  
got %r' % (row,))
          d = cursor.description
-        assert d[0][0] == u"©"
-        assert d[1][0] == u"®"
-        assert d[2][0] == u"¿"
+        self.assertEqual(d[0][0], u"©")
+        self.assertEqual(d[1][0], u"®")
+        self.assertEqual(d[2][0], u"¿")

      def test_read_write_negative_numerics(self):
          "reading and writing negative numeric values"
@@ -797,11 +788,10 @@
              cursor.execute("SELECT :start..:finish FROM :cf WHERE KEY =  
negatives;",
                             dict(start=-10, finish=-1, cf=cf))
              r = cursor.fetchone()
-            assert len(r) == 10, \
-                "returned %d columns, expected %d" % (len(r) - 1, 10)
+            self.assertEqual(len(r), 10)
              d = cursor.description
-            assert d[0][0] == -10
-            assert d[9][0] == -1
+            self.assertEqual(d[0][0], -10)
+            self.assertEqual(d[9][0], -1)

      def test_escaped_quotes(self):
          "reading and writing strings w/ escaped quotes"
@@ -814,11 +804,11 @@
          cursor.execute("""
                         SELECT 'x''and''y' FROM StandardString1 WHERE KEY  
= :key
                         """, dict(key="test_escaped_quotes"))
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          r = cursor.fetchone()
-        assert len(r) == 1, "wrong number of results"
+        self.assertEqual(len(r), 1)
          d = cursor.description
-        assert d[0][0] == "x'and'y"
+        self.assertEqual(d[0][0], "x'and'y")

      def test_newline_strings(self):
          "reading and writing strings w/ newlines"
@@ -831,12 +821,12 @@
          cursor.execute("""
                         SELECT :name FROM StandardString1 WHERE KEY = :key
                         """, {"key": "\nkey", "name": "\nname"})
-        assert cursor.rowcount == 1
+        self.assertEqual(cursor.rowcount, 1)
          r = cursor.fetchone()
-        assert len(r) == 1, "wrong number of results"
+        self.assertEqual(len(r), 1)
          d = cursor.description
-        assert d[0][0] == "\nname"
-        assert r[0] == "\nval"
+        self.assertEqual(d[0][0], "\nname")
+        self.assertEqual(r[0], "\nval")

      def test_typed_keys(self):
          "using typed keys"
@@ -858,11 +848,11 @@
          cursor.execute("SELECT * FROM StandardUtf82 WHERE KEY = :key",  
dict(key="meat"))
          r = cursor.fetchone()
          d = cursor.description
-        assert d[1][0] == "beef"
-        assert r[1] == "brisket"
-
-        assert d[2][0] == "pork"
-        assert r[2] == "bacon"
+        self.assertEqual(d[1][0], "beef")
+        self.assertEqual(r[1], "brisket")
+
+        self.assertEqual(d[2][0], "pork")
+        self.assertEqual(r[2], "bacon")

          # Bad writes.

@@ -888,11 +878,11 @@
          cursor.execute("SELECT :name FROM StandardString1 WHERE KEY  
= :key",
                         dict(name="some_name", key="compression_test"))

-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]
-        assert ['some_name'] == colnames, colnames
+        self.assertEqual(['some_name'], colnames)
          row = cursor.fetchone()
-        assert ['some_value'] == row, row
+        self.assertEqual(['some_value'], row)

      def test_batch_with_mixed_statements(self):
          "handle BATCH with INSERT/UPDATE/DELETE statements mixed in it"
@@ -911,30 +901,30 @@
          cursor.execute("SELECT :name FROM StandardString1 WHERE KEY  
= :key",
                         dict(name="bName", key="bKey1"))

-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]
-        assert ['bName'] == colnames, colnames
+        self.assertEqual(['bName'], colnames)
          r = cursor.fetchone()
-        assert ['bVal'] == r, r
+        self.assertEqual(['bVal'], r)

          cursor.execute("SELECT :name FROM StandardString1 WHERE KEY  
= :key",
                         dict(name="bCol2", key="bKey3"))

-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]
-        assert ['bCol2'] == colnames, colnames
+        self.assertEqual(['bCol2'], colnames)
          # was deleted by DELETE statement
          r = cursor.fetchone()
-        assert [None] == r, r
+        self.assertEqual([None], r)

          cursor.execute("SELECT :name FROM StandardString1 WHERE KEY  
= :key",
                         dict(name="bCol1", key="bKey2"))

-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]
-        assert ['bCol1'] == colnames, colnames
+        self.assertEqual(['bCol1'], colnames)
          r = cursor.fetchone()
-        assert ['bVal'] == r, r
+        self.assertEqual(['bVal'], r)

          # using all 3 types of statements allowed in batch to test  
timestamp
          cursor.execute("""
@@ -985,24 +975,20 @@
          """)

          cursor.execute("SELECT * FROM StandardString1 WHERE KEY IN  
('mUser1', 'mUser2')")
-        assert cursor.rowcount == 2, "expected 2 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 2)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "login", \
-               "unrecognized name '%s'" % colnames[1]
-        assert colnames[2] == "password", \
-               "unrecognized name '%s'" % colnames[2]
+        self.assertEqual(colnames[1], "login")
+        self.assertEqual(colnames[2], "password")

          for i in range(2):
              r = cursor.fetchone()
-            assert r[1] == "same", \
-                   "unrecognized value '%s'" % r[1]
-            assert r[2] == "p4ssw0rd", \
-                   "unrecognized value '%s'" % r[1]
+            self.assertEqual(r[1], "same")
+            self.assertEqual(r[2], "p4ssw0rd")

          # select with same KEY AND'ed (see CASSANDRA-2717)
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY = 'mUser1'  
AND KEY = 'mUser1'")
-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)

          # select with different KEYs AND'ed
          self.assertRaises(cql.ProgrammingError,
@@ -1011,7 +997,7 @@

          # select with same KEY repeated in IN
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY IN  
('mUser1', 'mUser1')")
-        assert cursor.rowcount == 1, "expected 1 result, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)

      def test_insert_with_timestamp_and_ttl(self):
          "insert statement should support setting timestamp"
@@ -1023,60 +1009,52 @@

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # and INSERT with CONSISTENCY and TIMESTAMP together
          cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES  
('TimestampedUser1', 'name here') USING TIMESTAMP 1303743619771318 AND  
CONSISTENCY ONE")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser1'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # and INSERT with TTL
          cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES  
('TimestampedUser2', 'name here') USING TTL 5678")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser2'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # and INSERT with CONSISTENCY, TIMESTAMP and TTL together
          cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES  
('TimestampedUser3', 'name here') USING TTL 4587 AND TIMESTAMP  
1303743619771318 AND CONSISTENCY ONE")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # and INSERT with TTL
          cursor.execute("INSERT INTO StandardString1 (KEY, name) VALUES  
('TimestampedUser14', 'name here') USING TTL 1 AND CONSISTENCY ONE")
@@ -1086,10 +1064,10 @@

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser14'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)

          r = cursor.fetchone()
-        assert len(r) == 1, "expected 0 results, got %d" % len(r)
+        self.assertEqual(len(r), 1)

      def test_update_with_timestamp_and_ttl(self):
          "update statement should support setting timestamp"
@@ -1101,60 +1079,52 @@

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser2'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # and UPDATE with CONSISTENCY and TIMESTAMP together
          cursor.execute("UPDATE StandardString1 USING CONSISTENCY ONE AND  
TIMESTAMP 1303743619771318 SET name = 'name here' WHERE KEY  
= 'TimestampedUser3'")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # UPDATE with TTL
          cursor.execute("UPDATE StandardString1 USING TTL 13030 SET name  
= 'name here' WHERE KEY = 'TimestampedUser4'")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser4'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # UPDATE with CONSISTENCY, TIMESTAMP and TTL together
          cursor.execute("UPDATE StandardString1 USING CONSISTENCY ONE AND  
TIMESTAMP 1303743619771318 AND TTL 13037 SET name = 'name here' WHERE KEY  
= 'TimestampedUser5'")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser5'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # UPDATE with TTL
          cursor.execute("UPDATE StandardString1 USING CONSISTENCY ONE TTL 1  
SET name = 'name here' WHERE KEY = 'TimestampedUser6'")
@@ -1164,10 +1134,10 @@

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser6'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)

          r = cursor.fetchone()
-        assert len(r) == 1, "expected 0 results, got %d" % len(r)
+        self.assertEqual(len(r), 1)

      def test_delete_with_timestamp(self):
          "delete statement should support setting timestamp"
@@ -1179,57 +1149,51 @@

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # DELETE with a lower TIMESTAMP
          cursor.execute("DELETE 'name here' FROM StandardString1 USING  
TIMESTAMP 3 WHERE KEY = 'TimestampedUser3'")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert len(colnames) == 2, "expected 2 columns, got %d" %  
len(colnames)
-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(len(colnames), 2)
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # now DELETE the whole row with a lower TIMESTAMP
          cursor.execute("DELETE FROM StandardString1 USING TIMESTAMP 3  
WHERE KEY = 'TimestampedUser3'")

          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert len(colnames) == 2, "expected 2 columns, got %d" %  
len(colnames)
-        assert colnames[1] == "name", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(len(colnames), 2)
+        self.assertEqual(colnames[1], "name")

          r = cursor.fetchone()
-        assert r[1] == "name here", \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], "name here")

          # now DELETE the row with a greater TIMESTAMP
          cursor.execute("DELETE FROM StandardString1 USING TIMESTAMP 15  
WHERE KEY = 'TimestampedUser3'")
          # try to read it
          cursor.execute("SELECT * FROM StandardString1 WHERE KEY  
= 'TimestampedUser3'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert len(colnames) == 1, "expected only the KEY column,  
got %d" % len(colnames)
-        assert colnames[0] == "KEY", "unrecognized name '%s'" % colnames[0]
+        self.assertEqual(len(colnames), 1, msg="expected only the KEY  
column, got %d columns" % len(colnames))
+        self.assertEqual(colnames[0], "KEY")

      def test_alter_table_statement(self):
          "test ALTER statement"
@@ -1246,35 +1210,32 @@

          # TODO: temporary (until this can be done with CQL).
          ksdef = thrift_client.describe_keyspace("AlterTableKS")
-        assert len(ksdef.cf_defs) == 1, \
-            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 1)
          cfam = ksdef.cf_defs[0]

-        assert len(cfam.column_metadata) == 0
+        self.assertEqual(len(cfam.column_metadata), 0)

          # testing "add a new column"
          cursor.execute("ALTER COLUMNFAMILY NewCf1 ADD name varchar")

          ksdef = thrift_client.describe_keyspace("AlterTableKS")
-        assert len(ksdef.cf_defs) == 1, \
-            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 1)
          columns = ksdef.cf_defs[0].column_metadata

-        assert len(columns) == 1
-        assert columns[0].name == 'name'
-        assert columns[0].validation_class  
== 'org.apache.cassandra.db.marshal.UTF8Type'
+        self.assertEqual(len(columns), 1)
+        self.assertEqual(columns[0].name, 'name')
+         
self.assertEqual(columns[0].validation_class, 'org.apache.cassandra.db.marshal.UTF8Type')

          # testing "alter a column type"
          cursor.execute("ALTER COLUMNFAMILY NewCf1 ALTER name TYPE ascii")

          ksdef = thrift_client.describe_keyspace("AlterTableKS")
-        assert len(ksdef.cf_defs) == 1, \
-            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 1)
          columns = ksdef.cf_defs[0].column_metadata

-        assert len(columns) == 1
-        assert columns[0].name == 'name'
-        assert columns[0].validation_class  
== 'org.apache.cassandra.db.marshal.AsciiType'
+        self.assertEqual(len(columns), 1)
+        self.assertEqual(columns[0].name, 'name')
+         
self.assertEqual(columns[0].validation_class, 'org.apache.cassandra.db.marshal.AsciiType')

          # alter column with unknown validator
          self.assertRaises(cql.ProgrammingError,
@@ -1285,11 +1246,10 @@
          cursor.execute("ALTER COLUMNFAMILY NewCf1 DROP name")

          ksdef = thrift_client.describe_keyspace("AlterTableKS")
-        assert len(ksdef.cf_defs) == 1, \
-            "expected 1 column family total, found %d" % len(ksdef.cf_defs)
+        self.assertEqual(len(ksdef.cf_defs), 1)
          columns = ksdef.cf_defs[0].column_metadata

-        assert len(columns) == 0
+        self.assertEqual(len(columns), 0)

          # add column with unknown validator
          self.assertRaises(cql.ProgrammingError,
@@ -1319,61 +1279,53 @@
          # increment counter
          cursor.execute("UPDATE CounterCF SET count_me = count_me + 2 WHERE  
key = 'counter1'")
          cursor.execute("SELECT * FROM CounterCF WHERE KEY = 'counter1'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "count_me", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "count_me")

          r = cursor.fetchone()
-        assert r[1] == 2, \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], 2)

          cursor.execute("UPDATE CounterCF SET count_me = count_me + 2 WHERE  
key = 'counter1'")
          cursor.execute("SELECT * FROM CounterCF WHERE KEY = 'counter1'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

-        assert colnames[1] == "count_me", \
-               "unrecognized name '%s'" % colnames[1]
+        self.assertEqual(colnames[1], "count_me")

          r = cursor.fetchone()
-        assert r[1] == 4, \
-               "unrecognized value '%s'" % r[1]
+        self.assertEqual(r[1], 4)

          # decrement counter
          cursor.execute("UPDATE CounterCF SET count_me = count_me - 4 WHERE  
key = 'counter1'")
          cursor.execute("SELECT * FROM CounterCF WHERE KEY = 'counter1'")
-        assert cursor.rowcount == 1, "expected 1 results, got %d" %  
cursor.rowcount
+        self.assertEqual(cursor.rowcount, 1)
          colnames = [col_d[0] for col_d in cursor.description]

***The diff for this file has been truncated for email.***
=======================================
--- /test/test_query_compression.py	Fri Apr 15 05:48:15 2011
+++ /test/test_query_compression.py	Thu Dec 15 12:50:09 2011
@@ -23,4 +23,4 @@
          query = "SELECT \"foo\" FROM Standard1 WHERE KEY = \"bar\";"
          compressed = zlib.compress(query)
          decompressed = zlib.decompress(compressed)
-        assert query == decompressed, "Decompressed query did not match"
+        self.assertEqual(query, decompressed)
=======================================
--- /test/test_query_preparation.py	Wed Aug 24 11:18:52 2011
+++ /test/test_query_preparation.py	Thu Dec 15 12:50:09 2011
@@ -56,7 +56,7 @@
          for (i, test) in enumerate(TESTS):
              a = prepare(test, ARGUMENTS[i])
              b = STANDARDS[i]
-            assert a == b, "\n%s !=\n%s" % (a, b)
+            self.assertEqual(a, b)

      def test_bad(self):
          "ensure bad calls raise exceptions"

==============================================================================
Revision: 626f935c9d6e
Author:   paul cannon <pa...@datastax.com>
Date:     Thu Dec 15 13:28:57 2011
Log:      Merge branch 'master' into issue-11

Conflicts:
	test/test_query_preparation.py

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=626f935c9d6e



==============================================================================
Revision: 2b2c179272ce
Author:   paul cannon <pa...@datastax.com>
Date:     Tue Dec 27 14:55:01 2011
Log:      Comply with ASF licensing requirements

Add NOTICE and LICENSE files, and add missing ASF license header to
test_regex.py. See http://www.apache.org/dev/apply-license.html

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=2b2c179272ce

Added:
  /LICENSE
  /NOTICE
Modified:
  /test/test_regex.py

=======================================
--- /dev/null
+++ /LICENSE	Tue Dec 27 14:55:01 2011
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other  
modifications
+      represent, as a whole, an original work of authorship. For the  
purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces  
of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright  
owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control  
systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this  
License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   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.
=======================================
--- /dev/null
+++ /NOTICE	Tue Dec 27 14:55:01 2011
@@ -0,0 +1,5 @@
+Apache Cassandra Python CQL Driver
+Copyright (c) 2011 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
=======================================
--- /test/test_regex.py	Wed Aug 24 11:18:52 2011
+++ /test/test_regex.py	Tue Dec 27 14:55:01 2011
@@ -1,3 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# 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.
+
  import unittest
  from cql.cursor import Cursor


==============================================================================
Revision: 9a3b065e6f41
Author:   paul cannon <pa...@riptano.com>
Date:     Tue Dec 27 15:48:04 2011
Log:      distribute NOTICE and LICENSE in sdist

that is, python source distributions created with setup.py sdist.

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=9a3b065e6f41

Modified:
  /MANIFEST.in

=======================================
--- /MANIFEST.in	Tue Sep 27 14:32:27 2011
+++ /MANIFEST.in	Tue Dec 27 15:48:04 2011
@@ -1,1 +1,2 @@
  include *.txt
+include LICENSE NOTICE

==============================================================================
Revision: 350590f4501d
Author:   paul cannon <pa...@riptano.com>
Date:     Tue Dec 27 15:17:14 2011
Log:      release 1.0.7

http://code.google.com/a/apache-extras.org/p/cassandra-dbapi2/source/detail?r=350590f4501d

Modified:
  /CHANGES.txt
  /setup.py

=======================================
--- /CHANGES.txt	Thu Nov 10 13:51:53 2011
+++ /CHANGES.txt	Tue Dec 27 15:17:14 2011
@@ -1,3 +1,9 @@
+1.0.7 - 2011/12/27
+ * Comply with ASF licensing requirements
+ * Fixed unit test for TRUNCATE
+ * Improve recognition of substitution parameters (":foo")
+ * Fix some unmarshallers when used under python2.4
+
  1.0.6
   * allow override of SchemaDecoder
   * put value type in row descriptions, not column name type
=======================================
--- /setup.py	Thu Nov 10 13:51:53 2011
+++ /setup.py	Tue Dec 27 15:17:14 2011
@@ -20,7 +20,7 @@

  setup(
      name="cql",
-    version="1.0.6",
+    version="1.0.7",
      description="Cassandra Query Language driver",
       
long_description=open(abspath(join(dirname(__file__), 'README'))).read(),
      maintainer='Cassandra DBAPI-2 Driver Team',