cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mish...@apache.org
Subject [2/2] git commit: Switch cqlsh from cassandra-dbapi2 to python-driver patch by Mikhail Stepura for CASSANDRA-6307; reviewed by Aleksey Yeschenko and Tyler Hobbs
Date Wed, 12 Mar 2014 22:06:18 GMT
Switch cqlsh from cassandra-dbapi2 to python-driver
patch by Mikhail Stepura for CASSANDRA-6307; reviewed by Aleksey Yeschenko and Tyler Hobbs


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/caf609cf
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/caf609cf
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/caf609cf

Branch: refs/heads/cassandra-2.1
Commit: caf609cf6f80c02dce7cffeecc167dc7fc051e73
Parents: 773dda7
Author: Mikhail Stepura <mishail@apache.org>
Authored: Wed Mar 12 15:02:14 2014 -0700
Committer: Mikhail Stepura <mishail@apache.org>
Committed: Wed Mar 12 15:02:14 2014 -0700

----------------------------------------------------------------------
 bin/cqlsh                                       | 653 +++++--------------
 conf/cqlshrc.sample                             |  10 +-
 ...assandra-driver-internal-only-1.0.2.post.zip | Bin 0 -> 95836 bytes
 lib/cql-internal-only-1.4.1.zip                 | Bin 92738 -> 0 bytes
 lib/futures-2.1.6-py2.py3-none-any.zip          | Bin 0 -> 16571 bytes
 lib/thrift-python-internal-only-0.9.1.zip       | Bin 52477 -> 0 bytes
 pylib/cqlshlib/cql3handling.py                  | 263 ++------
 pylib/cqlshlib/cqlhandling.py                   |   2 -
 pylib/cqlshlib/formatting.py                    |  78 ++-
 pylib/cqlshlib/helptopics.py                    |   4 +-
 pylib/cqlshlib/ssl.py                           |  70 --
 pylib/cqlshlib/sslhandling.py                   |  78 +++
 pylib/cqlshlib/test/basecase.py                 |   6 +-
 pylib/cqlshlib/test/cassconnect.py              |  36 +-
 pylib/cqlshlib/test/run_cqlsh.py                |   1 +
 pylib/cqlshlib/test/test_cqlsh_completion.py    |   5 +-
 pylib/cqlshlib/test/test_cqlsh_output.py        | 132 ++--
 pylib/cqlshlib/test/test_keyspace_init.cql      |  21 +-
 pylib/cqlshlib/tfactory.py                      |  31 -
 pylib/cqlshlib/tracing.py                       |  66 +-
 pylib/cqlshlib/usertypes.py                     |  31 +-
 21 files changed, 510 insertions(+), 977 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 9b39469..e168238 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -30,15 +30,14 @@ exit 1
 ":"""
 
 from __future__ import with_statement
+from uuid import UUID
 
 description = "CQL Shell for Apache Cassandra"
-version = "4.1.2"
+version = "5.0.0"
 
 from StringIO import StringIO
-from itertools import groupby
 from contextlib import contextmanager, closing
 from glob import glob
-from uuid import UUID
 
 import cmd
 import sys
@@ -63,8 +62,8 @@ try:
 except ImportError:
     pass
 
-CQL_LIB_PREFIX = 'cql-internal-only-'
-THRIFT_LIB_PREFIX = 'thrift-python-internal-only-'
+CQL_LIB_PREFIX = 'cassandra-driver-internal-only-'
+FUTURES_LIB_PREFIX = 'futures-'
 
 CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
 
@@ -87,24 +86,25 @@ def find_zip(libprefix):
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
-    sys.path.insert(0, os.path.join(cql_zip, 'cql-' + ver))
-thrift_zip = find_zip(THRIFT_LIB_PREFIX)
-if thrift_zip:
-    sys.path.insert(0, thrift_zip)
+    sys.path.insert(0, os.path.join(cql_zip, 'cassandra-driver-' + ver))
+futures_zip = find_zip(FUTURES_LIB_PREFIX)
+if futures_zip:
+    sys.path.insert(0, futures_zip)
+
 
 try:
-    import cql
+    import cassandra
 except ImportError, e:
-    sys.exit("\nPython CQL driver not installed, or not on PYTHONPATH.\n"
-             'You might try "easy_install cql".\n\n'
+    sys.exit("\nPython Cassandra driver not installed, or not on PYTHONPATH.\n"
+             'You might try "pip install cassandra-driver".\n\n'
              'Python: %s\n'
              'Module load path: %r\n\n'
              'Error: %s\n' % (sys.executable, sys.path, e))
 
-import cql.decoders
-from cql.cursor import _VOID_DESCRIPTION
-from cql.cqltypes import (cql_types, cql_typename, lookup_casstype, lookup_cqltype,
-                          CassandraType, ReversedType, CompositeType)
+from cassandra.cluster import Cluster
+from cassandra.query import SimpleStatement
+from cassandra.policies import WhiteListRoundRobinPolicy
+from cassandra.metadata import protect_name, protect_names, protect_value
 
 # cqlsh should run correctly when run out of a Cassandra source tree,
 # out of an unpacked Cassandra tarball, and after a proper package install.
@@ -112,7 +112,7 @@ cqlshlibdir = os.path.join(CASSANDRA_PATH, 'pylib')
 if os.path.isdir(cqlshlibdir):
     sys.path.insert(0, cqlshlibdir)
 
-from cqlshlib import cqlhandling, cql3handling, pylexotron, usertypes
+from cqlshlib import cqlhandling, cql3handling, pylexotron, usertypes, sslhandling
 from cqlshlib.displaying import (RED, BLUE, ANSI_RESET, COLUMN_NAME_COLORS,
                                  FormattedValue, colorme)
 from cqlshlib.formatting import format_by_type
@@ -132,10 +132,9 @@ OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
 if os.path.exists(OLD_HISTORY):
     os.rename(OLD_HISTORY, HISTORY)
 
-DEFAULT_HOST = 'localhost'
-DEFAULT_PORT = 9160
-DEFAULT_CQLVER = '3.1.1'
-DEFAULT_TRANSPORT_FACTORY = 'cqlshlib.tfactory.regular_transport_factory'
+DEFAULT_HOST = '127.0.0.1'
+DEFAULT_PORT = 9042
+DEFAULT_CQLVER = '3.1.5'
 
 DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S%z'
 DEFAULT_FLOAT_PRECISION = 5
@@ -158,25 +157,24 @@ parser.add_option("-C", "--color", action='store_true', dest='color',
                   help='Always use color output')
 parser.add_option("--no-color", action='store_false', dest='color',
                   help='Never use color output')
+parser.add_option('--ssl', action='store_true', help='Use SSL', default=False)
 parser.add_option("-u", "--username", help="Authenticate as user.")
 parser.add_option("-p", "--password", help="Authenticate using password.")
 parser.add_option('-k', '--keyspace', help='Authenticate to the given keyspace.')
 parser.add_option("-f", "--file", help="Execute commands from FILE, then exit")
-parser.add_option("-t", "--transport-factory",
-                  help="Use the provided Thrift transport factory function.")
 parser.add_option('--debug', action='store_true',
                   help='Show additional debugging information')
 parser.add_option('--cqlversion', default=DEFAULT_CQLVER,
                   help='Specify a particular CQL version (default: %default).'
                        ' Examples: "3.0.3", "3.1.0"')
 
-CQL_ERRORS = (cql.Error,)
-try:
-    from thrift.Thrift import TException
-except ImportError:
-    pass
-else:
-    CQL_ERRORS += (TException,)
+CQL_ERRORS = (
+    cassandra.AlreadyExists, cassandra.AuthenticationFailed, cassandra.InvalidRequest,
+    cassandra.Timeout, cassandra.Unauthorized, cassandra.OperationTimedOut,
+    cassandra.cluster.NoHostAvailable,
+    cassandra.connection.ConnectionBusy, cassandra.connection.ProtocolError, cassandra.connection.ConnectionException,
+    cassandra.decoder.ErrorMessage, cassandra.decoder.InternalError, cassandra.query.TraceUnavailable
+)
 
 debug_completion = bool(os.environ.get('CQLSH_DEBUG_COMPLETION', '') == 'YES')
 
@@ -374,12 +372,9 @@ class UserTypeNotFound(Exception):
 class DecodeError(Exception):
     verb = 'decode'
 
-    def __init__(self, thebytes, err, expectedtype, colname=None):
+    def __init__(self, thebytes, err, colname=None):
         self.thebytes = thebytes
         self.err = err
-        if isinstance(expectedtype, type) and issubclass(expectedtype, CassandraType):
-            expectedtype = expectedtype.cql_parameterized_type()
-        self.expectedtype = expectedtype
         self.colname = colname
 
     def __str__(self):
@@ -389,8 +384,8 @@ class DecodeError(Exception):
         what = 'value %r' % (self.thebytes,)
         if self.colname is not None:
             what = 'value %r (for column %r)' % (self.thebytes, self.colname)
-        return 'Failed to %s %s as %s: %s' \
-               % (self.verb, what, self.expectedtype, self.err)
+        return 'Failed to %s %s : %s' \
+               % (self.verb, what, self.err)
 
     def __repr__(self):
         return '<%s %s>' % (self.__class__.__name__, self.message())
@@ -405,16 +400,14 @@ def full_cql_version(ver):
     vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
     return ver, vertuple
 
-def format_value(val, typeclass, output_encoding, addcolor=False, time_format=None,
+def format_value(val, output_encoding, addcolor=False, time_format=None,
                  float_precision=None, colormap=None, nullval=None):
     if isinstance(val, DecodeError):
         if addcolor:
             return colorme(repr(val.thebytes), colormap, 'error')
         else:
             return FormattedValue(repr(val.thebytes))
-    if not issubclass(typeclass, CassandraType):
-        typeclass = lookup_casstype(typeclass)
-    return format_by_type(typeclass, val, output_encoding, colormap=colormap,
+    return format_by_type(type(val), val, output_encoding, colormap=colormap,
                           addcolor=addcolor, nullval=nullval, time_format=time_format,
                           float_precision=float_precision)
 
@@ -452,7 +445,6 @@ class Shell(cmd.Cmd):
     continue_prompt = "   ... "
     keyspace_prompt = custom_prompt + "cqlsh:%s> "
     keyspace_continue_prompt = "%s    ... "
-    num_retries = 4
     show_line_nums = False
     debug = False
     stop = False
@@ -460,38 +452,37 @@ class Shell(cmd.Cmd):
     shunted_query_out = None
     csv_dialect_defaults = dict(delimiter=',', doublequote=False,
                                 escapechar='\\', quotechar='"')
-    utypes_meta = None
 
-    def __init__(self, hostname, port, transport_factory, color=False,
+    def __init__(self, hostname, port, color=False,
                  username=None, password=None, encoding=None, stdin=None, tty=True,
                  completekey=DEFAULT_COMPLETEKEY, use_conn=None,
                  cqlver=DEFAULT_CQLVER, keyspace=None,
                  tracing_enabled=False, expand_enabled=False,
                  display_time_format=DEFAULT_TIME_FORMAT,
-                 display_float_precision=DEFAULT_FLOAT_PRECISION):
+                 display_float_precision=DEFAULT_FLOAT_PRECISION,
+                 ssl=False):
         cmd.Cmd.__init__(self, completekey=completekey)
         self.hostname = hostname
         self.port = port
-        self.transport_factory = transport_factory
-        self.username = username
-        self.password = password
+        self.auth_provider = None
+        if username and password:
+            self.auth_provider = lambda host: dict(username=username, password=password)
         self.keyspace = keyspace
         self.tracing_enabled = tracing_enabled
         self.expand_enabled = expand_enabled
-        if use_conn is not None:
+        if use_conn:
             self.conn = use_conn
         else:
-            transport = transport_factory(hostname, port, os.environ, CONFIG_FILE)
-            self.conn = cql.connect(hostname, port, user=username, password=password,
-                                    cql_version=cqlver, transport=transport)
+            self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
+                                auth_provider=self.auth_provider,
+                                ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,
+                                load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]))
         self.set_expanded_cql_version(cqlver)
-        # we could set the keyspace through cql.connect(), but as of 1.0.10,
-        # it doesn't quote the keyspace for USE :(
-        if keyspace is not None:
-            tempcurs = self.conn.cursor()
-            tempcurs.execute('USE %s;' % self.cql_protect_name(keyspace))
-            tempcurs.close()
-        self.cursor = self.conn.cursor()
+
+        if keyspace:
+            self.session = self.conn.connect(keyspace)
+        else:
+            self.session = self.conn.connect()
         self.get_connection_versions()
 
         self.current_keyspace = keyspace
@@ -520,13 +511,13 @@ class Shell(cmd.Cmd):
             self.show_line_nums = True
         self.stdin = stdin
         self.query_out = sys.stdout
-        self.refresh_utypes_meta()
-        #UserTypes will use it to get theirs field names
-        usertypes.get_field_names = lambda k, t: self.utypes_meta.get_field_names(k, t)
+        self.consistency_level = cassandra.ConsistencyLevel.ONE
+        #Python driver returns BLOBs as string, but we expect them as buffer()
+        cassandra.cqltypes.BytesType.deserialize = staticmethod(cassandra.cqltypes.BytesType.validate)
+        cassandra.cqltypes.CassandraType.support_empty_values = True
 
     def set_expanded_cql_version(self, ver):
         ver, vertuple = full_cql_version(ver)
-        self.set_cql_version(ver)
         self.cql_version = ver
         self.cql_ver_tuple = vertuple
 
@@ -536,31 +527,20 @@ class Shell(cmd.Cmd):
     def cassandraver_atleast(self, major, minor=0, patch=0):
         return self.cass_ver_tuple[:3] >= (major, minor, patch)
 
-    def myformat_value(self, val, casstype, **kwargs):
+    def myformat_value(self, val, **kwargs):
         if isinstance(val, DecodeError):
             self.decoding_errors.append(val)
         try:
-            return format_value(val, casstype, self.output_codec.name,
+            return format_value(val, self.output_codec.name,
                                 addcolor=self.color, time_format=self.display_time_format,
                                 float_precision=self.display_float_precision, **kwargs)
         except Exception, e:
-            err = FormatError(val, e, casstype)
+            err = FormatError(val, e)
             self.decoding_errors.append(err)
-            return format_value(err, None, self.output_codec.name, addcolor=self.color)
-
-    def myformat_colname(self, name, nametype):
-        return self.myformat_value(name, nametype, colormap=COLUMN_NAME_COLORS)
-
-    # cql/cursor.py:Cursor.decode_row() function, modified to not turn '' into None.
-    def decode_row(self, cursor, row):
-        values = []
-        bytevals = cursor.columnvalues(row)
-        for val, vtype, nameinfo in zip(bytevals, cursor.column_types, cursor.name_info):
-            if val == '':
-                values.append(val)
-            else:
-                values.append(cursor.decoder.decode_value(val, vtype, nameinfo[0]))
-        return values
+            return format_value(err, self.output_codec.name, addcolor=self.color)
+
+    def myformat_colname(self, name):
+        return self.myformat_value(name, colormap=COLUMN_NAME_COLORS)
 
     def report_connection(self):
         self.show_host()
@@ -578,156 +558,95 @@ class Shell(cmd.Cmd):
         # system.Versions['cql'] apparently does not reflect changes with
         # set_cql_version.
         vers['cql'] = self.cql_version
-        print "[cqlsh %(shver)s | Cassandra %(build)s | CQL spec %(cql)s | Thrift protocol %(thrift)s]" % vers
+        print "[cqlsh %(shver)s | Cassandra %(build)s | CQL spec %(cql)s | Native protocol v%(protocol)s]" % vers
 
     def show_session(self, sessionid):
-        print_trace_session(self, self.cursor, sessionid)
+        print_trace_session(self, self.session, sessionid)
 
     def get_connection_versions(self):
-        self.cursor.execute("select * from system.local where key = 'local'")
-        result = self.fetchdict()
+        result, = self.session.execute("select * from system.local where key = 'local'")
         vers = {
-            'build': result['release_version'],
-            'thrift': result['thrift_version'],
-            'cql': result['cql_version'],
+            'build': result.release_version,
+            'protocol': result.native_protocol_version,
+            'cql': result.cql_version,
         }
         self.connection_versions = vers
         self.cass_ver_tuple = tuple(map(int, vers['build'].split('-', 1)[0].split('.')[:3]))
 
-    def fetchdict(self):
-        row = self.cursor.fetchone()
-        if row is None:
-            return None
-        desc = self.cursor.description
-        return dict(zip([d[0] for d in desc], row))
-
-    def fetchdict_all(self):
-        dicts = []
-        for row in self.cursor:
-            desc = self.cursor.description
-            dicts.append(dict(zip([d[0] for d in desc], row)))
-        return dicts
-
     def get_keyspace_names(self):
-        return [k.name for k in self.get_keyspaces()]
+        return map(str, self.conn.metadata.keyspaces.keys())
 
     def get_columnfamily_names(self, ksname=None):
         if ksname is None:
             ksname = self.current_keyspace
-        cf_q = """select columnfamily_name from system.schema_columnfamilies
-                   where keyspace_name=:ks"""
-        self.cursor.execute(cf_q,
-                            {'ks': self.cql_unprotect_name(ksname)},
-                            consistency_level='ONE')
-        return [str(row[0]) for row in self.cursor.fetchall()]
+
+        return map(str, self.get_keyspace_meta(ksname).tables.keys())
 
     def get_index_names(self, ksname=None):
         idxnames = []
         for cfname in self.get_columnfamily_names(ksname=ksname):
-            for col in self.get_columnfamily_layout(ksname, cfname).columns:
-                if col.index_name is not None:
-                    idxnames.append(col.index_name)
+            for col in self.get_table_meta(ksname, cfname).columns.values():
+                if col.index:
+                    idxnames.append(col.index.name)
         return idxnames
 
     def get_column_names(self, ksname, cfname):
         if ksname is None:
             ksname = self.current_keyspace
-        layout = self.get_columnfamily_layout(ksname, cfname)
-        return [col.name for col in layout.columns]
+        layout = self.get_table_meta(ksname, cfname)
+        return [str(col) for col in layout.columns]
 
     def get_usertype_names(self, ksname=None):
         if ksname is None:
             ksname = self.current_keyspace
 
-        return self.utypes_meta.get_usertypes_names(ksname)
+        return self.get_usertypes_meta().get_usertypes_names(ksname)
 
     def get_usertype_layout(self, ksname, typename):
         if ksname is None:
             ksname = self.current_keyspace
-        layout = self.utypes_meta.get_fields_with_types(ksname, typename)
+        layout = self.get_usertypes_meta().get_fields_with_types(ksname, typename)
 
         if not layout:
             raise UserTypeNotFound("User type %r not found" % typename)
         return layout
 
-    # ===== thrift-dependent parts =====
-
     def get_cluster_name(self):
-        return self.make_hacktastic_thrift_call('describe_cluster_name')
+        return self.conn.metadata.cluster_name
 
     def get_partitioner(self):
-        return self.make_hacktastic_thrift_call('describe_partitioner')
+        return self.conn.metadata.partitioner
 
-    def get_snitch(self):
-        return self.make_hacktastic_thrift_call('describe_snitch')
+    def get_keyspace_meta(self, ksname):
+        if not ksname in self.conn.metadata.keyspaces:
+            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
+        return self.conn.metadata.keyspaces[ksname]
 
-    def get_thrift_version(self):
-        return self.make_hacktastic_thrift_call('describe_version')
+    def get_keyspaces(self):
+        return self.conn.metadata.keyspaces.values()
 
     def get_ring(self):
         if self.current_keyspace is None or self.current_keyspace == 'system':
             raise NoKeyspaceError("Ring view requires a current non-system keyspace")
-        return self.make_hacktastic_thrift_call('describe_ring', self.current_keyspace)
+        return self.conn.metadata.token_map.tokens_to_hosts_by_ks[self.current_keyspace]
 
-    def get_keyspace(self, ksname):
-        try:
-            return self.make_hacktastic_thrift_call('describe_keyspace', ksname)
-        except cql.cassandra.ttypes.NotFoundException:
-            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
-
-    def get_keyspaces(self):
-        return self.make_hacktastic_thrift_call('describe_keyspaces')
-
-    def get_schema_versions(self):
-        return self.make_hacktastic_thrift_call('describe_schema_versions')
-
-    def set_cql_version(self, ver):
-        try:
-            return self.make_hacktastic_thrift_call('set_cql_version', ver)
-        except cql.cassandra.ttypes.InvalidRequestException, e:
-            raise VersionNotSupported(e.why)
-
-    def trace_next_query(self):
-        return self.make_hacktastic_thrift_call('trace_next_query')
-
-    def make_hacktastic_thrift_call(self, call, *args):
-        client = self.conn.client
-        return getattr(client, call)(*args)
+    def get_table_meta(self, ksname, tablename):
+        if ksname is None:
+            ksname = self.current_keyspace
+        ksmeta = self.get_keyspace_meta(ksname)
 
-    # ===== end thrift-dependent parts =====
+        if tablename not in ksmeta.tables:
+            raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 
-    # ===== cql3-dependent parts =====
+        return ksmeta.tables[tablename]
 
-    def get_columnfamily_layout(self, ksname, cfname):
-        if ksname is None:
-            ksname = self.current_keyspace
-        cf_q = """select * from system.schema_columnfamilies
-                   where keyspace_name=:ks and columnfamily_name=:cf"""
-        col_q = """select * from system.schema_columns
-                    where keyspace_name=:ks and columnfamily_name=:cf"""
-        self.cursor.execute(cf_q,
-                            {'ks': ksname, 'cf': cfname},
-                            consistency_level='ONE')
-        layout = self.fetchdict()
-        if layout is None:
-            raise ColumnFamilyNotFound("Column family %r not found" % cfname)
-        self.cursor.execute(col_q,
-                            {'ks': ksname, 'cf': cfname},
-                            consistency_level='ONE')
-        cols = self.fetchdict_all()
-        return cql3handling.CqlTableDef.from_layout(layout, cols)
-
-    def build_usertypes_meta(self):
-        ut_q = """select * from system.schema_usertypes"""
-        self.cursor.execute(ut_q, consistency_level='ONE')
-        data = self.fetchdict_all()
+    def get_usertypes_meta(self):
+        data = self.session.execute("select * from system.schema_usertypes")
         if not data:
             return cql3handling.UserTypesMeta({})
 
         return cql3handling.UserTypesMeta.from_layout(data)
 
-    # ===== end cql3-dependent parts =====
-
     def reset_statement(self):
         self.reset_prompt()
         self.statement.truncate(0)
@@ -788,14 +707,6 @@ class Shell(cmd.Cmd):
                 return
             yield newline
 
-    def refresh_utypes_meta(self):
-        try:
-            self.utypes_meta = self.build_usertypes_meta()
-        except Exception, e:
-            if self.debug:
-                import traceback
-                traceback.print_exc()
-
 
     def cmdloop(self):
         """
@@ -812,7 +723,7 @@ class Shell(cmd.Cmd):
                         self.reset_statement()
                 except EOFError:
                     self.handle_eof()
-                except cql.Error, cqlerr:
+                except CQL_ERRORS, cqlerr:
                     self.printerr(str(cqlerr))
                 except KeyboardInterrupt:
                     self.reset_statement()
@@ -903,56 +814,37 @@ class Shell(cmd.Cmd):
 
     def do_use(self, parsed):
         ksname = parsed.get_binding('ksname')
-        if self.perform_statement_untraced(parsed.extract_orig()):
+        if self.perform_simple_statement(SimpleStatement(parsed.extract_orig())):
             if ksname[0] == '"' and ksname[-1] == '"':
                 self.current_keyspace = self.cql_unprotect_name(ksname)
             else:
                 self.current_keyspace = ksname.lower()
 
     def do_select(self, parsed):
-        ksname = parsed.get_binding('ksname')
-        if ksname is not None:
-            ksname = self.cql_unprotect_name(ksname)
-        cfname = self.cql_unprotect_name(parsed.get_binding('cfname'))
         statement = parsed.extract_orig()
         with_default_limit = parsed.get_binding('limit') is None
         if with_default_limit:
             statement = "%s LIMIT %d;" % (statement[:-1], DEFAULT_SELECT_LIMIT)
-        self.perform_statement(statement,
-                               decoder=ErrorHandlingSchemaDecoder,
-                               with_default_limit=with_default_limit)
+        self.perform_statement(statement, with_default_limit=with_default_limit)
 
-    def perform_statement(self, statement, decoder=None, with_default_limit=False):
+    def perform_statement(self, statement, with_default_limit=False):
+        stmt = SimpleStatement(statement, consistency_level=self.consistency_level)
+        result = self.perform_simple_statement(stmt,
+                                                with_default_limit=with_default_limit)
         if self.tracing_enabled:
-            session_id = UUID(bytes=self.trace_next_query())
-            result = self.perform_statement_untraced(statement,
-                                                     decoder=decoder,
-                                                     with_default_limit=with_default_limit)
             time.sleep(0.5) # trace writes are async so we wait a little.
-            print_trace_session(self, self.cursor, session_id)
-            return result
-        else:
-            return self.perform_statement_untraced(statement,
-                                                   decoder=decoder,
-                                                   with_default_limit=with_default_limit)
+            print_trace_session(self, self.session, stmt.trace.trace_id)
+
+        return result
 
-    def perform_statement_untraced(self, statement, decoder=None, with_default_limit=False):
+    def perform_simple_statement(self, statement, with_default_limit=False):
         if not statement:
             return False
-        trynum = 1
+        rows = None
         while True:
             try:
-                self.cursor.execute(statement, decoder=decoder)
+                rows = self.session.execute(statement, trace=self.tracing_enabled)
                 break
-            except cql.IntegrityError, err:
-                self.printerr("Attempt #%d: %s" % (trynum, str(err)))
-                trynum += 1
-                if trynum > self.num_retries:
-                    return False
-                time.sleep(1*trynum)
-            except cql.ProgrammingError, err:
-                self.printerr(str(err))
-                return False
             except CQL_ERRORS, err:
                 self.printerr(str(err))
                 return False
@@ -961,35 +853,22 @@ class Shell(cmd.Cmd):
                 self.printerr(traceback.format_exc())
                 return False
 
-        if statement[:6].lower() == 'select' or statement.lower().startswith("list"):
-            self.print_result(self.cursor, with_default_limit)
-        elif self.cursor.rowcount > 0:
+        if statement.query_string[:6].lower() == 'select' or statement.query_string.lower().startswith("list"):
+            self.print_result(rows, with_default_limit)
+        elif rows:
             # CAS INSERT/UPDATE
             self.writeresult("")
-            self.print_static_result(self.cursor)
+            self.print_static_result(rows)
         self.flush_output()
-        if self.could_change_schema(statement):
-            self.refresh_utypes_meta()
         return True
 
-    def get_nametype(self, cursor, num):
-        """
-        Determine the Cassandra type of a column name from the current row of
-        query results on the given cursor. The column in question is given by
-        its zero-based ordinal number within the row.
-
-        This is necessary to differentiate some things like ascii vs. blob hex.
-        """
-
-        return cursor.name_info[num][1]
-
-    def print_result(self, cursor, with_default_limit):
+    def print_result(self, rows, with_default_limit):
         self.decoding_errors = []
 
         self.writeresult("")
-        if cursor.rowcount != 0:
-            self.print_static_result(cursor)
-        self.writeresult("(%d rows)" % cursor.rowcount)
+        if rows :
+            self.print_static_result(rows)
+        self.writeresult("(%d rows)" % len(rows))
         self.writeresult("")
 
         if self.decoding_errors:
@@ -1000,24 +879,19 @@ class Shell(cmd.Cmd):
                                  % (len(self.decoding_errors) - 2), color=RED)
 
         if with_default_limit:
-            if (self.is_count_result(cursor) and self.get_count(cursor) == DEFAULT_SELECT_LIMIT) \
-                    or cursor.rowcount == DEFAULT_SELECT_LIMIT:
+            if len(rows) == DEFAULT_SELECT_LIMIT:
                 self.writeresult("Default LIMIT of %d was used. "
                                  "Specify your own LIMIT clause to get more results."
                                  % DEFAULT_SELECT_LIMIT, color=RED)
                 self.writeresult("")
 
-    def is_count_result(self, cursor):
-        return cursor.description == [(u'count', 'LongType', None, None, None, None, True)]
 
-    def get_count(self, cursor):
-        return lookup_casstype('LongType').deserialize(cursor.result[0][0].value)
-
-    def print_static_result(self, cursor):
-        colnames = [d[0] for d in cursor.description]
-        colnames_t = [(name, self.get_nametype(cursor, n)) for (n, name) in enumerate(colnames)]
-        formatted_names = [self.myformat_colname(name, nametype) for (name, nametype) in colnames_t]
-        formatted_values = [map(self.myformat_value, self.decode_row(cursor, row), cursor.column_types) for row in cursor.result]
+    def print_static_result(self, rows):
+        if not rows:
+            return
+        colnames = rows[0]._fields
+        formatted_names = [self.myformat_colname(name) for name in colnames]
+        formatted_values = [map(self.myformat_value, row) for row in rows]
         if self.expand_enabled:
             self.print_formatted_result_vertically(formatted_names, formatted_values)
         else:
@@ -1093,17 +967,6 @@ class Shell(cmd.Cmd):
     def set_prompt(self, prompt):
         self.prompt = prompt
 
-    def cql_protect_name(self, name):
-        if isinstance(name, unicode):
-            name = name.encode('utf8')
-        return cqlruleset.maybe_escape_name(name)
-
-    def cql_protect_names(self, names):
-        return map(self.cql_protect_name, names)
-
-    def cql_protect_value(self, value):
-        return cqlruleset.escape_value(value)
-
     def cql_unprotect_name(self, namestr):
         if namestr is None:
             return
@@ -1114,32 +977,20 @@ class Shell(cmd.Cmd):
             return cqlruleset.dequote_value(valstr)
 
     def print_recreate_keyspace(self, ksdef, out):
-        stratclass = trim_if_present(ksdef.strategy_class, 'org.apache.cassandra.locator.')
-        ksname = self.cql_protect_name(ksdef.name)
-        out.write("CREATE KEYSPACE %s WITH replication = {\n" % ksname)
-        out.write("  'class': %s" % self.cql_protect_value(stratclass))
-        for opname, opval in ksdef.strategy_options.iteritems():
-            out.write(",\n  %s: %s" % (self.cql_protect_value(opname),
-                                       self.cql_protect_value(opval)))
-        out.write("\n}")
-        if not ksdef.durable_writes:
-            out.write(" AND durable_writes = 'false'")
-        out.write(';\n')
-
-        #print usertypes first
-        uts = self.get_usertype_names(ksname)
+        ksname = protect_name(ksdef.name)
+        out.write(ksdef.as_cql_query())
+        out.write("\n\n")
+
+        uts = self.get_usertypes_meta().get_usertypes_names(ksname)
         if uts:
-            out.write('\nUSE %s;\n' % ksname)
+            out.write("USE %s;\n\n" % ksname)
             for ut in uts:
-                out.write('\n')
-                self.print_recreate_usertype(ksdef.name, ut, out)
+                self.print_recreate_usertype(ksname, ut, out)
 
-        cfs = self.get_columnfamily_names(ksname)
+        cfs = self.get_columnfamily_names(ksdef.name)
         if cfs:
-            out.write('\nUSE %s;\n' % ksname)
             for cf in cfs:
                 out.write('\n')
-                # yes, cf might be looked up again. oh well.
                 self.print_recreate_columnfamily(ksdef.name, cf, out)
 
     def print_recreate_usertype(self, ksname, utname, out):
@@ -1159,129 +1010,17 @@ class Shell(cmd.Cmd):
 
         Writes output to the given out stream.
         """
-        layout = self.get_columnfamily_layout(ksname, cfname)
-        cfname = self.cql_protect_name(layout.name)
-
-        out.write("CREATE TABLE %s (\n" % cfname)
-
-        for col in layout.columns:
-            colname = self.cql_protect_name(col.name)
-            coltype = col.cqltype
-
-            # Reversed types only matter for clustering order, not column definitions
-            if issubclass(coltype, ReversedType):
-                coltype = coltype.subtypes[0]
-
-            out.write("  %s %s" % (colname, coltype.cql_parameterized_type()))
-            if col.is_static():
-                out.write(" static")
-            out.write(",\n")
-
-        out.write("  PRIMARY KEY (")
-        partkeynames = self.cql_protect_names(layout.partition_key_columns)
-        if len(partkeynames) > 1:
-            partkey = "(%s)" % ', '.join(partkeynames)
-        else:
-            partkey = partkeynames[0]
-        pk_parts = [partkey] + self.cql_protect_names(layout.clustering_key_columns)
-        out.write(', '.join(pk_parts) + ')')
-
-        out.write("\n)")
-        joiner = 'WITH'
-
-        if layout.is_compact_storage():
-            out.write(' WITH COMPACT STORAGE')
-            joiner = 'AND'
-
-        # check if we need a CLUSTERING ORDER BY clause
-        if layout.clustering_key_columns:
-            # get a list of clustering component types
-            if issubclass(layout.comparator, CompositeType):
-                clustering_types = layout.comparator.subtypes
-            else:
-                clustering_types = [layout.comparator]
-
-            # only write CLUSTERING ORDER clause of we have >= 1 DESC item
-            if any(issubclass(t, ReversedType) for t in clustering_types):
-                if layout.is_compact_storage():
-                    out.write(' AND\n ')
-                else:
-                    out.write(' WITH')
-                out.write(' CLUSTERING ORDER BY (')
-
-                clustering_names = self.cql_protect_names(layout.clustering_key_columns)
-
-                inner = []
-                for colname, coltype in zip(clustering_names, clustering_types):
-                    ordering = "DESC" if issubclass(coltype, ReversedType) else "ASC"
-                    inner.append("%s %s" % (colname, ordering))
-                out.write(", ".join(inner))
-
-                out.write(")")
-                joiner = "AND"
-
-        cf_opts = []
-        compaction_strategy = trim_if_present(getattr(layout, 'compaction_strategy_class'),
-                                              'org.apache.cassandra.db.compaction.')
-        for cql3option, layoutoption in cqlruleset.columnfamily_layout_options:
-            if layoutoption is None:
-                layoutoption = cql3option
-            optval = getattr(layout, layoutoption, None)
-            if optval is None:
-                if layoutoption == 'bloom_filter_fp_chance':
-                    if compaction_strategy == 'LeveledCompactionStrategy':
-                        optval = 0.1
-                    else:
-                        optval = 0.01
-                else:
-                    continue
-            elif layoutoption == 'compaction_strategy_class':
-                optval = compaction_strategy
-            cf_opts.append((cql3option, self.cql_protect_value(optval)))
-        for cql3option, layoutoption, _ in cqlruleset.columnfamily_layout_map_options:
-            if layoutoption is None:
-                layoutoption = cql3option
-            optmap = getattr(layout, layoutoption, {})
-            if layoutoption == 'compression_parameters':
-                compclass = optmap.get('sstable_compression')
-                if compclass is not None:
-                    optmap['sstable_compression'] = \
-                            trim_if_present(compclass, 'org.apache.cassandra.io.compress.')
-            if layoutoption == 'compaction_strategy_options':
-                optmap['class'] = compaction_strategy
-
-            cf_opts.append((cql3option, optmap))
-
-        if cf_opts:
-            for optname, optval in cf_opts:
-                if isinstance(optval, dict):
-                    optval = '{%s}' % ', '.join(['%s: %s' % (self.cql_protect_value(k),
-                                                             self.cql_protect_value(v))
-                                                 for (k, v) in optval.items()])
-                out.write(" %s\n  %s=%s" % (joiner, optname, optval))
-                joiner = 'AND'
-        out.write(";\n")
-
-        for col in [ c for c in layout.columns if c.index_name is not None ]:
-            out.write('\n')
-            if col.index_type != 'CUSTOM':
-                out.write('CREATE INDEX %s ON %s (%s);\n'
-                             % (col.index_name, cfname, self.cql_protect_name(col.name)))
-            else:
-                out.write("CREATE CUSTOM INDEX %s ON %s (%s) USING '%s';\n"
-                             % (col.index_name,
-                                cfname,
-                                self.cql_protect_name(col.name),
-                                col.index_options[u'class_name']))
+        out.write(self.get_table_meta(ksname, cfname).export_as_string())
+        out.write("\n")
 
     def describe_keyspaces(self):
         print
-        cmd.Cmd.columnize(self, self.get_keyspace_names())
+        cmd.Cmd.columnize(self, protect_names(self.get_keyspace_names()))
         print
 
     def describe_keyspace(self, ksname):
         print
-        self.print_recreate_keyspace(self.get_keyspace(ksname), sys.stdout)
+        self.print_recreate_keyspace(self.get_keyspace_meta(ksname), sys.stdout)
         print
 
     def describe_columnfamily(self, ksname, cfname):
@@ -1295,26 +1034,26 @@ class Shell(cmd.Cmd):
         print
         if ksname is None:
             for k in self.get_keyspaces():
-                name = self.cql_protect_name(k.name)
+                name = protect_name(k.name)
                 print 'Keyspace %s' % (name,)
                 print '---------%s' % ('-' * len(name))
-                cmd.Cmd.columnize(self, self.get_columnfamily_names(k.name))
+                cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(k.name)))
                 print
         else:
-            cmd.Cmd.columnize(self, self.get_columnfamily_names(ksname))
+            cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(ksname)))
             print
 
     def describe_usertypes(self, ksname):
         print
         if ksname is None:
             for k in self.get_keyspaces():
-                name = self.cql_protect_name(k.name)
+                name = protect_name(k.name)
                 print 'Keyspace %s' % (name,)
                 print '---------%s' % ('-' * len(name))
-                cmd.Cmd.columnize(self, self.get_usertype_names(k.name))
+                cmd.Cmd.columnize(self, protect_names(self.get_usertype_names(k.name)))
                 print
         else:
-            cmd.Cmd.columnize(self, self.get_usertype_names(ksname))
+            cmd.Cmd.columnize(self, protect_names(self.get_usertype_names(ksname)))
             print
 
     def describe_usertype(self, ksname, typename):
@@ -1327,15 +1066,16 @@ class Shell(cmd.Cmd):
     def describe_cluster(self):
         print '\nCluster: %s' % self.get_cluster_name()
         p = trim_if_present(self.get_partitioner(), 'org.apache.cassandra.dht.')
-        print 'Partitioner: %s' % p
-        snitch = trim_if_present(self.get_snitch(), 'org.apache.cassandra.locator.')
-        print 'Snitch: %s\n' % snitch
+        print 'Partitioner: %s\n' % p
+        # TODO: snitch?
+        #snitch = trim_if_present(self.get_snitch(), 'org.apache.cassandra.locator.')
+        #print 'Snitch: %s\n' % snitch
         if self.current_keyspace is not None \
         and self.current_keyspace != 'system':
             print "Range ownership:"
             ring = self.get_ring()
-            for entry in ring:
-                print ' %39s  [%s]' % (entry.start_token, ', '.join(entry.endpoints))
+            for entry in ring.items():
+                print ' %39s  [%s]' % (str(entry[0].value), ', '.join([host.address for host in entry[1]]))
             print
 
     def describe_schema(self, include_system=False):
@@ -1516,7 +1256,7 @@ class Shell(cmd.Cmd):
         try:
             if header:
                 linesource.next()
-            layout = self.get_columnfamily_layout(ks, cf)
+            table_meta = self.get_table_meta(ks, cf)
             rownum = -1
             reader = csv.reader(linesource, **dialect_options)
             for rownum, row in enumerate(reader):
@@ -1525,7 +1265,7 @@ class Shell(cmd.Cmd):
                                   "(%d instead of %d)."
                                   % (rownum, reader.line_num, len(row), len(columns)))
                     return rownum
-                if not self.do_import_row(columns, nullval, layout, row):
+                if not self.do_import_row(columns, nullval, table_meta, row):
                     self.printerr("Aborting import at record #%d (line %d). "
                                   "Previously-inserted values still present."
                                   % (rownum, reader.line_num))
@@ -1537,40 +1277,39 @@ class Shell(cmd.Cmd):
                 print
         return rownum + 1
 
-    def do_import_row(self, columns, nullval, layout, row):
+    def do_import_row(self, columns, nullval, table_meta, row):
         rowmap = {}
+        clustering_key_columns = [col.name for col in table_meta.clustering_key]
         for name, value in zip(columns, row):
-            type = layout.get_column(name).cqltype
-            if issubclass(type, ReversedType):
-                type = type.subtypes[0]
-            cqltype = type.cql_parameterized_type()
+            type = table_meta.columns[name].data_type
+            cqltype = table_meta.columns[name].typestring
 
             if value != nullval:
                 if cqltype in ('ascii', 'text', 'timestamp', 'inet'):
-                    rowmap[name] = self.cql_protect_value(value)
+                    rowmap[name] = protect_value(value)
                 else:
                     rowmap[name] = value
-            elif name in layout.clustering_key_columns and not type.empty_binary_ok:
+            elif name in clustering_key_columns and not type.empty_binary_ok:
                 rowmap[name] = 'blobAs%s(0x)' % cqltype.title()
             else:
                 rowmap[name] = 'null'
-        return self.do_import_insert(layout, rowmap)
+        return self.do_import_insert(table_meta, rowmap)
 
-    def do_import_insert(self, layout, rowmap):
+    def do_import_insert(self, table_meta, rowmap):
         # would be nice to be able to use a prepared query here, but in order
         # to use that interface, we'd need to have all the input as native
         # values already, reading them from text just like the various
         # Cassandra cql types do. Better just to submit them all as intact
         # CQL string literals and let Cassandra do its thing.
         query = 'INSERT INTO %s.%s (%s) VALUES (%s)' % (
-            self.cql_protect_name(layout.keyspace_name),
-            self.cql_protect_name(layout.columnfamily_name),
-            ', '.join(self.cql_protect_names(rowmap.keys())),
+            protect_name(table_meta.keyspace.name),
+            protect_name(table_meta.name),
+            ', '.join(protect_names(rowmap.keys())),
             ', '.join(rowmap.values())
         )
         if self.debug:
             print 'Import using CQL: %s' % query
-        return self.perform_statement_untraced(query)
+        return self.perform_simple_statement(SimpleStatement(query))
 
     def perform_csv_export(self, ks, cf, columns, fname, opts):
         dialect_options = self.csv_dialect_defaults.copy()
@@ -1603,20 +1342,17 @@ class Shell(cmd.Cmd):
                 self.printerr("Can't open %r for writing: %s" % (fname, e))
                 return 0
         try:
-            self.prep_export_dump(ks, cf, columns)
+            dump = self.prep_export_dump(ks, cf, columns)
             writer = csv.writer(csvdest, **dialect_options)
             if header:
-                writer.writerow([d[0] for d in self.cursor.description])
+                writer.writerow(columns)
             rows = 0
-            while True:
-                row = self.cursor.fetchone()
-                if row is None:
-                    break
-                fmt = lambda v, t: \
-                    format_value(v, t, output_encoding=encoding, nullval=nullval,
+            for row in dump:
+                fmt = lambda v: \
+                    format_value(v, output_encoding=encoding, nullval=nullval,
                                  time_format=self.display_time_format,
                                  float_precision=self.display_float_precision).strval
-                writer.writerow(map(fmt, row, self.cursor.column_types))
+                writer.writerow(map(fmt, row))
                 rows += 1
         finally:
             if do_close:
@@ -1626,14 +1362,15 @@ class Shell(cmd.Cmd):
     def prep_export_dump(self, ks, cf, columns):
         if columns is None:
             columns = self.get_column_names(ks, cf)
-        columnlist = ', '.join(self.cql_protect_names(columns))
+        columnlist = ', '.join(protect_names(columns))
         # this limit is pretty awful. would be better to use row-key-paging, so
         # that the dump could be pretty easily aborted if necessary, but that
         # can be kind of tricky with cql3. Punt for now, until the real cursor
         # API is added in CASSANDRA-4415.
+        # https://datastax-oss.atlassian.net/browse/PYTHON-16
         query = 'SELECT %s FROM %s.%s LIMIT 99999999' \
-                % (columnlist, self.cql_protect_name(ks), self.cql_protect_name(cf))
-        self.cursor.execute(query)
+                % (columnlist, protect_name(ks), protect_name(cf))
+        return self.session.execute(query)
 
     def do_show(self, parsed):
         """
@@ -1664,7 +1401,7 @@ class Shell(cmd.Cmd):
             self.show_host()
         elif showwhat.startswith('session'):
             session_id = parsed.get_binding('sessionid').lower()
-            self.show_session(session_id)
+            self.show_session(UUID(session_id))
         else:
             self.printerr('Wait, how do I show %r?' % (showwhat,))
 
@@ -1695,7 +1432,7 @@ class Shell(cmd.Cmd):
         except IOError, e:
             self.printerr('Could not open %r: %s' % (fname, e))
             return
-        subshell = Shell(self.hostname, self.port, self.transport_factory,
+        subshell = Shell(self.hostname, self.port,
                          color=self.color, encoding=self.encoding, stdin=f,
                          tty=False, use_conn=self.conn, cqlver=self.cql_version,
                          display_time_format=self.display_time_format,
@@ -1870,10 +1607,10 @@ class Shell(cmd.Cmd):
         """
         level = parsed.get_binding('level')
         if level is None:
-            print 'Current consistency level is %s.' % (self.cursor.consistency_level,)
+            print 'Current consistency level is %s.' % (self.consistency_level)
             return
 
-        self.cursor.consistency_level = level.upper()
+        self.consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
         print 'Consistency level set to %s.' % (level.upper(),)
 
     def do_exit(self, parsed=None):
@@ -1883,6 +1620,7 @@ class Shell(cmd.Cmd):
         Exits cqlsh.
         """
         self.stop = True
+        self.conn.shutdown()
     do_quit = do_exit
 
     def do_debug(self, parsed):
@@ -1942,18 +1680,6 @@ class Shell(cmd.Cmd):
             text = '%s:%d:%s' % (self.stdin.name, self.lineno, text)
         self.writeresult(text, color, newline=newline, out=sys.stderr)
 
-    @staticmethod
-    def could_change_schema(statement):
-        import re
-        return re.match(r"(alter|create|drop)\s+type", statement.lower())
-
-
-class ErrorHandlingSchemaDecoder(cql.decoders.SchemaDecoder):
-    def name_decode_error(self, err, namebytes, expectedtype):
-        return DecodeError(namebytes, err, expectedtype)
-
-    def value_decode_error(self, err, namebytes, valuebytes, expectedtype):
-        return DecodeError(valuebytes, err, expectedtype, colname=namebytes)
 
 def option_with_default(cparser_getter, section, option, default=None):
     try:
@@ -1988,21 +1714,6 @@ def should_use_color():
         pass
     return True
 
-def load_factory(name):
-    """
-    Attempts to load a transport factory function given its fully qualified
-    name, e.g. "cqlshlib.tfactory.regular_transport_factory"
-    """
-    parts = name.split('.')
-    module = ".".join(parts[:-1])
-    try:
-        t = __import__(module)
-        for part in parts[1:]:
-            t = getattr(t, part)
-        return t
-    except (ImportError, AttributeError):
-        sys.exit("Can't locate transport factory function %s" % name)
-
 def read_options(cmdlineargs, environment):
     configs = ConfigParser.SafeConfigParser()
     configs.read(CONFIG_FILE)
@@ -2011,8 +1722,6 @@ def read_options(cmdlineargs, environment):
     optvalues.username = option_with_default(configs.get, 'authentication', 'username')
     optvalues.password = option_with_default(configs.get, 'authentication', 'password')
     optvalues.keyspace = option_with_default(configs.get, 'authentication', 'keyspace')
-    optvalues.transport_factory = option_with_default(configs.get, 'connection', 'factory',
-                                                      DEFAULT_TRANSPORT_FACTORY)
     optvalues.completekey = option_with_default(configs.get, 'ui', 'completekey',
                                                 DEFAULT_COMPLETEKEY)
     optvalues.color = option_with_default(configs.getboolean, 'ui', 'color')
@@ -2022,6 +1731,8 @@ def read_options(cmdlineargs, environment):
                                                     DEFAULT_FLOAT_PRECISION)
     optvalues.debug = False
     optvalues.file = None
+    optvalues.ssl = False
+
     optvalues.tty = sys.stdin.isatty()
     optvalues.cqlversion = option_with_default(configs.get, 'cql', 'version', DEFAULT_CQLVER)
 
@@ -2041,8 +1752,6 @@ def read_options(cmdlineargs, environment):
     if options.file is not None:
         options.tty = False
 
-    options.transport_factory = load_factory(options.transport_factory)
-
     if optvalues.color in (True, False):
         options.color = optvalues.color
     else:
@@ -2108,14 +1817,11 @@ def main(options, hostname, port):
             sys.exit("Can't open %r: %s" % (options.file, e))
 
     if options.debug:
-        import thrift
-        sys.stderr.write("Using CQL driver: %s\n" % (cql,))
-        sys.stderr.write("Using thrift lib: %s\n" % (thrift,))
+        sys.stderr.write("Using CQL driver: %s\n" % (cassandra,))
 
     try:
         shell = Shell(hostname,
                       port,
-                      options.transport_factory,
                       color=options.color,
                       username=options.username,
                       password=options.password,
@@ -2125,7 +1831,8 @@ def main(options, hostname, port):
                       cqlver=options.cqlversion,
                       keyspace=options.keyspace,
                       display_time_format=options.time_format,
-                      display_float_precision=options.float_precision)
+                      display_float_precision=options.float_precision,
+                      ssl=options.ssl)
     except KeyboardInterrupt:
         sys.exit('Connection aborted.')
     except CQL_ERRORS, e:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/conf/cqlshrc.sample
----------------------------------------------------------------------
diff --git a/conf/cqlshrc.sample b/conf/cqlshrc.sample
index 365defd..ad59787 100644
--- a/conf/cqlshrc.sample
+++ b/conf/cqlshrc.sample
@@ -26,18 +26,20 @@ color = on
 completekey = tab
 
 [cql]
-version = 3.0
+version = 3.1.5
 
 [connection]
 hostname = 127.0.0.1
-port = 9160
-; enable below for ssl
-;factory = cqlshlib.ssl.ssl_transport_factory
+port = 9042
 
 ;[ssl]
 ;certfile = ~/keys/cassandra.cert
 ;; optional - true by default.
 ;validate = true
+;; to be provided when require_client_auth=true
+;userkey = ~/key.pem
+;; to be provided when require_client_auth=true
+;usercert = ~/cert.pem
 
 ;; optional section, overrides default certfile in [ssl] section, if present
 ;[certfiles]

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/lib/cassandra-driver-internal-only-1.0.2.post.zip
----------------------------------------------------------------------
diff --git a/lib/cassandra-driver-internal-only-1.0.2.post.zip b/lib/cassandra-driver-internal-only-1.0.2.post.zip
new file mode 100644
index 0000000..9f6af56
Binary files /dev/null and b/lib/cassandra-driver-internal-only-1.0.2.post.zip differ

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/lib/cql-internal-only-1.4.1.zip
----------------------------------------------------------------------
diff --git a/lib/cql-internal-only-1.4.1.zip b/lib/cql-internal-only-1.4.1.zip
deleted file mode 100644
index fa33a3a..0000000
Binary files a/lib/cql-internal-only-1.4.1.zip and /dev/null differ

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/lib/futures-2.1.6-py2.py3-none-any.zip
----------------------------------------------------------------------
diff --git a/lib/futures-2.1.6-py2.py3-none-any.zip b/lib/futures-2.1.6-py2.py3-none-any.zip
new file mode 100644
index 0000000..50bd78b
Binary files /dev/null and b/lib/futures-2.1.6-py2.py3-none-any.zip differ

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/lib/thrift-python-internal-only-0.9.1.zip
----------------------------------------------------------------------
diff --git a/lib/thrift-python-internal-only-0.9.1.zip b/lib/thrift-python-internal-only-0.9.1.zip
deleted file mode 100644
index 7949ea6..0000000
Binary files a/lib/thrift-python-internal-only-0.9.1.zip and /dev/null differ

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 3522d1c..ae03cde 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -14,16 +14,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import re
-from warnings import warn
 from .cqlhandling import CqlParsingRuleSet, Hint
-from cql.cqltypes import (cql_types, lookup_casstype, CompositeType, UTF8Type,
-                          ColumnToCollectionType, CounterColumnType, DateType)
-from . import helptopics
+from cassandra.metadata import maybe_escape_name
+from cassandra.metadata import escape_name
+
 
-simple_cql_types = set(cql_types)
+simple_cql_types = set(('ascii', 'bigint', 'blob', 'boolean', 'counter', 'decimal', 'double', 'float', 'inet', 'int',
+                        'text', 'timestamp', 'timeuuid', 'uuid', 'varchar', 'varint'))
 simple_cql_types.difference_update(('set', 'map', 'list'))
 
+from . import helptopics
 cqldocs = helptopics.CQL3HelpTopics()
 
 try:
@@ -31,10 +31,6 @@ try:
 except ImportError:
     import simplejson as json
 
-# temporarily have this here until a newer cassandra-dbapi2 is bundled with C*
-class TimestampType(DateType):
-    pass
-
 class UnexpectedTableStructure(UserWarning):
     def __init__(self, msg):
         self.msg = msg
@@ -99,6 +95,10 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
         'SERIAL'
     )
 
+    maybe_escape_name = staticmethod(maybe_escape_name)
+
+    escape_name = staticmethod(escape_name)
+
     @classmethod
     def escape_value(cls, value):
         if value is None:
@@ -112,26 +112,6 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
         return "'%s'" % value.replace("'", "''")
 
     @staticmethod
-    def escape_name(name):
-        return '"%s"' % name.replace('"', '""')
-
-    valid_cql3_word_re = re.compile(r'^[a-z][0-9a-z_]*$')
-
-    @classmethod
-    def is_valid_cql3_name(cls, s):
-        if s is None:
-            return False
-        if s.lower() in cls.keywords - cls.unreserved_keywords:
-            return False
-        return cls.valid_cql3_word_re.match(s) is not None
-
-    @classmethod
-    def maybe_escape_name(cls, name):
-        if cls.is_valid_cql3_name(name):
-            return name
-        return cls.escape_name(name)
-
-    @staticmethod
     def dequote_name(name):
         name = name.strip()
         if name == '':
@@ -154,7 +134,7 @@ CqlRuleSet = Cql3ParsingRuleSet()
 # convenience for remainder of module
 shorthands = ('completer_for', 'explain_completion',
               'dequote_value', 'dequote_name',
-              'escape_value', 'escape_name',
+              'escape_value',
               'maybe_escape_name')
 
 for shorthand in shorthands:
@@ -575,12 +555,12 @@ def unreserved_keyword_completer(ctxt, cass):
     # names, CF names, property values, etc.
     return ()
 
-def get_cf_layout(ctxt, cass):
+def get_table_meta(ctxt, cass):
     ks = ctxt.get_binding('ksname', None)
     if ks is not None:
         ks = dequote_name(ks)
     cf = dequote_name(ctxt.get_binding('cfname'))
-    return cass.get_columnfamily_layout(ks, cf)
+    return cass.get_table_meta(ks, cf)
 
 def get_ut_layout(ctxt, cass):
     ks = ctxt.get_binding('ksname', None)
@@ -632,8 +612,8 @@ def select_order_column_completer(ctxt, cass):
         keyname = ctxt.get_binding('rel_lhs', ())
         if not keyname:
             return [Hint("Can't ORDER BY here: need to specify partition key in WHERE clause")]
-    layout = get_cf_layout(ctxt, cass)
-    order_by_candidates = layout.clustering_key_columns[:]
+    layout = get_table_meta(ctxt, cass)
+    order_by_candidates = [col.name for col in layout.clustering_key]
     if len(order_by_candidates) > len(prev_order_cols):
         return [maybe_escape_name(order_by_candidates[len(prev_order_cols)])]
     return [Hint('No more orderable columns here.')]
@@ -644,26 +624,26 @@ def relation_token_word_completer(ctxt, cass):
 
 @completer_for('relation', 'rel_tokname')
 def relation_token_subject_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    return [layout.partition_key_columns[0]]
+    layout = get_table_meta(ctxt, cass)
+    return [key.name for key in layout.partition_key]
 
 @completer_for('relation', 'rel_lhs')
 def select_relation_lhs_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    filterable = set((layout.partition_key_columns[0], layout.clustering_key_columns[0]))
-    already_filtered_on = map(dequote_name, ctxt.get_binding('rel_lhs'))
-    for num in range(1, len(layout.partition_key_columns)):
-        if layout.partition_key_columns[num - 1] in already_filtered_on:
-            filterable.add(layout.partition_key_columns[num])
+    layout = get_table_meta(ctxt, cass)
+    filterable = set((layout.partition_key[0].name, layout.clustering_key[0].name))
+    already_filtered_on = map(dequote_name, ctxt.get_binding('rel_lhs', ()))
+    for num in range(1, len(layout.partition_key)):
+        if layout.partition_key[num - 1].name in already_filtered_on:
+            filterable.add(layout.partition_key[num].name)
         else:
             break
-    for num in range(1, len(layout.clustering_key_columns)):
-        if layout.clustering_key_columns[num - 1] in already_filtered_on:
-            filterable.add(layout.clustering_key_columns[num])
+    for num in range(1, len(layout.clustering_key)):
+        if layout.clustering_key[num - 1].name in already_filtered_on:
+            filterable.add(layout.clustering_key[num].name)
         else:
             break
-    for cd in layout.columns:
-        if cd.index_name is not None:
+    for cd in layout.columns.values():
+        if cd.index:
             filterable.add(cd.name)
     return map(maybe_escape_name, filterable)
 
@@ -687,26 +667,34 @@ syntax_rules += r'''
                 ;
 '''
 
+def regular_column_names(table_meta):
+    if not table_meta or not table_meta.columns:
+        return []
+    regular_coulmns = list(set(table_meta.columns.keys())
+                           - set([key.name for key in table_meta.partition_key])
+                           - set([key.name for key in table_meta.clustering_key]))
+    return regular_coulmns
+
 @completer_for('insertStatement', 'colname')
 def insert_colname_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     colnames = set(map(dequote_name, ctxt.get_binding('colname', ())))
-    keycols = layout.primary_key_columns
+    keycols = layout.primary_key
     for k in keycols:
-        if k not in colnames:
-            return [maybe_escape_name(k)]
-    normalcols = set(layout.regular_columns) - colnames
+        if k.name not in colnames:
+            return [maybe_escape_name(k.name)]
+    normalcols = set(regular_column_names(layout)) - colnames
     return map(maybe_escape_name, normalcols)
 
 @completer_for('insertStatement', 'newval')
 def insert_newval_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     insertcols = map(dequote_name, ctxt.get_binding('colname'))
     valuesdone = ctxt.get_binding('newval', ())
     if len(valuesdone) >= len(insertcols):
         return []
     curcol = insertcols[len(valuesdone)]
-    cqltype = layout.get_column(curcol).cqltype
+    cqltype = layout.columns[curcol].data_type
     coltype = cqltype.typename
     if coltype in ('map', 'set'):
         return ['{']
@@ -719,7 +707,7 @@ def insert_newval_completer(ctxt, cass):
 
 @completer_for('insertStatement', 'valcomma')
 def insert_valcomma_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     numcols = len(ctxt.get_binding('colname', ()))
     numvals = len(ctxt.get_binding('newval', ()))
     if numcols > numvals:
@@ -757,14 +745,14 @@ def insert_option_completer(ctxt, cass):
 
 @completer_for('assignment', 'updatecol')
 def update_col_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    return map(maybe_escape_name, layout.regular_columns)
+    layout = get_table_meta(ctxt, cass)
+    return map(maybe_escape_name, regular_column_names(layout))
 
 @completer_for('assignment', 'update_rhs')
 def update_countername_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     curcol = dequote_name(ctxt.get_binding('updatecol', ''))
-    cqltype = layout.get_column(curcol).cqltype
+    cqltype = layout.columns[curcol].data_type
     coltype = cqltype.typename
     if coltype == 'counter':
         return [maybe_escape_name(curcol)]
@@ -776,15 +764,15 @@ def update_countername_completer(ctxt, cass):
 
 @completer_for('assignment', 'counterop')
 def update_counterop_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     curcol = dequote_name(ctxt.get_binding('updatecol', ''))
-    return ['+', '-'] if layout.is_counter_col(curcol) else []
+    return ['+', '-'] if layout.columns[curcol].data_type.typename == 'counter' else []
 
 @completer_for('assignment', 'inc')
 def update_counter_inc_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     curcol = dequote_name(ctxt.get_binding('updatecol', ''))
-    if layout.is_counter_col(curcol):
+    if layout.columns[curcol].data_type.typename == 'counter':
         return [Hint('<wholenumber>')]
     return []
 
@@ -805,9 +793,9 @@ def update_listcol_completer(ctxt, cass):
 
 @completer_for('assignment', 'indexbracket')
 def update_indexbracket_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
+    layout = get_table_meta(ctxt, cass)
     curcol = dequote_name(ctxt.get_binding('updatecol', ''))
-    coltype = layout.get_column(curcol).cqltype.typename
+    coltype = layout.columns[curcol].data_type.typename
     if coltype in ('map', 'list'):
         return ['[']
     return []
@@ -833,8 +821,8 @@ def delete_opt_completer(ctxt, cass):
 
 @completer_for('deleteSelector', 'delcol')
 def delete_delcol_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    return map(maybe_escape_name, layout.regular_columns)
+    layout = get_table_meta(ctxt, cass)
+    return map(maybe_escape_name, regular_column_names(layout))
 
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
@@ -987,8 +975,8 @@ explain_completion('createUserTypeStatement', 'newcol', '<new_field_name>')
 
 @completer_for('createIndexStatement', 'col')
 def create_index_col_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    colnames = [cd.name for cd in layout.columns if cd.index_name is None]
+    layout = get_table_meta(ctxt, cass)
+    colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
 syntax_rules += r'''
@@ -1034,8 +1022,8 @@ syntax_rules += r'''
 
 @completer_for('alterInstructions', 'existcol')
 def alter_table_col_completer(ctxt, cass):
-    layout = get_cf_layout(ctxt, cass)
-    cols = [md.name for md in layout.columns]
+    layout = get_table_meta(ctxt, cass)
+    cols = [str(md) for md in layout.columns]
     return map(maybe_escape_name, cols)
 
 @completer_for('alterTypeInstructions', 'existcol')
@@ -1119,133 +1107,14 @@ def username_name_completer(ctxt, cass):
     if ctxt.matched[0][0] == 'K_CREATE':
         return [Hint('<username>')]
 
-    cursor = cass.conn.cursor()
-    cursor.execute("LIST USERS")
-    return [maybe_quote(row[0].replace("'", "''")) for row in cursor.fetchall()]
+    session = cass.session
+    return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)
 
-class CqlColumnDef:
-    index_name = None
-    index_type = None
-    component_type = 'regular'
-    component_index = None
-    index_options = {}
-
-    def __init__(self, name, cqltype):
-        self.name = name
-        self.cqltype = cqltype
-        assert name is not None
-
-    @classmethod
-    def from_layout(cls, layout):
-        c = cls(layout[u'column_name'], lookup_casstype(layout[u'validator']))
-        c.component_type = layout[u'type']
-        idx = layout[u'component_index'] # can be None
-        if idx:
-            c.component_index = int(idx)
-        c.index_name = layout[u'index_name']
-        c.index_type = layout[u'index_type']
-        if c.index_type == 'CUSTOM':
-            c.index_options = json.loads(layout[u'index_options'])
-        return c
-
-    def is_static(self):
-        return self.component_type == 'static'
-
-    def __str__(self):
-        indexstr = ' (index %s)' % self.index_name if self.index_name is not None else ''
-        return '<CqlColumnDef %r %r%s>' % (self.name, self.cqltype, indexstr)
-    __repr__ = __str__
-
-class CqlTableDef:
-    """Names of all columns which are grouped into the partition key"""
-    partition_key_columns = ()
-
-    """Names of all columns which are part of the primary key, but not grouped
-       into the partition key"""
-    clustering_key_columns = ()
-
-    """Names of all columns which are part of the primary key, whether or not
-       they are grouped into the partition key"""
-    primary_key_columns = ()
-
-    """Names of all columns which aren't part of the primary key"""
-    regular_columns = ()
-
-    """CqlColumnDef objects for all columns. Use .get_column() to access one
-       by name."""
-    columns = ()
-
-    def __init__(self, name):
-        self.name = name
-
-    @classmethod
-    def from_layout(cls, layout, coldefs):
-        """
-        This constructor accepts a dictionary of column-value pairs from a row
-        of system.schema_columnfamilies, and a sequence of similar dictionaries
-        from corresponding rows in system.schema_columns.
-        """
-        cf = cls(name=layout[u'columnfamily_name'])
-        cf.keyspace = layout[u'keyspace_name']
-        for attr, val in layout.items():
-            setattr(cf, attr.encode('ascii'), val)
-        cf.comparator = lookup_casstype(cf.comparator)
-        for attr in ('compaction_strategy_options', 'compression_parameters', 'caching'):
-            setattr(cf, attr, json.loads(getattr(cf, attr)))
-
-        # deal with columns, filter out empty column names (see CASSANDRA-6139)
-        columns = filter(lambda c: c.name, map(CqlColumnDef.from_layout, coldefs))
-
-        partition_key_cols = filter(lambda c: c.component_type == u'partition_key', columns)
-        partition_key_cols.sort(key=lambda c: c.component_index)
-        cf.partition_key_columns = map(lambda c: c.name, partition_key_cols)
-
-        clustering_key_cols = filter(lambda c: c.component_type == u'clustering_key', columns)
-        clustering_key_cols.sort(key=lambda c: c.component_index)
-        cf.clustering_key_columns = map(lambda c: c.name, clustering_key_cols)
-
-        cf.primary_key_columns = cf.partition_key_columns + cf.clustering_key_columns
-
-        regular_cols = list(set(columns) - set(partition_key_cols) - set(clustering_key_cols))
-        regular_cols.sort(key=lambda c: c.name)
-        cf.regular_columns = map(lambda c: c.name, regular_cols)
-
-        cf.columns = partition_key_cols + clustering_key_cols + regular_cols
-        return cf
-
-    # not perfect, but good enough; please read CFDefinition constructor comments
-    # returns False if we are dealing with a CQL3 table, True otherwise.
-    # 'compact' here means 'needs WITH COMPACT STORAGE option for CREATE TABLE in CQL3'.
-    def is_compact_storage(self):
-        if not issubclass(self.comparator, CompositeType):
-            return True
-        for subtype in self.comparator.subtypes:
-            if issubclass(subtype, ColumnToCollectionType):
-                return False
-        if len(self.clustering_key_columns) == len(self.comparator.subtypes) - 1:
-            if self.comparator.subtypes[-1] is UTF8Type:
-                return False
-        return True
-
-    def is_counter_col(self, colname):
-        try:
-            return bool(self.get_column(colname).cqltype is CounterColumnType)
-        except KeyError:
-            return False
-
-    def get_column(self, colname):
-        col_info = [cm for cm in self.columns if cm.name == colname]
-        if not col_info:
-            raise KeyError("column %r not found" % (colname,))
-        return col_info[0]
-
-    def __str__(self):
-        return '<%s %s.%s>' % (self.__class__.__name__, self.keyspace, self.name)
-    __repr__ = __str__
+from cassandra.cqltypes import lookup_casstype
 
 class UserTypesMeta(object):
     _meta = {}
@@ -1257,12 +1126,12 @@ class UserTypesMeta(object):
     def from_layout(cls, layout):
         result = {}
         for row in layout:
-            ksname = row[u'keyspace_name']
+            ksname = row.keyspace_name
             if ksname not in result:
                 result[ksname] = {}
-            utname = row[u'type_name']
+            utname = row.type_name
 
-            result[ksname][utname] = zip(row[u'column_names'], row[u'column_types'])
+            result[ksname][utname] = zip(row.column_names, row.column_types)
         return cls(meta=result)
 
     def get_usertypes_names(self, keyspace):

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/pylib/cqlshlib/cqlhandling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cqlhandling.py b/pylib/cqlshlib/cqlhandling.py
index 86abf02..fc3dc20 100644
--- a/pylib/cqlshlib/cqlhandling.py
+++ b/pylib/cqlshlib/cqlhandling.py
@@ -17,10 +17,8 @@
 # code for dealing with CQL's syntax, rules, interpretation
 # i.e., stuff that's not necessarily cqlsh-specific
 
-import re
 import traceback
 from . import pylexotron, util
-from cql import cqltypes
 
 Hint = pylexotron.Hint
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index 7a0ef17..73a6213 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -16,11 +16,12 @@
 
 import re
 import time
-import binascii
+import calendar
 import math
 from collections import defaultdict
 from . import wcwidth
 from .displaying import colorme, FormattedValue, DEFAULT_VALUE_COLORS
+from cassandra.cqltypes import EMPTY
 
 unicode_controlchars_re = re.compile(r'[\x00-\x31\x7f-\xa0]')
 controlchars_re = re.compile(r'[\x00-\x31\x7f-\xff]')
@@ -95,11 +96,11 @@ def format_value_default(val, colormap, **_):
 # making format_value a generic function
 _formatters = {}
 
-def format_value(cqltype, val, **kwargs):
-    if val == '' and not cqltype.empty_binary_ok:
-        return format_value_default(val, **kwargs)
-    formatter = _formatters.get(cqltype.typename, format_value_default)
-    return formatter(val, subtypes=cqltype.subtypes, **kwargs)
+def format_value(type, val, **kwargs):
+    if val == EMPTY:
+        return format_value_default('', **kwargs)
+    formatter = _formatters.get(type.__name__, format_value_default)
+    return formatter(val, **kwargs)
 
 def formatter_for(typname):
     def registrator(f):
@@ -107,10 +108,12 @@ def formatter_for(typname):
         return f
     return registrator
 
-@formatter_for('blob')
+@formatter_for('bytearray')
 def format_value_blob(val, colormap, **_):
     bval = '0x' + ''.join('%02x' % ord(c) for c in val)
     return colorme(bval, colormap, 'blob')
+formatter_for('buffer')(format_value_blob)
+
 
 def format_python_formatted_type(val, colormap, color, quote=False):
     bval = str(val)
@@ -118,21 +121,20 @@ def format_python_formatted_type(val, colormap, color, quote=False):
         bval = "'%s'" % bval
     return colorme(bval, colormap, color)
 
-@formatter_for('decimal')
+@formatter_for('Decimal')
 def format_value_decimal(val, colormap, **_):
     return format_python_formatted_type(val, colormap, 'decimal')
 
-@formatter_for('uuid')
+@formatter_for('UUID')
 def format_value_uuid(val, colormap, **_):
     return format_python_formatted_type(val, colormap, 'uuid')
 
-formatter_for('timeuuid')(format_value_uuid)
 
 @formatter_for('inet')
 def formatter_value_inet(val, colormap, quote=False, **_):
     return format_python_formatted_type(val, colormap, 'inet', quote=quote)
 
-@formatter_for('boolean')
+@formatter_for('bool')
 def format_value_boolean(val, colormap, **_):
     return format_python_formatted_type(val, colormap, 'boolean')
 
@@ -146,25 +148,24 @@ def format_floating_point_type(val, colormap, float_precision, **_):
     return colorme(bval, colormap, 'float')
 
 formatter_for('float')(format_floating_point_type)
-formatter_for('double')(format_floating_point_type)
 
 def format_integer_type(val, colormap, **_):
     # base-10 only for now; support others?
     bval = str(val)
     return colorme(bval, colormap, 'int')
 
-formatter_for('bigint')(format_integer_type)
+formatter_for('long')(format_integer_type)
 formatter_for('int')(format_integer_type)
-formatter_for('varint')(format_integer_type)
-formatter_for('counter')(format_integer_type)
 
-@formatter_for('timestamp')
+@formatter_for('date')
 def format_value_timestamp(val, colormap, time_format, quote=False, **_):
-    bval = strftime(time_format, val)
+    bval = strftime(time_format, calendar.timegm(val.utctimetuple()))
     if quote:
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+formatter_for('datetime')(format_value_timestamp)
+
 def strftime(time_format, seconds):
     local = time.localtime(seconds)
     formatted = time.strftime(time_format, local)
@@ -182,7 +183,7 @@ def strftime(time_format, seconds):
     hours, minutes = divmod(abs(offset) / 60, 60)
     return formatted[:-5] + sign + '{0:0=2}{1:0=2}'.format(hours, minutes)
 
-@formatter_for('text')
+@formatter_for('str')
 def format_value_text(val, encoding, colormap, quote=False, **_):
     escapedval = val.replace(u'\\', u'\\\\')
     if quote:
@@ -195,11 +196,11 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
     return color_text(bval, colormap, displaywidth)
 
 # name alias
-formatter_for('varchar')(format_value_text)
+formatter_for('unicode')(format_value_text)
 
-def format_simple_collection(subtype, val, lbracket, rbracket, encoding,
+def format_simple_collection(val, lbracket, rbracket, encoding,
                              colormap, time_format, float_precision, nullval):
-    subs = [format_value(subtype, sval, encoding=encoding, colormap=colormap,
+    subs = [format_value(type(sval), sval, encoding=encoding, colormap=colormap,
                          time_format=time_format, float_precision=float_precision,
                          nullval=nullval, quote=True)
             for sval in val]
@@ -211,24 +212,27 @@ def format_simple_collection(subtype, val, lbracket, rbracket, encoding,
     return FormattedValue(bval, coloredval, displaywidth)
 
 @formatter_for('list')
-def format_value_list(val, encoding, colormap, time_format, float_precision, subtypes, nullval, **_):
-    return format_simple_collection(subtypes[0], val, '[', ']', encoding, colormap,
+def format_value_list(val, encoding, colormap, time_format, float_precision, nullval, **_):
+    return format_simple_collection(val, '[', ']', encoding, colormap,
                                     time_format, float_precision, nullval)
+formatter_for('tuple')(format_value_list)
 
 @formatter_for('set')
-def format_value_set(val, encoding, colormap, time_format, float_precision, subtypes, nullval, **_):
-    return format_simple_collection(subtypes[0], sorted(val), '{', '}', encoding, colormap,
+def format_value_set(val, encoding, colormap, time_format, float_precision, nullval, **_):
+    return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval)
+formatter_for('frozenset')(format_value_set)
+formatter_for('sortedset')(format_value_set)
+
 
-@formatter_for('map')
-def format_value_map(val, encoding, colormap, time_format, float_precision, subtypes, nullval, **_):
-    def subformat(v, subtype):
-        return format_value(subtype, v, encoding=encoding, colormap=colormap,
+@formatter_for('dict')
+def format_value_map(val, encoding, colormap, time_format, float_precision, nullval, **_):
+    def subformat(v):
+        return format_value(type(v), v, encoding=encoding, colormap=colormap,
                             time_format=time_format, float_precision=float_precision,
                             nullval=nullval, quote=True)
 
-    subkeytype, subvaltype = subtypes
-    subs = [(subformat(k, subkeytype), subformat(v, subvaltype)) for (k, v) in sorted(val.items())]
+    subs = [(subformat(k), subformat(v)) for (k, v) in sorted(val.items())]
     bval = '{' + ', '.join(k.strval + ': ' + v.strval for (k, v) in subs) + '}'
     lb, comma, colon, rb = [colormap['collection'] + s + colormap['reset']
                             for s in ('{', ', ', ': ', '}')]
@@ -237,17 +241,19 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, subt
                + rb
     displaywidth = 4 * len(subs) + sum(k.displaywidth + v.displaywidth for (k, v) in subs)
     return FormattedValue(bval, coloredval, displaywidth)
+formatter_for('OrderedDict')(format_value_map)
 
-def format_value_utype(val, encoding, colormap, time_format, float_precision, subtypes, nullval, **_):
-    def format_field_value(v, subtype):
-        return format_value(subtype, v, encoding=encoding, colormap=colormap,
+
+def format_value_utype(val, encoding, colormap, time_format, float_precision, nullval, **_):
+    def format_field_value(v):
+        return format_value(type(v), v, encoding=encoding, colormap=colormap,
                             time_format=time_format, float_precision=float_precision,
                             nullval=nullval, quote=True)
 
     def format_field_name(name):
         return format_value_text(name, encoding=encoding, colormap=colormap, quote=False)
 
-    subs = [(format_field_name(k), format_field_value(v, subtypes[index])) for (index, (k, v)) in enumerate(val)]
+    subs = [(format_field_name(k), format_field_value(v)) for (k, v) in val._asdict().items() if v is not None]
     bval = '{' + ', '.join(k.strval + ': ' + v.strval for (k, v) in subs) + '}'
     lb, comma, colon, rb = [colormap['collection'] + s + colormap['reset']
                             for s in ('{', ', ', ': ', '}')]
@@ -255,4 +261,4 @@ def format_value_utype(val, encoding, colormap, time_format, float_precision, su
                  + comma.join(k.coloredval + colon + v.coloredval for (k, v) in subs) \
                  + rb
     displaywidth = 4 * len(subs) + sum(k.displaywidth + v.displaywidth for (k, v) in subs)
-    return FormattedValue(bval, coloredval, displaywidth)
\ No newline at end of file
+    return FormattedValue(bval, coloredval, displaywidth)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/pylib/cqlshlib/helptopics.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/helptopics.py b/pylib/cqlshlib/helptopics.py
index 710aa74..9848c71 100644
--- a/pylib/cqlshlib/helptopics.py
+++ b/pylib/cqlshlib/helptopics.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from cql.cqltypes import cql_types
+from .cql3handling import simple_cql_types
 
 class CQLHelpTopics(object):
     def get_help_topics(self):
@@ -25,7 +25,7 @@ class CQLHelpTopics(object):
 
     def help_types(self):
         print "\n        CQL types recognized by this version of cqlsh:\n"
-        for t in cql_types:
+        for t in simple_cql_types:
             print '          ' + t
         print """
         For information on the various recognizable input formats for these

http://git-wip-us.apache.org/repos/asf/cassandra/blob/caf609cf/pylib/cqlshlib/ssl.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/ssl.py b/pylib/cqlshlib/ssl.py
deleted file mode 100644
index 3400b40..0000000
--- a/pylib/cqlshlib/ssl.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# 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 os
-import sys
-import ConfigParser
-from thrift.transport import TSSLSocket, TTransport
-
-def ssl_transport_factory(host, port, env, config_file):
-    """
-    SSL Thrift transport factory function.
-
-    Params:
-    * host .........: hostname of Cassandra node.
-    * port .........: port number to connect to.
-    * env ..........: environment variables. SSL factory will use, if passed,
-                      SSL_CERTFILE and SSL_VALIDATE variables.
-    * config_file ..: path to cqlsh config file (usually ~/.cqlshrc).
-                      SSL factory will use, if set, certfile and validate
-                      options in [ssl] section, as well as host to certfile
-                      mapping in [certfiles] section.
-
-    [certfiles] section is optional, 'validate' setting in [ssl] section is
-    optional too. If validation is enabled then SSL certfile must be provided
-    either in the config file or as an environment variable.
-    Environment variables override any options set in cqlsh config file.
-    """
-    configs = ConfigParser.SafeConfigParser()
-    configs.read(config_file)
-
-    def get_option(section, option):
-        try:
-            return configs.get(section, option)
-        except ConfigParser.Error:
-            return None
-
-    ssl_validate = env.get('SSL_VALIDATE')
-    if ssl_validate is None:
-        ssl_validate = get_option('ssl', 'validate')
-    ssl_validate = ssl_validate is None or ssl_validate.lower() != 'false'
-
-    ssl_certfile = env.get('SSL_CERTFILE')
-    if ssl_certfile is None:
-        ssl_certfile = get_option('certfiles', host)
-    if ssl_certfile is None:
-        ssl_certfile = get_option('ssl', 'certfile')
-    if ssl_validate and ssl_certfile is None:
-        sys.exit("Validation is enabled; SSL transport factory requires a valid certfile "
-                 "to be specified. Please provide path to the certfile in [ssl] section "
-                 "as 'certfile' option in %s (or use [certfiles] section) or set SSL_CERTFILE "
-                 "environment variable." % (config_file,))
-    if not ssl_certfile is None:
-        ssl_certfile = os.path.expanduser(ssl_certfile)
-
-    tsocket = TSSLSocket.TSSLSocket(host, port, ca_certs=ssl_certfile,
-                                    validate=ssl_validate)
-    return TTransport.TFramedTransport(tsocket)


Mime
View raw message