You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by ja...@apache.org on 2018/01/15 14:07:35 UTC

[01/23] cassandra git commit: More PEP8 compliance for cqlsh

Repository: cassandra
Updated Branches:
  refs/heads/cassandra-2.1 d4fd82be5 -> f8d73a3ac
  refs/heads/cassandra-2.2 b800f3c76 -> 503aec74a
  refs/heads/cassandra-3.0 51bf51813 -> 685dde10e
  refs/heads/cassandra-3.11 36375f8b5 -> 02bbdd634
  refs/heads/trunk 1e58a53ca -> 6d324f9d7


More PEP8 compliance for cqlsh

patch by Michael Kjellman; reviewed by Jay Zhuang for CASSANDRA-14021


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

Branch: refs/heads/cassandra-2.1
Commit: f8d73a3acb00d807d09aa33e1612c89389b18480
Parents: d4fd82b
Author: Michael Kjellman <kj...@apple.com>
Authored: Tue Nov 14 20:51:37 2017 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 05:56:44 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 +-
 bin/cqlsh                      |  4 ++++
 pylib/cqlshlib/copyutil.py     |  6 +++---
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b4e6f75..6e1ca85 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
 2.1.20
- * 
+ * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 
 2.1.19
  * Add storage port options to sstableloader (CASSANDRA-13844)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 6317ec9..30840db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -83,6 +83,7 @@ def find_zip(libprefix):
         if zips:
             return max(zips)   # probably the highest version, if multiple
 
+
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
@@ -522,6 +523,8 @@ def show_warning_without_quoting_line(message, category, filename, lineno, file=
         file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
     except IOError:
         pass
+
+
 warnings.showwarning = show_warning_without_quoting_line
 warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 
@@ -2213,6 +2216,7 @@ def main(options, hostname, port):
     if batch_mode and shell.statement_error:
         sys.exit(2)
 
+
 # always call this regardless of module name: when a sub-process is spawned
 # on Windows then the module name is not __main__, see CASSANDRA-9304
 insert_driver_hooks()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py
index 3a45353..85e2678 100644
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@ -191,7 +191,7 @@ class OneWayChannels(object):
         for ch in self.channels:
             try:
                 ch.close()
-            except:
+            except Exception:
                 pass
 
 
@@ -1967,8 +1967,8 @@ class ImportConversion(object):
             pk_values = []
             for i in partition_key_indexes:
                 val = serialize(i, row[i])
-                l = len(val)
-                pk_values.append(struct.pack(">H%dsB" % l, l, val, 0))
+                length = len(val)
+                pk_values.append(struct.pack(">H%dsB" % length, length, val, 0))
             return b"".join(pk_values)
 
         if len(partition_key_indexes) == 1:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 029e0c7..012e383 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,6 +34,7 @@ class UnexpectedTableStructure(UserWarning):
     def __str__(self):
         return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
 
+
 SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 NONALTERBALE_KEYSPACES = ('system')
 
@@ -109,6 +110,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
             cqlword = cqlword[1:-1].replace("''", "'")
         return cqlword
 
+
 CqlRuleSet = Cql3ParsingRuleSet()
 
 # convenience for remainder of module
@@ -306,6 +308,7 @@ def prop_equals_completer(ctxt, cass):
             return ()
     return ['=']
 
+
 completer_for('property', 'propeq')(prop_equals_completer)
 
 
@@ -529,6 +532,7 @@ def ks_name_completer(ctxt, cass):
 def cf_ks_name_completer(ctxt, cass):
     return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
 
+
 completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 
 
@@ -538,6 +542,7 @@ def cf_ks_dot_completer(ctxt, cass):
         return ['.']
     return []
 
+
 completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 
 
@@ -554,6 +559,7 @@ def cf_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, cfnames)
 
+
 completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
 
 completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
@@ -606,6 +612,7 @@ def working_on_keyspace(ctxt):
         return True
     return False
 
+
 syntax_rules += r'''
 <useStatement> ::= "USE" <keyspaceName>
                  ;
@@ -694,6 +701,7 @@ def select_relation_lhs_completer(ctxt, cass):
 def select_count_star_completer(ctxt, cass):
     return ['*']
 
+
 explain_completion('selector', 'colname')
 
 syntax_rules += r'''
@@ -770,6 +778,7 @@ def insert_option_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <updateStatement> ::= "UPDATE" cf=<columnFamilyName>
                         ( "USING" [updateopt]=<usingOption>
@@ -863,6 +872,7 @@ def update_indexbracket_completer(ctxt, cass):
         return ['[']
     return []
 
+
 syntax_rules += r'''
 <deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
                         "FROM" cf=<columnFamilyName>
@@ -890,6 +900,7 @@ def delete_delcol_completer(ctxt, cass):
     layout = get_table_meta(ctxt, cass)
     return map(maybe_escape_name, regular_column_names(layout))
 
+
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
                         ( "USING" [batchopt]=<usingOption>
@@ -912,6 +923,7 @@ def batch_opt_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
                       ;
@@ -931,6 +943,7 @@ def create_ks_wat_completer(ctxt, cass):
         return ['KEYSPACE']
     return ['KEYSPACE', 'SCHEMA']
 
+
 syntax_rules += r'''
 <createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
                                     ( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
@@ -979,6 +992,7 @@ def create_cf_wat_completer(ctxt, cass):
         return ['TABLE']
     return ['TABLE', 'COLUMNFAMILY']
 
+
 explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
 explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
 
@@ -1033,6 +1047,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
         return ()
     return [',']
 
+
 syntax_rules += r'''
 
 <idxName> ::= <identifier>
@@ -1065,6 +1080,7 @@ def create_index_col_completer(ctxt, cass):
     colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
+
 syntax_rules += r'''
 <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                           ;
@@ -1113,6 +1129,7 @@ def idx_ks_idx_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, idxnames)
 
+
 syntax_rules += r'''
 <alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
                                <alterInstructions>
@@ -1149,6 +1166,7 @@ def alter_type_field_completer(ctxt, cass):
     fields = [tuple[0] for tuple in layout]
     return map(maybe_escape_name, fields)
 
+
 explain_completion('alterInstructions', 'newcol', '<new_column_name>')
 explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
 
@@ -1227,6 +1245,7 @@ def username_name_completer(ctxt, cass):
     session = cass.session
     return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
+
 syntax_rules += r'''
 <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
@@ -1251,6 +1270,7 @@ def alter_type_field_completer(ctxt, cass):
     names = get_trigger_names(ctxt, cass)
     return map(maybe_escape_name, names)
 
+
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/displaying.py b/pylib/cqlshlib/displaying.py
index 7b260c2..09068ca 100644
--- a/pylib/cqlshlib/displaying.py
+++ b/pylib/cqlshlib/displaying.py
@@ -99,6 +99,7 @@ class FormattedValue:
         """
         return self.coloredval + self._pad(width, fill)
 
+
 DEFAULT_VALUE_COLORS = dict(
     default=YELLOW,
     text=YELLOW,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index abb4896..eac1810 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -38,6 +38,7 @@ def _show_control_chars(match):
         txt = txt[1:-1]
     return txt
 
+
 bits_to_turn_red_re = re.compile(r'\\([^uUx]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|U[0-9a-fA-F]{8})')
 
 
@@ -49,6 +50,7 @@ def _make_turn_bits_red_f(color1, color2):
         return color1 + txt + color2
     return _turn_bits_red
 
+
 default_null_placeholder = 'null'
 default_time_format = ''
 default_float_precision = 3
@@ -101,6 +103,7 @@ def format_value_default(val, colormap, **_):
     bval = controlchars_re.sub(_show_control_chars, escapedval)
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap)
 
+
 # Mapping cql type base names ("int", "map", etc) to formatter functions,
 # making format_value a generic function
 _formatters = {}
@@ -128,6 +131,8 @@ def formatter_for(typname):
 def format_value_blob(val, colormap, **_):
     bval = '0x' + binascii.hexlify(str(val))
     return colorme(bval, colormap, 'blob')
+
+
 formatter_for('buffer')(format_value_blob)
 
 
@@ -188,6 +193,7 @@ def format_floating_point_type(val, colormap, float_precision, decimal_sep=None,
 
     return colorme(bval, colormap, 'float')
 
+
 formatter_for('float')(format_floating_point_type)
 
 
@@ -196,6 +202,7 @@ def format_integer_type(val, colormap, thousands_sep=None, **_):
     bval = format_integer_with_thousands_sep(val, thousands_sep) if thousands_sep else str(val)
     return colorme(bval, colormap, 'int')
 
+
 # We can get rid of this in cassandra-2.2
 if sys.version_info >= (2, 7):
     def format_integer_with_thousands_sep(val, thousands_sep=','):
@@ -221,6 +228,7 @@ def format_value_timestamp(val, colormap, time_format, quote=False, **_):
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+
 formatter_for('datetime')(format_value_timestamp)
 
 
@@ -241,6 +249,7 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
 
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
 
+
 # name alias
 formatter_for('unicode')(format_value_text)
 
@@ -286,6 +295,8 @@ def format_value_set(val, encoding, colormap, time_format, float_precision, null
     return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval,
                                     decimal_sep, thousands_sep, boolean_styles)
+
+
 formatter_for('frozenset')(format_value_set)
 # This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 # and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
@@ -314,6 +325,8 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, null
         + 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)
 formatter_for('OrderedMap')(format_value_map)
 formatter_for('OrderedMapSerializedKey')(format_value_map)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index 9cf0f4e..7b11eac 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -518,6 +518,7 @@ class ParsingRuleSet:
         pattern.match(ctxt, completions)
         return completions
 
+
 import sys
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/wcwidth.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/wcwidth.py b/pylib/cqlshlib/wcwidth.py
index bc55c31..985fd41 100644
--- a/pylib/cqlshlib/wcwidth.py
+++ b/pylib/cqlshlib/wcwidth.py
@@ -94,6 +94,7 @@ def bisearch(ucs, table):
             return 1
     return 0
 
+
 # The following two functions define the column width of an ISO 10646
 # character as follows:
 #
@@ -178,6 +179,7 @@ combining = (
     (0xE0100, 0xE01EF)
 )
 
+
 # sorted list of non-overlapping intervals of East Asian Ambiguous
 # characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 ambiguous = (
@@ -321,6 +323,7 @@ def wcwidth_cjk(c):
 def wcswidth_cjk(s):
     return mk_wcswidth_cjk(map(ord, s))
 
+
 if __name__ == "__main__":
     samples = (
         ('MUSIC SHARP SIGN', 1),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[04/23] cassandra git commit: More PEP8 compliance for cqlsh

Posted by ja...@apache.org.
More PEP8 compliance for cqlsh

patch by Michael Kjellman; reviewed by Jay Zhuang for CASSANDRA-14021


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

Branch: refs/heads/cassandra-3.0
Commit: f8d73a3acb00d807d09aa33e1612c89389b18480
Parents: d4fd82b
Author: Michael Kjellman <kj...@apple.com>
Authored: Tue Nov 14 20:51:37 2017 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 05:56:44 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 +-
 bin/cqlsh                      |  4 ++++
 pylib/cqlshlib/copyutil.py     |  6 +++---
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b4e6f75..6e1ca85 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
 2.1.20
- * 
+ * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 
 2.1.19
  * Add storage port options to sstableloader (CASSANDRA-13844)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 6317ec9..30840db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -83,6 +83,7 @@ def find_zip(libprefix):
         if zips:
             return max(zips)   # probably the highest version, if multiple
 
+
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
@@ -522,6 +523,8 @@ def show_warning_without_quoting_line(message, category, filename, lineno, file=
         file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
     except IOError:
         pass
+
+
 warnings.showwarning = show_warning_without_quoting_line
 warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 
@@ -2213,6 +2216,7 @@ def main(options, hostname, port):
     if batch_mode and shell.statement_error:
         sys.exit(2)
 
+
 # always call this regardless of module name: when a sub-process is spawned
 # on Windows then the module name is not __main__, see CASSANDRA-9304
 insert_driver_hooks()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py
index 3a45353..85e2678 100644
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@ -191,7 +191,7 @@ class OneWayChannels(object):
         for ch in self.channels:
             try:
                 ch.close()
-            except:
+            except Exception:
                 pass
 
 
@@ -1967,8 +1967,8 @@ class ImportConversion(object):
             pk_values = []
             for i in partition_key_indexes:
                 val = serialize(i, row[i])
-                l = len(val)
-                pk_values.append(struct.pack(">H%dsB" % l, l, val, 0))
+                length = len(val)
+                pk_values.append(struct.pack(">H%dsB" % length, length, val, 0))
             return b"".join(pk_values)
 
         if len(partition_key_indexes) == 1:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 029e0c7..012e383 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,6 +34,7 @@ class UnexpectedTableStructure(UserWarning):
     def __str__(self):
         return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
 
+
 SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 NONALTERBALE_KEYSPACES = ('system')
 
@@ -109,6 +110,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
             cqlword = cqlword[1:-1].replace("''", "'")
         return cqlword
 
+
 CqlRuleSet = Cql3ParsingRuleSet()
 
 # convenience for remainder of module
@@ -306,6 +308,7 @@ def prop_equals_completer(ctxt, cass):
             return ()
     return ['=']
 
+
 completer_for('property', 'propeq')(prop_equals_completer)
 
 
@@ -529,6 +532,7 @@ def ks_name_completer(ctxt, cass):
 def cf_ks_name_completer(ctxt, cass):
     return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
 
+
 completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 
 
@@ -538,6 +542,7 @@ def cf_ks_dot_completer(ctxt, cass):
         return ['.']
     return []
 
+
 completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 
 
@@ -554,6 +559,7 @@ def cf_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, cfnames)
 
+
 completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
 
 completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
@@ -606,6 +612,7 @@ def working_on_keyspace(ctxt):
         return True
     return False
 
+
 syntax_rules += r'''
 <useStatement> ::= "USE" <keyspaceName>
                  ;
@@ -694,6 +701,7 @@ def select_relation_lhs_completer(ctxt, cass):
 def select_count_star_completer(ctxt, cass):
     return ['*']
 
+
 explain_completion('selector', 'colname')
 
 syntax_rules += r'''
@@ -770,6 +778,7 @@ def insert_option_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <updateStatement> ::= "UPDATE" cf=<columnFamilyName>
                         ( "USING" [updateopt]=<usingOption>
@@ -863,6 +872,7 @@ def update_indexbracket_completer(ctxt, cass):
         return ['[']
     return []
 
+
 syntax_rules += r'''
 <deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
                         "FROM" cf=<columnFamilyName>
@@ -890,6 +900,7 @@ def delete_delcol_completer(ctxt, cass):
     layout = get_table_meta(ctxt, cass)
     return map(maybe_escape_name, regular_column_names(layout))
 
+
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
                         ( "USING" [batchopt]=<usingOption>
@@ -912,6 +923,7 @@ def batch_opt_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
                       ;
@@ -931,6 +943,7 @@ def create_ks_wat_completer(ctxt, cass):
         return ['KEYSPACE']
     return ['KEYSPACE', 'SCHEMA']
 
+
 syntax_rules += r'''
 <createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
                                     ( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
@@ -979,6 +992,7 @@ def create_cf_wat_completer(ctxt, cass):
         return ['TABLE']
     return ['TABLE', 'COLUMNFAMILY']
 
+
 explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
 explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
 
@@ -1033,6 +1047,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
         return ()
     return [',']
 
+
 syntax_rules += r'''
 
 <idxName> ::= <identifier>
@@ -1065,6 +1080,7 @@ def create_index_col_completer(ctxt, cass):
     colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
+
 syntax_rules += r'''
 <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                           ;
@@ -1113,6 +1129,7 @@ def idx_ks_idx_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, idxnames)
 
+
 syntax_rules += r'''
 <alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
                                <alterInstructions>
@@ -1149,6 +1166,7 @@ def alter_type_field_completer(ctxt, cass):
     fields = [tuple[0] for tuple in layout]
     return map(maybe_escape_name, fields)
 
+
 explain_completion('alterInstructions', 'newcol', '<new_column_name>')
 explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
 
@@ -1227,6 +1245,7 @@ def username_name_completer(ctxt, cass):
     session = cass.session
     return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
+
 syntax_rules += r'''
 <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
@@ -1251,6 +1270,7 @@ def alter_type_field_completer(ctxt, cass):
     names = get_trigger_names(ctxt, cass)
     return map(maybe_escape_name, names)
 
+
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/displaying.py b/pylib/cqlshlib/displaying.py
index 7b260c2..09068ca 100644
--- a/pylib/cqlshlib/displaying.py
+++ b/pylib/cqlshlib/displaying.py
@@ -99,6 +99,7 @@ class FormattedValue:
         """
         return self.coloredval + self._pad(width, fill)
 
+
 DEFAULT_VALUE_COLORS = dict(
     default=YELLOW,
     text=YELLOW,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index abb4896..eac1810 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -38,6 +38,7 @@ def _show_control_chars(match):
         txt = txt[1:-1]
     return txt
 
+
 bits_to_turn_red_re = re.compile(r'\\([^uUx]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|U[0-9a-fA-F]{8})')
 
 
@@ -49,6 +50,7 @@ def _make_turn_bits_red_f(color1, color2):
         return color1 + txt + color2
     return _turn_bits_red
 
+
 default_null_placeholder = 'null'
 default_time_format = ''
 default_float_precision = 3
@@ -101,6 +103,7 @@ def format_value_default(val, colormap, **_):
     bval = controlchars_re.sub(_show_control_chars, escapedval)
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap)
 
+
 # Mapping cql type base names ("int", "map", etc) to formatter functions,
 # making format_value a generic function
 _formatters = {}
@@ -128,6 +131,8 @@ def formatter_for(typname):
 def format_value_blob(val, colormap, **_):
     bval = '0x' + binascii.hexlify(str(val))
     return colorme(bval, colormap, 'blob')
+
+
 formatter_for('buffer')(format_value_blob)
 
 
@@ -188,6 +193,7 @@ def format_floating_point_type(val, colormap, float_precision, decimal_sep=None,
 
     return colorme(bval, colormap, 'float')
 
+
 formatter_for('float')(format_floating_point_type)
 
 
@@ -196,6 +202,7 @@ def format_integer_type(val, colormap, thousands_sep=None, **_):
     bval = format_integer_with_thousands_sep(val, thousands_sep) if thousands_sep else str(val)
     return colorme(bval, colormap, 'int')
 
+
 # We can get rid of this in cassandra-2.2
 if sys.version_info >= (2, 7):
     def format_integer_with_thousands_sep(val, thousands_sep=','):
@@ -221,6 +228,7 @@ def format_value_timestamp(val, colormap, time_format, quote=False, **_):
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+
 formatter_for('datetime')(format_value_timestamp)
 
 
@@ -241,6 +249,7 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
 
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
 
+
 # name alias
 formatter_for('unicode')(format_value_text)
 
@@ -286,6 +295,8 @@ def format_value_set(val, encoding, colormap, time_format, float_precision, null
     return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval,
                                     decimal_sep, thousands_sep, boolean_styles)
+
+
 formatter_for('frozenset')(format_value_set)
 # This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 # and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
@@ -314,6 +325,8 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, null
         + 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)
 formatter_for('OrderedMap')(format_value_map)
 formatter_for('OrderedMapSerializedKey')(format_value_map)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index 9cf0f4e..7b11eac 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -518,6 +518,7 @@ class ParsingRuleSet:
         pattern.match(ctxt, completions)
         return completions
 
+
 import sys
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/wcwidth.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/wcwidth.py b/pylib/cqlshlib/wcwidth.py
index bc55c31..985fd41 100644
--- a/pylib/cqlshlib/wcwidth.py
+++ b/pylib/cqlshlib/wcwidth.py
@@ -94,6 +94,7 @@ def bisearch(ucs, table):
             return 1
     return 0
 
+
 # The following two functions define the column width of an ISO 10646
 # character as follows:
 #
@@ -178,6 +179,7 @@ combining = (
     (0xE0100, 0xE01EF)
 )
 
+
 # sorted list of non-overlapping intervals of East Asian Ambiguous
 # characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 ambiguous = (
@@ -321,6 +323,7 @@ def wcwidth_cjk(c):
 def wcswidth_cjk(s):
     return mk_wcswidth_cjk(map(ord, s))
 
+
 if __name__ == "__main__":
     samples = (
         ('MUSIC SHARP SIGN', 1),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[18/23] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by ja...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


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

Branch: refs/heads/trunk
Commit: 685dde10e3a6b4a27936893840f536fa25ae9da5
Parents: 51bf518 503aec7
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:01:38 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:03:22 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  3 ++-
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 0453ddd,055a35d..8696653
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -25,67 -2,11 +25,68 @@@ Merged from 2.2
   * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
-- * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.2.11
 +
 +3.0.15
 + * Improve TRUNCATE performance (CASSANDRA-13909)
 + * Implement short read protection on partition boundaries (CASSANDRA-13595)
 + * Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)
 + * Filter header only commit logs before recovery (CASSANDRA-13918)
 + * AssertionError prepending to a list (CASSANDRA-13149)
 + * Fix support for SuperColumn tables (CASSANDRA-12373)
 + * Handle limit correctly on tables with strict liveness (CASSANDRA-13883)
 + * Fix missing original update in TriggerExecutor (CASSANDRA-13894)
 + * Remove non-rpc-ready nodes from counter leader candidates (CASSANDRA-13043)
 + * Improve short read protection performance (CASSANDRA-13794)
 + * Fix sstable reader to support range-tombstone-marker for multi-slices (CASSANDRA-13787)
 + * Fix short read protection for tables with no clustering columns (CASSANDRA-13880)
 + * Make isBuilt volatile in PartitionUpdate (CASSANDRA-13619)
 + * Prevent integer overflow of timestamps in CellTest and RowsTest (CASSANDRA-13866)
 + * Fix counter application order in short read protection (CASSANDRA-12872)
 + * Don't block RepairJob execution on validation futures (CASSANDRA-13797)
 + * Wait for all management tasks to complete before shutting down CLSM (CASSANDRA-13123)
 + * INSERT statement fails when Tuple type is used as clustering column with default DESC order (CASSANDRA-13717)
 + * Fix pending view mutations handling and cleanup batchlog when there are local and remote paired mutations (CASSANDRA-13069)
 + * Improve config validation and documentation on overflow and NPE (CASSANDRA-13622)
 + * Range deletes in a CAS batch are ignored (CASSANDRA-13655)
 + * Avoid assertion error when IndexSummary > 2G (CASSANDRA-12014)
 + * Change repair midpoint logging for tiny ranges (CASSANDRA-13603)
 + * Better handle corrupt final commitlog segment (CASSANDRA-11995)
 + * StreamingHistogram is not thread safe (CASSANDRA-13756)
 + * Fix MV timestamp issues (CASSANDRA-11500)
 + * Better tolerate improperly formatted bcrypt hashes (CASSANDRA-13626) 
 + * Fix race condition in read command serialization (CASSANDRA-13363)
 + * Enable segement creation before recovering commitlogs (CASSANDRA-13587)
 + * Fix AssertionError in short read protection (CASSANDRA-13747)
 + * Don't skip corrupted sstables on startup (CASSANDRA-13620)
 + * Fix the merging of cells with different user type versions (CASSANDRA-13776)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13640)
 + * Potential AssertionError during ReadRepair of range tombstone and partition deletions (CASSANDRA-13719)
 + * Don't let stress write warmup data if n=0 (CASSANDRA-13773)
 + * Gossip thread slows down when using batch commit log (CASSANDRA-12966)
 + * Randomize batchlog endpoint selection with only 1 or 2 racks (CASSANDRA-12884)
 + * Fix digest calculation for counter cells (CASSANDRA-13750)
 + * Fix ColumnDefinition.cellValueType() for non-frozen collection and change SSTabledump to use type.toJSONString() (CASSANDRA-13573)
 + * Skip materialized view addition if the base table doesn't exist (CASSANDRA-13737)
 + * Drop table should remove corresponding entries in dropped_columns table (CASSANDRA-13730)
 + * Log warn message until legacy auth tables have been migrated (CASSANDRA-13371)
 + * Fix incorrect [2.1 <- 3.0] serialization of counter cells created in 2.0 (CASSANDRA-13691)
 + * Fix invalid writetime for null cells (CASSANDRA-13711)
 + * Fix ALTER TABLE statement to atomically propagate changes to the table and its MVs (CASSANDRA-12952)
 + * Fixed ambiguous output of nodetool tablestats command (CASSANDRA-13722)
 + * JMXEnabledThreadPoolExecutor with corePoolSize equal to maxPoolSize (Backport CASSANDRA-13329)
 + * Fix Digest mismatch Exception if hints file has UnknownColumnFamily (CASSANDRA-13696)
 + * Purge tombstones created by expired cells (CASSANDRA-13643)
 + * Make concat work with iterators that have different subsets of columns (CASSANDRA-13482)
 + * Set test.runners based on cores and memory size (CASSANDRA-13078)
 + * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557)
 + * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606)
 + * Fix secondary index queries on COMPACT tables (CASSANDRA-13627)
 + * Nodetool listsnapshots output is missing a newline, if there are no snapshots (CASSANDRA-13568)
 + * sstabledump reports incorrect usage for argument order (CASSANDRA-13532)
 +Merged from 2.2:
   * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
   * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
   * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 2a8b560,8224ad9..0f42e6e
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,8 -34,9 +34,9 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
 -NONALTERBALE_KEYSPACES = ('system')
 +SYSTEM_KEYSPACES = ('system', 'system_schema', 'system_traces', 'system_auth', 'system_distributed')
 +NONALTERBALE_KEYSPACES = ('system', 'system_schema')
  
  
  class Cql3ParsingRuleSet(CqlParsingRuleSet):
@@@ -579,8 -571,8 +582,9 @@@ def ks_name_completer(ctxt, cass)
  def cf_ks_name_completer(ctxt, cass):
      return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
  
+ 
  completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 +completer_for('materializedViewName', 'ksname')(cf_ks_name_completer)
  
  
  def cf_ks_dot_completer(ctxt, cass):
@@@ -589,8 -581,8 +593,9 @@@
          return ['.']
      return []
  
+ 
  completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 +completer_for('materializedViewName', 'dot')(cf_ks_dot_completer)
  
  
  @completer_for('columnFamilyName', 'cfname')
@@@ -607,19 -599,6 +612,20 @@@ def cf_name_completer(ctxt, cass)
      return map(maybe_escape_name, cfnames)
  
  
 +@completer_for('materializedViewName', 'mvname')
 +def mv_name_completer(ctxt, cass):
 +    ks = ctxt.get_binding('ksname', None)
 +    if ks is not None:
 +        ks = dequote_name(ks)
 +    try:
 +        mvnames = cass.get_materialized_view_names(ks)
 +    except Exception:
 +        if ks is None:
 +            return ()
 +        raise
 +    return map(maybe_escape_name, mvnames)
 +
++
  completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
  
  completer_for('userTypeName', 'dot')(cf_ks_dot_completer)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[14/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
Merge branch 'cassandra-2.1' into cassandra-2.2


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

Branch: refs/heads/cassandra-3.0
Commit: 503aec74a56a5aada7398bf38b67ceb8743b027e
Parents: b800f3c f8d73a3
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 05:58:04 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:01:14 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 266ed14,6e1ca85..055a35d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,25 -1,9 +1,27 @@@
 -2.1.20
 +2.2.12
 + * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
 + * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
 + * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
++Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.1.19
 +2.2.11
 + * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
 + * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)
 + * Fix compaction and flush exception not captured (CASSANDRA-13833)
 + * Make BatchlogManagerMBean.forceBatchlogReplay() blocking (CASSANDRA-13809)
 + * Uncaught exceptions in Netty pipeline (CASSANDRA-13649)
 + * Prevent integer overflow on exabyte filesystems (CASSANDRA-13067) 
 + * Fix queries with LIMIT and filtering on clustering columns (CASSANDRA-11223)
 + * Fix potential NPE when resume bootstrap fails (CASSANDRA-13272)
 + * Fix toJSONString for the UDT, tuple and collection types (CASSANDRA-13592)
 + * Fix nested Tuples/UDTs validation (CASSANDRA-13646)
 + * Remove unused max_value_size_in_mb config setting from yaml (CASSANDRA-13625
 +Merged from 2.1:
   * Add storage port options to sstableloader (CASSANDRA-13844)
 - * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775) 
 + * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775)
   * Clone HeartBeatState when building gossip messages. Make its generation/version volatile (CASSANDRA-13700)
  
  


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[11/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
Merge branch 'cassandra-2.1' into cassandra-2.2


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

Branch: refs/heads/cassandra-2.2
Commit: 503aec74a56a5aada7398bf38b67ceb8743b027e
Parents: b800f3c f8d73a3
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 05:58:04 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:01:14 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 266ed14,6e1ca85..055a35d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,25 -1,9 +1,27 @@@
 -2.1.20
 +2.2.12
 + * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
 + * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
 + * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
++Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.1.19
 +2.2.11
 + * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
 + * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)
 + * Fix compaction and flush exception not captured (CASSANDRA-13833)
 + * Make BatchlogManagerMBean.forceBatchlogReplay() blocking (CASSANDRA-13809)
 + * Uncaught exceptions in Netty pipeline (CASSANDRA-13649)
 + * Prevent integer overflow on exabyte filesystems (CASSANDRA-13067) 
 + * Fix queries with LIMIT and filtering on clustering columns (CASSANDRA-11223)
 + * Fix potential NPE when resume bootstrap fails (CASSANDRA-13272)
 + * Fix toJSONString for the UDT, tuple and collection types (CASSANDRA-13592)
 + * Fix nested Tuples/UDTs validation (CASSANDRA-13646)
 + * Remove unused max_value_size_in_mb config setting from yaml (CASSANDRA-13625
 +Merged from 2.1:
   * Add storage port options to sstableloader (CASSANDRA-13844)
 - * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775) 
 + * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775)
   * Clone HeartBeatState when building gossip messages. Make its generation/version volatile (CASSANDRA-13700)
  
  


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[17/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
Merge branch 'cassandra-2.1' into cassandra-2.2


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

Branch: refs/heads/cassandra-3.11
Commit: 503aec74a56a5aada7398bf38b67ceb8743b027e
Parents: b800f3c f8d73a3
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 05:58:04 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:01:14 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 266ed14,6e1ca85..055a35d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,25 -1,9 +1,27 @@@
 -2.1.20
 +2.2.12
 + * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
 + * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
 + * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
++Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.1.19
 +2.2.11
 + * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
 + * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)
 + * Fix compaction and flush exception not captured (CASSANDRA-13833)
 + * Make BatchlogManagerMBean.forceBatchlogReplay() blocking (CASSANDRA-13809)
 + * Uncaught exceptions in Netty pipeline (CASSANDRA-13649)
 + * Prevent integer overflow on exabyte filesystems (CASSANDRA-13067) 
 + * Fix queries with LIMIT and filtering on clustering columns (CASSANDRA-11223)
 + * Fix potential NPE when resume bootstrap fails (CASSANDRA-13272)
 + * Fix toJSONString for the UDT, tuple and collection types (CASSANDRA-13592)
 + * Fix nested Tuples/UDTs validation (CASSANDRA-13646)
 + * Remove unused max_value_size_in_mb config setting from yaml (CASSANDRA-13625
 +Merged from 2.1:
   * Add storage port options to sstableloader (CASSANDRA-13844)
 - * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775) 
 + * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775)
   * Clone HeartBeatState when building gossip messages. Make its generation/version volatile (CASSANDRA-13700)
  
  


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[06/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/copyutil.py
index b72b517,85e2678..c9c5829
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@@ -150,37 -129,28 +150,37 @@@ class SendingChannel(object)
      def num_pending(self):
          return self.pending_messages.qsize() if self.pending_messages else 0
  
 -    def recv(self):
 -        with self.rlock:
 -            return self.reader.recv()
 +    def close(self):
 +        self.pipe.close()
 +
 +
 +class SendingChannels(object):
 +    """
 +    A group of one way channels for sending messages.
 +    """
 +    def __init__(self, num_channels):
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [SendingChannel(p) for p in self.pipes]
 +        self.num_channels = num_channels
  
      def close(self):
 -        self.reader.close()
 -        self.writer.close()
 +        for ch in self.channels:
 +            try:
 +                ch.close()
-             except:
++            except Exception:
 +                pass
  
  
 -class OneWayChannels(object):
 +class ReceivingChannels(object):
      """
 -    A group of one way channels.
 +    A group of one way channels for receiving messages.
      """
      def __init__(self, num_channels):
 -        self.channels = [OneWayChannel() for _ in xrange(num_channels)]
 -        self._readers = [ch.reader for ch in self.channels]
 -        self._rlocks = [ch.rlock for ch in self.channels]
 -        self._rlocks_by_readers = dict([(ch.reader, ch.rlock) for ch in self.channels])
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [ReceivingChannel(p) for p in self.pipes]
 +        self._readers = [p.reader for p in self.pipes]
 +        self._rlocks = [p.rlock for p in self.pipes]
 +        self._rlocks_by_readers = dict([(p.reader, p.rlock) for p in self.pipes])
          self.num_channels = num_channels
  
          self.recv = self.recv_select if IS_LINUX else self.recv_polling

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 897ee16,012e383..8224ad9
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,7 -34,8 +34,8 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 +SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
  NONALTERBALE_KEYSPACES = ('system')
  
  
@@@ -785,10 -691,17 +792,11 @@@ def select_relation_lhs_completer(ctxt
              filterable.add(layout.clustering_key[num].name)
          else:
              break
 -    for cd in layout.columns.values():
 -        if cd.index:
 -            filterable.add(cd.name)
 +    for idx in layout.indexes.itervalues():
 +        filterable.add(idx.index_options["target"])
      return map(maybe_escape_name, filterable)
  
+ 
 -@completer_for('selectClause', 'star')
 -def select_count_star_completer(ctxt, cass):
 -    return ['*']
 -
 -
  explain_completion('selector', 'colname')
  
  syntax_rules += r'''
@@@ -1178,12 -1076,11 +1193,13 @@@ explain_completion('createUserTypeState
  
  @completer_for('createIndexStatement', 'col')
  def create_index_col_completer(ctxt, cass):
 +    """ Return the columns for which an index doesn't exist yet. """
      layout = get_table_meta(ctxt, cass)
 -    colnames = [cd.name for cd in layout.columns.values() if not cd.index]
 +    idx_targets = [idx.index_options["target"] for idx in layout.indexes.itervalues()]
 +    colnames = [cd.name for cd in layout.columns.values() if cd.name not in idx_targets]
      return map(maybe_escape_name, colnames)
  
+ 
  syntax_rules += r'''
  <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                            ;
@@@ -1403,20 -1246,6 +1421,21 @@@ def username_name_completer(ctxt, cass)
      return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
  
  
 +@completer_for('rolename', 'role')
 +def rolename_completer(ctxt, cass):
 +    def maybe_quote(name):
 +        if CqlRuleSet.is_valid_cql3_name(name):
 +            return name
 +        return "'%s'" % name
 +
 +    # disable completion for CREATE ROLE.
 +    if ctxt.matched[0][1].upper() == 'CREATE':
 +        return [Hint('<rolename>')]
 +
 +    session = cass.session
 +    return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")]
 +
++
  syntax_rules += r'''
  <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                 "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index dcd08da,eac1810..f88fc5d
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -53,7 -50,9 +54,8 @@@ def _make_turn_bits_red_f(color1, color
          return color1 + txt + color2
      return _turn_bits_red
  
+ 
  default_null_placeholder = 'null'
 -default_time_format = ''
  default_float_precision = 3
  default_colormap = DEFAULT_VALUE_COLORS
  empty_colormap = defaultdict(lambda: '')
@@@ -97,24 -96,7 +99,25 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
 +DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
 +DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 +DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
 +
 +if platform.system() == 'Windows':
 +    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +
 +
 +class DateTimeFormat():
 +
 +    def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +        self.timestamp_format = timestamp_format
 +        self.date_format = date_format
 +        self.nanotime_format = nanotime_format
 +        self.timezone = timezone
 +
 +
  def format_value_default(val, colormap, **_):
      val = str(val)
      escapedval = val.replace('\\', '\\\\')
@@@ -146,8 -129,10 +150,10 @@@ def formatter_for(typname)
  
  @formatter_for('bytearray')
  def format_value_blob(val, colormap, **_):
 -    bval = '0x' + binascii.hexlify(str(val))
 +    bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
  
  
@@@ -311,14 -290,18 +320,16 @@@ def format_value_tuple(val, encoding, c
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, time_format, float_precision, nullval,
 +def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
      return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 -                                    time_format, float_precision, nullval,
 +                                    date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
 -# This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 -# and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
 -formatter_for('SortedSet')(format_value_set)
  formatter_for('sortedset')(format_value_set)
 +formatter_for('SortedSet')(format_value_set)
  
  
  @formatter_for('dict')


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[16/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/bin/cqlsh.py
----------------------------------------------------------------------
diff --cc bin/cqlsh.py
index 1f63826,0000000..e242d42
mode 100644,000000..100644
--- a/bin/cqlsh.py
+++ b/bin/cqlsh.py
@@@ -1,2588 -1,0 +1,2592 @@@
 +#!/bin/sh
 +# -*- mode: Python -*-
 +
 +# 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.
 +
 +""":"
 +# bash code here; finds a suitable python interpreter and execs this file.
 +# prefer unqualified "python" if suitable:
 +python -c 'import sys; sys.exit(not (0x020700b0 < sys.hexversion < 0x03000000))' 2>/dev/null \
 +    && exec python "$0" "$@"
 +for pyver in 2.7; do
 +    which python$pyver > /dev/null 2>&1 && exec python$pyver "$0" "$@"
 +done
 +echo "No appropriate python interpreter found." >&2
 +exit 1
 +":"""
 +
 +from __future__ import with_statement
 +
 +import cmd
 +import codecs
 +import ConfigParser
 +import csv
 +import getpass
 +import optparse
 +import os
 +import platform
 +import sys
 +import traceback
 +import warnings
 +import webbrowser
 +from StringIO import StringIO
 +from contextlib import contextmanager
 +from glob import glob
 +from uuid import UUID
 +
 +if sys.version_info[0] != 2 or sys.version_info[1] != 7:
 +    sys.exit("\nCQL Shell supports only Python 2.7\n")
 +
 +UTF8 = 'utf-8'
 +CP65001 = 'cp65001'  # Win utf-8 variant
 +
 +description = "CQL Shell for Apache Cassandra"
 +version = "5.0.1"
 +
 +readline = None
 +try:
 +    # check if tty first, cause readline doesn't check, and only cares
 +    # about $TERM. we don't want the funky escape code stuff to be
 +    # output if not a tty.
 +    if sys.stdin.isatty():
 +        import readline
 +except ImportError:
 +    pass
 +
 +CQL_LIB_PREFIX = 'cassandra-driver-internal-only-'
 +
 +CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
 +CASSANDRA_CQL_HTML_FALLBACK = 'https://cassandra.apache.org/doc/cql3/CQL-2.2.html'
 +
 +if os.path.exists(CASSANDRA_PATH + '/doc/cql3/CQL.html'):
 +    # default location of local CQL.html
 +    CASSANDRA_CQL_HTML = 'file://' + CASSANDRA_PATH + '/doc/cql3/CQL.html'
 +elif os.path.exists('/usr/share/doc/cassandra/CQL.html'):
 +    # fallback to package file
 +    CASSANDRA_CQL_HTML = 'file:///usr/share/doc/cassandra/CQL.html'
 +else:
 +    # fallback to online version
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +
 +# On Linux, the Python webbrowser module uses the 'xdg-open' executable
 +# to open a file/URL. But that only works, if the current session has been
 +# opened from _within_ a desktop environment. I.e. 'xdg-open' will fail,
 +# if the session's been opened via ssh to a remote box.
 +#
 +# Use 'python' to get some information about the detected browsers.
 +# >>> import webbrowser
 +# >>> webbrowser._tryorder
 +# >>> webbrowser._browser
 +#
 +if len(webbrowser._tryorder) == 0:
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +elif webbrowser._tryorder[0] == 'xdg-open' and os.environ.get('XDG_DATA_DIRS', '') == '':
 +    # only on Linux (some OS with xdg-open)
 +    webbrowser._tryorder.remove('xdg-open')
 +    webbrowser._tryorder.append('xdg-open')
 +
 +# use bundled libs for python-cql and thrift, if available. if there
 +# is a ../lib dir, use bundled libs there preferentially.
 +ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')]
 +myplatform = platform.system()
 +is_win = myplatform == 'Windows'
 +
 +# Workaround for supporting CP65001 encoding on python < 3.3 (https://bugs.python.org/issue13216)
 +if is_win and sys.version_info < (3, 3):
 +    codecs.register(lambda name: codecs.lookup(UTF8) if name == CP65001 else None)
 +
 +if myplatform == 'Linux':
 +    ZIPLIB_DIRS.append('/usr/share/cassandra/lib')
 +
 +if os.environ.get('CQLSH_NO_BUNDLED', ''):
 +    ZIPLIB_DIRS = ()
 +
 +
 +def find_zip(libprefix):
 +    for ziplibdir in ZIPLIB_DIRS:
 +        zips = glob(os.path.join(ziplibdir, libprefix + '*.zip'))
 +        if zips:
 +            return max(zips)   # probably the highest version, if multiple
 +
++
 +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, 'cassandra-driver-' + ver))
 +
 +third_parties = ('futures-', 'six-')
 +
 +for lib in third_parties:
 +    lib_zip = find_zip(lib)
 +    if lib_zip:
 +        sys.path.insert(0, lib_zip)
 +
 +warnings.filterwarnings("ignore", r".*blist.*")
 +try:
 +    import cassandra
 +except ImportError, e:
 +    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))
 +
 +from cassandra.auth import PlainTextAuthProvider
 +from cassandra.cluster import Cluster
 +from cassandra.metadata import (ColumnMetadata, KeyspaceMetadata,
 +                                TableMetadata, protect_name, protect_names)
 +from cassandra.policies import WhiteListRoundRobinPolicy
 +from cassandra.query import SimpleStatement, ordered_dict_factory, TraceUnavailable
 +
 +# cqlsh should run correctly when run out of a Cassandra source tree,
 +# out of an unpacked Cassandra tarball, and after a proper package install.
 +cqlshlibdir = os.path.join(CASSANDRA_PATH, 'pylib')
 +if os.path.isdir(cqlshlibdir):
 +    sys.path.insert(0, cqlshlibdir)
 +
 +from cqlshlib import cql3handling, cqlhandling, pylexotron, sslhandling
 +from cqlshlib.copyutil import ExportTask, ImportTask
 +from cqlshlib.displaying import (ANSI_RESET, BLUE, COLUMN_NAME_COLORS, CYAN,
 +                                 RED, FormattedValue, colorme)
 +from cqlshlib.formatting import (DEFAULT_DATE_FORMAT, DEFAULT_NANOTIME_FORMAT,
 +                                 DEFAULT_TIMESTAMP_FORMAT, DateTimeFormat,
 +                                 format_by_type, format_value_utype,
 +                                 formatter_for)
 +from cqlshlib.tracing import print_trace, print_trace_session
 +from cqlshlib.util import get_file_encoding_bomsize, trim_if_present
 +
 +DEFAULT_HOST = '127.0.0.1'
 +DEFAULT_PORT = 9042
 +DEFAULT_CQLVER = '3.3.1'
 +DEFAULT_PROTOCOL_VERSION = 4
 +DEFAULT_CONNECT_TIMEOUT_SECONDS = 5
 +DEFAULT_REQUEST_TIMEOUT_SECONDS = 10
 +
 +DEFAULT_FLOAT_PRECISION = 5
 +DEFAULT_MAX_TRACE_WAIT = 10
 +
 +if readline is not None and readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +    DEFAULT_COMPLETEKEY = '\t'
 +else:
 +    DEFAULT_COMPLETEKEY = 'tab'
 +
 +cqldocs = None
 +cqlruleset = None
 +
 +epilog = """Connects to %(DEFAULT_HOST)s:%(DEFAULT_PORT)d by default. These
 +defaults can be changed by setting $CQLSH_HOST and/or $CQLSH_PORT. When a
 +host (and optional port number) are given on the command line, they take
 +precedence over any defaults.""" % globals()
 +
 +parser = optparse.OptionParser(description=description, epilog=epilog,
 +                               usage="Usage: %prog [options] [host [port]]",
 +                               version='cqlsh ' + version)
 +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("--browser", dest='browser', help="""The browser to use to display CQL help, where BROWSER can be:
 +                                                    - one of the supported browsers in https://docs.python.org/2/library/webbrowser.html.
 +                                                    - browser path followed by %s, example: /usr/bin/google-chrome-stable %s""")
 +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('--debug', action='store_true',
 +                  help='Show additional debugging information')
 +parser.add_option("--encoding", help="Specify a non-default encoding for output." +
 +                  " (Default: %s)" % (UTF8,))
 +parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.")
 +parser.add_option('--cqlversion', default=DEFAULT_CQLVER,
 +                  help='Specify a particular CQL version (default: %default).'
 +                       ' Examples: "3.0.3", "3.1.0"')
 +parser.add_option("-e", "--execute", help='Execute the statement and quit.')
 +parser.add_option("--connect-timeout", default=DEFAULT_CONNECT_TIMEOUT_SECONDS, dest='connect_timeout',
 +                  help='Specify the connection timeout in seconds (default: %default seconds).')
 +parser.add_option("--request-timeout", default=DEFAULT_REQUEST_TIMEOUT_SECONDS, dest='request_timeout',
 +                  help='Specify the default request timeout in seconds (default: %default seconds).')
 +parser.add_option("-t", "--tty", action='store_true', dest='tty',
 +                  help='Force tty mode (command prompt).')
 +
 +optvalues = optparse.Values()
 +(options, arguments) = parser.parse_args(sys.argv[1:], values=optvalues)
 +
 +# BEGIN history/config definition
 +HISTORY_DIR = os.path.expanduser(os.path.join('~', '.cassandra'))
 +
 +if hasattr(options, 'cqlshrc'):
 +    CONFIG_FILE = options.cqlshrc
 +    if not os.path.exists(CONFIG_FILE):
 +        print '\nWarning: Specified cqlshrc location `%s` does not exist.  Using `%s` instead.\n' % (CONFIG_FILE, HISTORY_DIR)
 +        CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +else:
 +    CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +
 +HISTORY = os.path.join(HISTORY_DIR, 'cqlsh_history')
 +if not os.path.exists(HISTORY_DIR):
 +    try:
 +        os.mkdir(HISTORY_DIR)
 +    except OSError:
 +        print '\nWarning: Cannot create directory at `%s`. Command history will not be saved.\n' % HISTORY_DIR
 +
 +OLD_CONFIG_FILE = os.path.expanduser(os.path.join('~', '.cqlshrc'))
 +if os.path.exists(OLD_CONFIG_FILE):
 +    if os.path.exists(CONFIG_FILE):
 +        print '\nWarning: cqlshrc config files were found at both the old location (%s) and \
 +                the new location (%s), the old config file will not be migrated to the new \
 +                location, and the new location will be used for now.  You should manually \
 +                consolidate the config files at the new location and remove the old file.' \
 +                % (OLD_CONFIG_FILE, CONFIG_FILE)
 +    else:
 +        os.rename(OLD_CONFIG_FILE, CONFIG_FILE)
 +OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
 +if os.path.exists(OLD_HISTORY):
 +    os.rename(OLD_HISTORY, HISTORY)
 +# END history/config definition
 +
 +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.protocol.ErrorMessage, cassandra.protocol.InternalError, cassandra.query.TraceUnavailable
 +)
 +
 +debug_completion = bool(os.environ.get('CQLSH_DEBUG_COMPLETION', '') == 'YES')
 +
 +# we want the cql parser to understand our cqlsh-specific commands too
 +my_commands_ending_with_newline = (
 +    'help',
 +    '?',
 +    'consistency',
 +    'serial',
 +    'describe',
 +    'desc',
 +    'show',
 +    'source',
 +    'capture',
 +    'login',
 +    'debug',
 +    'tracing',
 +    'expand',
 +    'paging',
 +    'exit',
 +    'quit',
 +    'clear',
 +    'cls'
 +)
 +
 +
 +cqlsh_syntax_completers = []
 +
 +
 +def cqlsh_syntax_completer(rulename, termname):
 +    def registrator(f):
 +        cqlsh_syntax_completers.append((rulename, termname, f))
 +        return f
 +    return registrator
 +
 +
 +cqlsh_extra_syntax_rules = r'''
 +<cqlshCommand> ::= <CQL_Statement>
 +                 | <specialCommand> ( ";" | "\n" )
 +                 ;
 +
 +<specialCommand> ::= <describeCommand>
 +                   | <consistencyCommand>
 +                   | <serialConsistencyCommand>
 +                   | <showCommand>
 +                   | <sourceCommand>
 +                   | <captureCommand>
 +                   | <copyCommand>
 +                   | <loginCommand>
 +                   | <debugCommand>
 +                   | <helpCommand>
 +                   | <tracingCommand>
 +                   | <expandCommand>
 +                   | <exitCommand>
 +                   | <pagingCommand>
 +                   | <clearCommand>
 +                   ;
 +
 +<describeCommand> ::= ( "DESCRIBE" | "DESC" )
 +                                  ( "FUNCTIONS"
 +                                  | "FUNCTION" udf=<anyFunctionName>
 +                                  | "AGGREGATES"
 +                                  | "AGGREGATE" uda=<userAggregateName>
 +                                  | "KEYSPACES"
 +                                  | "KEYSPACE" ksname=<keyspaceName>?
 +                                  | ( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
 +                                  | "INDEX" idx=<indexName>
 +                                  | ( "COLUMNFAMILIES" | "TABLES" )
 +                                  | "FULL"? "SCHEMA"
 +                                  | "CLUSTER"
 +                                  | "TYPES"
 +                                  | "TYPE" ut=<userTypeName>
 +                                  | (ksname=<keyspaceName> | cf=<columnFamilyName> | idx=<indexName>))
 +                    ;
 +
 +<consistencyCommand> ::= "CONSISTENCY" ( level=<consistencyLevel> )?
 +                       ;
 +
 +<consistencyLevel> ::= "ANY"
 +                     | "ONE"
 +                     | "TWO"
 +                     | "THREE"
 +                     | "QUORUM"
 +                     | "ALL"
 +                     | "LOCAL_QUORUM"
 +                     | "EACH_QUORUM"
 +                     | "SERIAL"
 +                     | "LOCAL_SERIAL"
 +                     | "LOCAL_ONE"
 +                     ;
 +
 +<serialConsistencyCommand> ::= "SERIAL" "CONSISTENCY" ( level=<serialConsistencyLevel> )?
 +                             ;
 +
 +<serialConsistencyLevel> ::= "SERIAL"
 +                           | "LOCAL_SERIAL"
 +                           ;
 +
 +<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid=<uuid> )
 +                ;
 +
 +<sourceCommand> ::= "SOURCE" fname=<stringLiteral>
 +                  ;
 +
 +<captureCommand> ::= "CAPTURE" ( fname=( <stringLiteral> | "OFF" ) )?
 +                   ;
 +
 +<copyCommand> ::= "COPY" cf=<columnFamilyName>
 +                         ( "(" [colnames]=<colname> ( "," [colnames]=<colname> )* ")" )?
 +                         ( dir="FROM" ( fname=<stringLiteral> | "STDIN" )
 +                         | dir="TO"   ( fname=<stringLiteral> | "STDOUT" ) )
 +                         ( "WITH" <copyOption> ( "AND" <copyOption> )* )?
 +                ;
 +
 +<copyOption> ::= [optnames]=(<identifier>|<reserved_identifier>) "=" [optvals]=<copyOptionVal>
 +               ;
 +
 +<copyOptionVal> ::= <identifier>
 +                  | <reserved_identifier>
 +                  | <term>
 +                  ;
 +
 +# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal
 +<debugCommand> ::= "DEBUG" "THINGS"?
 +                 ;
 +
 +<helpCommand> ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )*
 +                ;
 +
 +<tracingCommand> ::= "TRACING" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<expandCommand> ::= "EXPAND" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<pagingCommand> ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )?
 +                  ;
 +
 +<loginCommand> ::= "LOGIN" username=<username> (password=<stringLiteral>)?
 +                 ;
 +
 +<exitCommand> ::= "exit" | "quit"
 +                ;
 +
 +<clearCommand> ::= "CLEAR" | "CLS"
 +                 ;
 +
 +<qmark> ::= "?" ;
 +'''
 +
 +
 +@cqlsh_syntax_completer('helpCommand', 'topic')
 +def complete_help(ctxt, cqlsh):
 +    return sorted([t.upper() for t in cqldocs.get_help_topics() + cqlsh.get_help_topics()])
 +
 +
 +def complete_source_quoted_filename(ctxt, cqlsh):
 +    partial_path = ctxt.get_binding('partial', '')
 +    head, tail = os.path.split(partial_path)
 +    exhead = os.path.expanduser(head)
 +    try:
 +        contents = os.listdir(exhead or '.')
 +    except OSError:
 +        return ()
 +    matches = filter(lambda f: f.startswith(tail), contents)
 +    annotated = []
 +    for f in matches:
 +        match = os.path.join(head, f)
 +        if os.path.isdir(os.path.join(exhead, f)):
 +            match += '/'
 +        annotated.append(match)
 +    return annotated
 +
 +
 +cqlsh_syntax_completer('sourceCommand', 'fname')(complete_source_quoted_filename)
 +cqlsh_syntax_completer('captureCommand', 'fname')(complete_source_quoted_filename)
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'fname')
 +def copy_fname_completer(ctxt, cqlsh):
 +    lasttype = ctxt.get_binding('*LASTTYPE*')
 +    if lasttype == 'unclosedString':
 +        return complete_source_quoted_filename(ctxt, cqlsh)
 +    partial_path = ctxt.get_binding('partial')
 +    if partial_path == '':
 +        return ["'"]
 +    return ()
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'colnames')
 +def complete_copy_column_names(ctxt, cqlsh):
 +    existcols = map(cqlsh.cql_unprotect_name, ctxt.get_binding('colnames', ()))
 +    ks = cqlsh.cql_unprotect_name(ctxt.get_binding('ksname', None))
 +    cf = cqlsh.cql_unprotect_name(ctxt.get_binding('cfname'))
 +    colnames = cqlsh.get_column_names(ks, cf)
 +    if len(existcols) == 0:
 +        return [colnames[0]]
 +    return set(colnames[1:]) - set(existcols)
 +
 +
 +COPY_COMMON_OPTIONS = ['DELIMITER', 'QUOTE', 'ESCAPE', 'HEADER', 'NULL', 'DATETIMEFORMAT',
 +                       'MAXATTEMPTS', 'REPORTFREQUENCY', 'DECIMALSEP', 'THOUSANDSSEP', 'BOOLSTYLE',
 +                       'NUMPROCESSES', 'CONFIGFILE', 'RATEFILE']
 +COPY_FROM_OPTIONS = ['CHUNKSIZE', 'INGESTRATE', 'MAXBATCHSIZE', 'MINBATCHSIZE', 'MAXROWS',
 +                     'SKIPROWS', 'SKIPCOLS', 'MAXPARSEERRORS', 'MAXINSERTERRORS', 'ERRFILE', 'PREPAREDSTATEMENTS']
 +COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS']
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optnames')
 +def complete_copy_options(ctxt, cqlsh):
 +    optnames = map(str.upper, ctxt.get_binding('optnames', ()))
 +    direction = ctxt.get_binding('dir').upper()
 +    if direction == 'FROM':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_FROM_OPTIONS) - set(optnames)
 +    elif direction == 'TO':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_TO_OPTIONS) - set(optnames)
 +    return opts
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optvals')
 +def complete_copy_opt_values(ctxt, cqlsh):
 +    optnames = ctxt.get_binding('optnames', ())
 +    lastopt = optnames[-1].lower()
 +    if lastopt == 'header':
 +        return ['true', 'false']
 +    return [cqlhandling.Hint('<single_character_string>')]
 +
 +
 +class NoKeyspaceError(Exception):
 +    pass
 +
 +
 +class KeyspaceNotFound(Exception):
 +    pass
 +
 +
 +class ColumnFamilyNotFound(Exception):
 +    pass
 +
 +
 +class IndexNotFound(Exception):
 +    pass
 +
 +
 +class ObjectNotFound(Exception):
 +    pass
 +
 +
 +class VersionNotSupported(Exception):
 +    pass
 +
 +
 +class UserTypeNotFound(Exception):
 +    pass
 +
 +
 +class FunctionNotFound(Exception):
 +    pass
 +
 +
 +class AggregateNotFound(Exception):
 +    pass
 +
 +
 +class DecodeError(Exception):
 +    verb = 'decode'
 +
 +    def __init__(self, thebytes, err, colname=None):
 +        self.thebytes = thebytes
 +        self.err = err
 +        self.colname = colname
 +
 +    def __str__(self):
 +        return str(self.thebytes)
 +
 +    def message(self):
 +        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 : %s' \
 +               % (self.verb, what, self.err)
 +
 +    def __repr__(self):
 +        return '<%s %s>' % (self.__class__.__name__, self.message())
 +
 +
 +class FormatError(DecodeError):
 +    verb = 'format'
 +
 +
 +def full_cql_version(ver):
 +    while ver.count('.') < 2:
 +        ver += '.0'
 +    ver_parts = ver.split('-', 1) + ['']
 +    vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
 +    return ver, vertuple
 +
 +
 +def format_value(val, output_encoding, addcolor=False, date_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))
 +    return format_by_type(type(val), val, output_encoding, colormap=colormap,
 +                          addcolor=addcolor, nullval=nullval, date_time_format=date_time_format,
 +                          float_precision=float_precision)
 +
 +
 +def show_warning_without_quoting_line(message, category, filename, lineno, file=None, line=None):
 +    if file is None:
 +        file = sys.stderr
 +    try:
 +        file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
 +    except IOError:
 +        pass
++
++
 +warnings.showwarning = show_warning_without_quoting_line
 +warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 +
 +
 +def insert_driver_hooks():
 +    extend_cql_deserialization()
 +    auto_format_udts()
 +
 +
 +def extend_cql_deserialization():
 +    """
 +    The python driver returns BLOBs as string, but we expect them as bytearrays; therefore we change
 +    the implementation of cassandra.cqltypes.BytesType.deserialize.
 +
 +    The deserializers package exists only when the driver has been compiled with cython extensions and
 +    cassandra.deserializers.DesBytesType replaces cassandra.cqltypes.BytesType.deserialize.
 +
 +    DesBytesTypeByteArray is a fast deserializer that converts blobs into bytearrays but it was
 +    only introduced recently (3.1.0). If it is available we use it, otherwise we remove
 +    cassandra.deserializers.DesBytesType so that we fall back onto cassandra.cqltypes.BytesType.deserialize
 +    just like in the case where no cython extensions are present.
 +    """
 +    if hasattr(cassandra, 'deserializers'):
 +        if hasattr(cassandra.deserializers, 'DesBytesTypeByteArray'):
 +            cassandra.deserializers.DesBytesType = cassandra.deserializers.DesBytesTypeByteArray
 +        else:
 +            del cassandra.deserializers.DesBytesType
 +
 +    cassandra.cqltypes.BytesType.deserialize = staticmethod(lambda byts, protocol_version: bytearray(byts))
 +    cassandra.cqltypes.CassandraType.support_empty_values = True
 +
 +
 +def auto_format_udts():
 +    # when we see a new user defined type, set up the shell formatting for it
 +    udt_apply_params = cassandra.cqltypes.UserType.apply_parameters
 +
 +    def new_apply_params(cls, *args, **kwargs):
 +        udt_class = udt_apply_params(*args, **kwargs)
 +        formatter_for(udt_class.typename)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.udt_apply_parameters = classmethod(new_apply_params)
 +
 +    make_udt_class = cassandra.cqltypes.UserType.make_udt_class
 +
 +    def new_make_udt_class(cls, *args, **kwargs):
 +        udt_class = make_udt_class(*args, **kwargs)
 +        formatter_for(udt_class.tuple_type.__name__)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.make_udt_class = classmethod(new_make_udt_class)
 +
 +
 +class FrozenType(cassandra.cqltypes._ParameterizedType):
 +    """
 +    Needed until the bundled python driver adds FrozenType.
 +    """
 +    typename = "frozen"
 +    num_subtypes = 1
 +
 +    @classmethod
 +    def deserialize_safe(cls, byts, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.from_binary(byts)
 +
 +    @classmethod
 +    def serialize_safe(cls, val, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.to_binary(val, protocol_version)
 +
 +
 +class Shell(cmd.Cmd):
 +    custom_prompt = os.getenv('CQLSH_PROMPT', '')
 +    if custom_prompt is not '':
 +        custom_prompt += "\n"
 +    default_prompt = custom_prompt + "cqlsh> "
 +    continue_prompt = "   ... "
 +    keyspace_prompt = custom_prompt + "cqlsh:%s> "
 +    keyspace_continue_prompt = "%s    ... "
 +    show_line_nums = False
 +    debug = False
 +    stop = False
 +    last_hist = None
 +    shunted_query_out = None
 +    use_paging = True
 +
 +    default_page_size = 100
 +
 +    def __init__(self, hostname, port, color=False,
 +                 username=None, password=None, encoding=None, stdin=None, tty=True,
 +                 completekey=DEFAULT_COMPLETEKEY, browser=None, use_conn=None,
 +                 cqlver=DEFAULT_CQLVER, keyspace=None,
 +                 tracing_enabled=False, expand_enabled=False,
 +                 display_nanotime_format=DEFAULT_NANOTIME_FORMAT,
 +                 display_timestamp_format=DEFAULT_TIMESTAMP_FORMAT,
 +                 display_date_format=DEFAULT_DATE_FORMAT,
 +                 display_float_precision=DEFAULT_FLOAT_PRECISION,
 +                 display_timezone=None,
 +                 max_trace_wait=DEFAULT_MAX_TRACE_WAIT,
 +                 ssl=False,
 +                 single_statement=None,
 +                 request_timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS,
 +                 protocol_version=DEFAULT_PROTOCOL_VERSION,
 +                 connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS):
 +        cmd.Cmd.__init__(self, completekey=completekey)
 +        self.hostname = hostname
 +        self.port = port
 +        self.auth_provider = None
 +        if username:
 +            if not password:
 +                password = getpass.getpass()
 +            self.auth_provider = PlainTextAuthProvider(username=username, password=password)
 +        self.username = username
 +        self.keyspace = keyspace
 +        self.ssl = ssl
 +        self.tracing_enabled = tracing_enabled
 +        self.page_size = self.default_page_size
 +        self.expand_enabled = expand_enabled
 +        if use_conn:
 +            self.conn = use_conn
 +        else:
 +            self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
 +                                protocol_version=protocol_version,
 +                                auth_provider=self.auth_provider,
 +                                ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,
 +                                load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                                control_connection_timeout=connect_timeout,
 +                                connect_timeout=connect_timeout)
 +        self.owns_connection = not use_conn
 +        self.set_expanded_cql_version(cqlver)
 +
 +        if keyspace:
 +            self.session = self.conn.connect(keyspace)
 +        else:
 +            self.session = self.conn.connect()
 +
 +        if browser == "":
 +            browser = None
 +        self.browser = browser
 +        self.color = color
 +
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_date_format = display_date_format
 +
 +        self.display_float_precision = display_float_precision
 +
 +        self.display_timezone = display_timezone
 +
 +        self.session.default_timeout = request_timeout
 +        self.session.row_factory = ordered_dict_factory
 +        self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.get_connection_versions()
 +
 +        self.current_keyspace = keyspace
 +
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_date_format = display_date_format
 +
 +        self.max_trace_wait = max_trace_wait
 +        self.session.max_trace_wait = max_trace_wait
 +
 +        self.tty = tty
 +        self.encoding = encoding
 +        self.check_windows_encoding()
 +
 +        self.output_codec = codecs.lookup(encoding)
 +
 +        self.statement = StringIO()
 +        self.lineno = 1
 +        self.in_comment = False
 +
 +        self.prompt = ''
 +        if stdin is None:
 +            stdin = sys.stdin
 +
 +        if tty:
 +            self.reset_prompt()
 +            self.report_connection()
 +            print 'Use HELP for help.'
 +        else:
 +            self.show_line_nums = True
 +        self.stdin = stdin
 +        self.query_out = sys.stdout
 +        self.consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.SERIAL
 +
 +        self.empty_lines = 0
 +        self.statement_error = False
 +        self.single_statement = single_statement
 +
 +    @property
 +    def is_using_utf8(self):
 +        # utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html
 +        return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8', CP65001]
 +
 +    def check_windows_encoding(self):
 +        if is_win and os.name == 'nt' and self.tty and \
 +           self.is_using_utf8 and sys.stdout.encoding != CP65001:
 +            self.printerr("\nWARNING: console codepage must be set to cp65001 "
 +                          "to support {} encoding on Windows platforms.\n"
 +                          "If you experience encoding problems, change your console"
 +                          " codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding))
 +
 +    def set_expanded_cql_version(self, ver):
 +        ver, vertuple = full_cql_version(ver)
 +        self.cql_version = ver
 +        self.cql_ver_tuple = vertuple
 +
 +    def cqlver_atleast(self, major, minor=0, patch=0):
 +        return self.cql_ver_tuple[:3] >= (major, minor, patch)
 +
 +    def myformat_value(self, val, **kwargs):
 +        if isinstance(val, DecodeError):
 +            self.decoding_errors.append(val)
 +        try:
 +            dtformats = DateTimeFormat(timestamp_format=self.display_timestamp_format,
 +                                       date_format=self.display_date_format, nanotime_format=self.display_nanotime_format,
 +                                       timezone=self.display_timezone)
 +            return format_value(val, self.output_codec.name,
 +                                addcolor=self.color, date_time_format=dtformats,
 +                                float_precision=self.display_float_precision, **kwargs)
 +        except Exception, e:
 +            err = FormatError(val, e)
 +            self.decoding_errors.append(err)
 +            return format_value(err, self.output_codec.name, addcolor=self.color)
 +
 +    def myformat_colname(self, name, table_meta=None):
 +        column_colors = COLUMN_NAME_COLORS.copy()
 +        # check column role and color appropriately
 +        if table_meta:
 +            if name in [col.name for col in table_meta.partition_key]:
 +                column_colors.default_factory = lambda: RED
 +            elif name in [col.name for col in table_meta.clustering_key]:
 +                column_colors.default_factory = lambda: CYAN
 +        return self.myformat_value(name, colormap=column_colors)
 +
 +    def report_connection(self):
 +        self.show_host()
 +        self.show_version()
 +
 +    def show_host(self):
 +        print "Connected to %s at %s:%d." % \
 +            (self.applycolor(self.get_cluster_name(), BLUE),
 +              self.hostname,
 +              self.port)
 +
 +    def show_version(self):
 +        vers = self.connection_versions.copy()
 +        vers['shver'] = version
 +        # 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 | Native protocol v%(protocol)s]" % vers
 +
 +    def show_session(self, sessionid, partial_session=False):
 +        print_trace_session(self, self.session, sessionid, partial_session)
 +
 +    def get_connection_versions(self):
 +        result, = self.session.execute("select * from system.local where key = 'local'")
 +        vers = {
 +            'build': result['release_version'],
 +            'protocol': result['native_protocol_version'],
 +            'cql': result['cql_version'],
 +        }
 +        self.connection_versions = vers
 +
 +    def get_keyspace_names(self):
 +        return map(str, self.conn.metadata.keyspaces.keys())
 +
 +    def get_columnfamily_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).tables.keys())
 +
 +    def get_index_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).indexes.keys())
 +
 +    def get_column_names(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        layout = self.get_table_meta(ksname, cfname)
 +        return [unicode(col) for col in layout.columns]
 +
 +    def get_usertype_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return self.get_keyspace_meta(ksname).user_types.keys()
 +
 +    def get_usertype_layout(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        ks_meta = self.get_keyspace_meta(ksname)
 +
 +        try:
 +            user_type = ks_meta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +
 +        return [(field_name, field_type.cql_parameterized_type())
 +                for field_name, field_type in zip(user_type.field_names, user_type.field_types)]
 +
 +    def get_userfunction_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).functions.values())
 +
 +    def get_useraggregate_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).aggregates.values())
 +
 +    def get_cluster_name(self):
 +        return self.conn.metadata.cluster_name
 +
 +    def get_partitioner(self):
 +        return self.conn.metadata.partitioner
 +
 +    def get_keyspace_meta(self, ksname):
 +        if ksname not in self.conn.metadata.keyspaces:
 +            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
 +        return self.conn.metadata.keyspaces[ksname]
 +
 +    def get_keyspaces(self):
 +        return self.conn.metadata.keyspaces.values()
 +
 +    def get_ring(self, ks):
 +        self.conn.metadata.token_map.rebuild_keyspace(ks, build_if_absent=True)
 +        return self.conn.metadata.token_map.tokens_to_hosts_by_ks[ks]
 +
 +    def get_table_meta(self, ksname, tablename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if tablename not in ksmeta.tables:
 +            if ksname == 'system_auth' and tablename in ['roles', 'role_permissions']:
 +                self.get_fake_auth_table_meta(ksname, tablename)
 +            else:
 +                raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +        else:
 +            return ksmeta.tables[tablename]
 +
 +    def get_fake_auth_table_meta(self, ksname, tablename):
 +        # may be using external auth implementation so internal tables
 +        # aren't actually defined in schema. In this case, we'll fake
 +        # them up
 +        if tablename == 'roles':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'roles')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['is_superuser'] = ColumnMetadata(table_meta, 'is_superuser', cassandra.cqltypes.BooleanType)
 +            table_meta.columns['can_login'] = ColumnMetadata(table_meta, 'can_login', cassandra.cqltypes.BooleanType)
 +        elif tablename == 'role_permissions':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'role_permissions')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['resource'] = ColumnMetadata(table_meta, 'resource', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['permission'] = ColumnMetadata(table_meta, 'permission', cassandra.cqltypes.UTF8Type)
 +        else:
 +            raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +
 +    def get_index_meta(self, ksname, idxname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if idxname not in ksmeta.indexes:
 +            raise IndexNotFound("Index %r not found" % idxname)
 +
 +        return ksmeta.indexes[idxname]
 +
 +    def get_object_meta(self, ks, name):
 +        if name is None:
 +            if ks and ks in self.conn.metadata.keyspaces:
 +                return self.conn.metadata.keyspaces[ks]
 +            elif self.current_keyspace is None:
 +                raise ObjectNotFound("%r not found in keyspaces" % (ks))
 +            else:
 +                name = ks
 +                ks = self.current_keyspace
 +
 +        if ks is None:
 +            ks = self.current_keyspace
 +
 +        ksmeta = self.get_keyspace_meta(ks)
 +
 +        if name in ksmeta.tables:
 +            return ksmeta.tables[name]
 +        elif name in ksmeta.indexes:
 +            return ksmeta.indexes[name]
 +
 +        raise ObjectNotFound("%r not found in keyspace %r" % (name, ks))
 +
 +    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)
 +
 +    def get_trigger_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return [trigger.name
 +                for table in self.get_keyspace_meta(ksname).tables.values()
 +                for trigger in table.triggers.values()]
 +
 +    def reset_statement(self):
 +        self.reset_prompt()
 +        self.statement.truncate(0)
 +        self.empty_lines = 0
 +
 +    def reset_prompt(self):
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.default_prompt, True)
 +        else:
 +            self.set_prompt(self.keyspace_prompt % self.current_keyspace, True)
 +
 +    def set_continue_prompt(self):
 +        if self.empty_lines >= 3:
 +            self.set_prompt("Statements are terminated with a ';'.  You can press CTRL-C to cancel an incomplete statement.")
 +            self.empty_lines = 0
 +            return
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.continue_prompt)
 +        else:
 +            spaces = ' ' * len(str(self.current_keyspace))
 +            self.set_prompt(self.keyspace_continue_prompt % spaces)
 +        self.empty_lines = self.empty_lines + 1 if not self.lastcmd else 0
 +
 +    @contextmanager
 +    def prepare_loop(self):
 +        readline = None
 +        if self.tty and self.completekey:
 +            try:
 +                import readline
 +            except ImportError:
 +                if is_win:
 +                    print "WARNING: pyreadline dependency missing.  Install to enable tab completion."
 +                pass
 +            else:
 +                old_completer = readline.get_completer()
 +                readline.set_completer(self.complete)
 +                if readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +                    readline.parse_and_bind("bind -e")
 +                    readline.parse_and_bind("bind '" + self.completekey + "' rl_complete")
 +                    readline.parse_and_bind("bind ^R em-inc-search-prev")
 +                else:
 +                    readline.parse_and_bind(self.completekey + ": complete")
 +        try:
 +            yield
 +        finally:
 +            if readline is not None:
 +                readline.set_completer(old_completer)
 +
 +    def get_input_line(self, prompt=''):
 +        if self.tty:
 +            try:
 +                self.lastcmd = raw_input(prompt).decode(self.encoding)
 +            except UnicodeDecodeError:
 +                self.lastcmd = ''
 +                traceback.print_exc()
 +                self.check_windows_encoding()
 +            line = self.lastcmd + '\n'
 +        else:
 +            self.lastcmd = self.stdin.readline()
 +            line = self.lastcmd
 +            if not len(line):
 +                raise EOFError
 +        self.lineno += 1
 +        return line
 +
 +    def use_stdin_reader(self, until='', prompt=''):
 +        until += '\n'
 +        while True:
 +            try:
 +                newline = self.get_input_line(prompt=prompt)
 +            except EOFError:
 +                return
 +            if newline == until:
 +                return
 +            yield newline
 +
 +    def cmdloop(self):
 +        """
 +        Adapted from cmd.Cmd's version, because there is literally no way with
 +        cmd.Cmd.cmdloop() to tell the difference between "EOF" showing up in
 +        input and an actual EOF.
 +        """
 +        with self.prepare_loop():
 +            while not self.stop:
 +                try:
 +                    if self.single_statement:
 +                        line = self.single_statement
 +                        self.stop = True
 +                    else:
 +                        line = self.get_input_line(self.prompt)
 +                    self.statement.write(line)
 +                    if self.onecmd(self.statement.getvalue()):
 +                        self.reset_statement()
 +                except EOFError:
 +                    self.handle_eof()
 +                except CQL_ERRORS, cqlerr:
 +                    self.printerr(cqlerr.message.decode(encoding='utf-8'))
 +                except KeyboardInterrupt:
 +                    self.reset_statement()
 +                    print
 +
 +    def onecmd(self, statementtext):
 +        """
 +        Returns true if the statement is complete and was handled (meaning it
 +        can be reset).
 +        """
 +
 +        try:
 +            statements, endtoken_escaped = cqlruleset.cql_split_statements(statementtext)
 +        except pylexotron.LexingError, e:
 +            if self.show_line_nums:
 +                self.printerr('Invalid syntax at char %d' % (e.charnum,))
 +            else:
 +                self.printerr('Invalid syntax at line %d, char %d'
 +                              % (e.linenum, e.charnum))
 +            statementline = statementtext.split('\n')[e.linenum - 1]
 +            self.printerr('  %s' % statementline)
 +            self.printerr(' %s^' % (' ' * e.charnum))
 +            return True
 +
 +        while statements and not statements[-1]:
 +            statements = statements[:-1]
 +        if not statements:
 +            return True
 +        if endtoken_escaped or statements[-1][-1][0] != 'endtoken':
 +            self.set_continue_prompt()
 +            return
 +        for st in statements:
 +            try:
 +                self.handle_statement(st, statementtext)
 +            except Exception, e:
 +                if self.debug:
 +                    traceback.print_exc()
 +                else:
 +                    self.printerr(e)
 +        return True
 +
 +    def handle_eof(self):
 +        if self.tty:
 +            print
 +        statement = self.statement.getvalue()
 +        if statement.strip():
 +            if not self.onecmd(statement):
 +                self.printerr('Incomplete statement at end of file')
 +        self.do_exit()
 +
 +    def handle_statement(self, tokens, srcstr):
 +        # Concat multi-line statements and insert into history
 +        if readline is not None:
 +            nl_count = srcstr.count("\n")
 +
 +            new_hist = srcstr.replace("\n", " ").rstrip()
 +
 +            if nl_count > 1 and self.last_hist != new_hist:
 +                readline.add_history(new_hist.encode(self.encoding))
 +
 +            self.last_hist = new_hist
 +        cmdword = tokens[0][1]
 +        if cmdword == '?':
 +            cmdword = 'help'
 +        custom_handler = getattr(self, 'do_' + cmdword.lower(), None)
 +        if custom_handler:
 +            parsed = cqlruleset.cql_whole_parse_tokens(tokens, srcstr=srcstr,
 +                                                       startsymbol='cqlshCommand')
 +            if parsed and not parsed.remainder:
 +                # successful complete parse
 +                return custom_handler(parsed)
 +            else:
 +                return self.handle_parse_error(cmdword, tokens, parsed, srcstr)
 +        return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +
 +    def handle_parse_error(self, cmdword, tokens, parsed, srcstr):
 +        if cmdword.lower() in ('select', 'insert', 'update', 'delete', 'truncate',
 +                               'create', 'drop', 'alter', 'grant', 'revoke',
 +                               'batch', 'list'):
 +            # hey, maybe they know about some new syntax we don't. type
 +            # assumptions won't work, but maybe the query will.
 +            return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +        if parsed:
 +            self.printerr('Improper %s command (problem at %r).' % (cmdword, parsed.remainder[0]))
 +        else:
 +            self.printerr('Improper %s command.' % cmdword)
 +
 +    def do_use(self, parsed):
 +        ksname = parsed.get_binding('ksname')
 +        success, _ = self.perform_simple_statement(SimpleStatement(parsed.extract_orig()))
 +        if success:
 +            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):
 +        tracing_was_enabled = self.tracing_enabled
 +        ksname = parsed.get_binding('ksname')
 +        stop_tracing = ksname == 'system_traces' or (ksname is None and self.current_keyspace == 'system_traces')
 +        self.tracing_enabled = self.tracing_enabled and not stop_tracing
 +        statement = parsed.extract_orig()
 +        self.perform_statement(statement)
 +        self.tracing_enabled = tracing_was_enabled
 +
 +    def perform_statement(self, statement):
 +        stmt = SimpleStatement(statement, consistency_level=self.consistency_level, serial_consistency_level=self.serial_consistency_level, fetch_size=self.page_size if self.use_paging else None)
 +        success, future = self.perform_simple_statement(stmt)
 +
 +        if future:
 +            if future.warnings:
 +                self.print_warnings(future.warnings)
 +
 +            if self.tracing_enabled:
 +                try:
 +                    for trace in future.get_all_query_traces(max_wait_per=self.max_trace_wait, query_cl=self.consistency_level):
 +                        print_trace(self, trace)
 +                except TraceUnavailable:
 +                    msg = "Statement trace did not complete within %d seconds; trace data may be incomplete." % (self.session.max_trace_wait,)
 +                    self.writeresult(msg, color=RED)
 +                    for trace_id in future.get_query_trace_ids():
 +                        self.show_session(trace_id, partial_session=True)
 +                except Exception, err:
 +                    self.printerr("Unable to fetch query trace: %s" % (str(err),))
 +
 +        return success
 +
 +    def parse_for_table_meta(self, query_string):
 +        try:
 +            parsed = cqlruleset.cql_parse(query_string)[1]
 +        except IndexError:
 +            return None
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        return self.get_table_meta(ks, cf)
 +
 +    def perform_simple_statement(self, statement):
 +        if not statement:
 +            return False, None
 +
 +        future = self.session.execute_async(statement, trace=self.tracing_enabled)
 +        result = None
 +        try:
 +            result = future.result()
 +        except CQL_ERRORS, err:
 +            self.printerr(unicode(err.__class__.__name__) + u": " + err.message.decode(encoding='utf-8'))
 +        except Exception:
 +            import traceback
 +            self.printerr(traceback.format_exc())
 +
 +        # Even if statement failed we try to refresh schema if not agreed (see CASSANDRA-9689)
 +        if not future.is_schema_agreed:
 +            try:
 +                self.conn.refresh_schema_metadata(5)  # will throw exception if there is a schema mismatch
 +            except Exception:
 +                self.printerr("Warning: schema version mismatch detected; check the schema versions of your "
 +                              "nodes in system.local and system.peers.")
 +                self.conn.refresh_schema_metadata(-1)
 +
 +        if result is None:
 +            return False, None
 +
 +        if statement.query_string[:6].lower() == 'select':
 +            self.print_result(result, self.parse_for_table_meta(statement.query_string))
 +        elif statement.query_string.lower().startswith("list users") or statement.query_string.lower().startswith("list roles"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'roles'))
 +        elif statement.query_string.lower().startswith("list"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'role_permissions'))
 +        elif result:
 +            # CAS INSERT/UPDATE
 +            self.writeresult("")
 +            self.print_static_result(result.column_names, list(result), self.parse_for_table_meta(statement.query_string))
 +        self.flush_output()
 +        return True, future
 +
 +    def print_result(self, result, table_meta):
 +        self.decoding_errors = []
 +
 +        self.writeresult("")
 +        if result.has_more_pages and self.tty:
 +            num_rows = 0
 +            while True:
 +                page = result.current_rows
 +                if page:
 +                    num_rows += len(page)
 +                    self.print_static_result(result.column_names, page, table_meta)
 +                if result.has_more_pages:
 +                    raw_input("---MORE---")
 +                    result.fetch_next_page()
 +                else:
 +                    break
 +        else:
 +            rows = list(result)
 +            num_rows = len(rows)
 +            self.print_static_result(result.column_names, rows, table_meta)
 +        self.writeresult("(%d rows)" % num_rows)
 +
 +        if self.decoding_errors:
 +            for err in self.decoding_errors[:2]:
 +                self.writeresult(err.message(), color=RED)
 +            if len(self.decoding_errors) > 2:
 +                self.writeresult('%d more decoding errors suppressed.'
 +                                 % (len(self.decoding_errors) - 2), color=RED)
 +
 +    def print_static_result(self, column_names, rows, table_meta):
 +        if not column_names and not table_meta:
 +            return
 +
 +        column_names = column_names or table_meta.columns.keys()
 +        formatted_names = [self.myformat_colname(name, table_meta) for name in column_names]
 +        if not rows:
 +            # print header only
 +            self.print_formatted_result(formatted_names, None)
 +            return
 +        formatted_values = [map(self.myformat_value, row.values()) for row in rows]
 +
 +        if self.expand_enabled:
 +            self.print_formatted_result_vertically(formatted_names, formatted_values)
 +        else:
 +            self.print_formatted_result(formatted_names, formatted_values)
 +
 +    def print_formatted_result(self, formatted_names, formatted_values):
 +        # determine column widths
 +        widths = [n.displaywidth for n in formatted_names]
 +        if formatted_values is not None:
 +            for fmtrow in formatted_values:
 +                for num, col in enumerate(fmtrow):
 +                    widths[num] = max(widths[num], col.displaywidth)
 +
 +        # print header
 +        header = ' | '.join(hdr.ljust(w, color=self.color) for (hdr, w) in zip(formatted_names, widths))
 +        self.writeresult(' ' + header.rstrip())
 +        self.writeresult('-%s-' % '-+-'.join('-' * w for w in widths))
 +
 +        # stop if there are no rows
 +        if formatted_values is None:
 +            self.writeresult("")
 +            return
 +
 +        # print row data
 +        for row in formatted_values:
 +            line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
 +            self.writeresult(' ' + line)
 +
 +        self.writeresult("")
 +
 +    def print_formatted_result_vertically(self, formatted_names, formatted_values):
 +        max_col_width = max([n.displaywidth for n in formatted_names])
 +        max_val_width = max([n.displaywidth for row in formatted_values for n in row])
 +
 +        # for each row returned, list all the column-value pairs
 +        for row_id, row in enumerate(formatted_values):
 +            self.writeresult("@ Row %d" % (row_id + 1))
 +            self.writeresult('-%s-' % '-+-'.join(['-' * max_col_width, '-' * max_val_width]))
 +            for field_id, field in enumerate(row):
 +                column = formatted_names[field_id].ljust(max_col_width, color=self.color)
 +                value = field.ljust(field.displaywidth, color=self.color)
 +                self.writeresult(' ' + " | ".join([column, value]))
 +            self.writeresult('')
 +
 +    def print_warnings(self, warnings):
 +        if warnings is None or len(warnings) == 0:
 +            return
 +
 +        self.writeresult('')
 +        self.writeresult('Warnings :')
 +        for warning in warnings:
 +            self.writeresult(warning)
 +            self.writeresult('')
 +
 +    def emptyline(self):
 +        pass
 +
 +    def parseline(self, line):
 +        # this shouldn't be needed
 +        raise NotImplementedError
 +
 +    def complete(self, text, state):
 +        if readline is None:
 +            return
 +        if state == 0:
 +            try:
 +                self.completion_matches = self.find_completions(text)
 +            except Exception:
 +                if debug_completion:
 +                    import traceback
 +                    traceback.print_exc()
 +                else:
 +                    raise
 +        try:
 +            return self.completion_matches[state]
 +        except IndexError:
 +            return None
 +
 +    def find_completions(self, text):
 +        curline = readline.get_line_buffer()
 +        prevlines = self.statement.getvalue()
 +        wholestmt = prevlines + curline
 +        begidx = readline.get_begidx() + len(prevlines)
 +        stuff_to_complete = wholestmt[:begidx]
 +        return cqlruleset.cql_complete(stuff_to_complete, text, cassandra_conn=self,
 +                                       debug=debug_completion, startsymbol='cqlshCommand')
 +
 +    def set_prompt(self, prompt, prepend_user=False):
 +        if prepend_user and self.username:
 +            self.prompt = "%s@%s" % (self.username, prompt)
 +            return
 +        self.prompt = prompt
 +
 +    def cql_unprotect_name(self, namestr):
 +        if namestr is None:
 +            return
 +        return cqlruleset.dequote_name(namestr)
 +
 +    def cql_unprotect_value(self, valstr):
 +        if valstr is not None:
 +            return cqlruleset.dequote_value(valstr)
 +
 +    def print_recreate_keyspace(self, ksdef, out):
 +        out.write(ksdef.export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_columnfamily(self, ksname, cfname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given table.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_table_meta(ksname, cfname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_index(self, ksname, idxname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given index.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_index_meta(ksname, idxname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_object(self, ks, name, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given object (ks, table or index).
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_object_meta(ks, name).export_as_string())
 +        out.write("\n")
 +
 +    def describe_keyspaces(self):
 +        print
 +        cmd.Cmd.columnize(self, protect_names(self.get_keyspace_names()))
 +        print
 +
 +    def describe_keyspace(self, ksname):
 +        print
 +        self.print_recreate_keyspace(self.get_keyspace_meta(ksname), sys.stdout)
 +        print
 +
 +    def describe_columnfamily(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        self.print_recreate_columnfamily(ksname, cfname, sys.stdout)
 +        print
 +
 +    def describe_index(self, ksname, idxname):
 +        print
 +        self.print_recreate_index(ksname, idxname, sys.stdout)
 +        print
 +
 +    def describe_object(self, ks, name):
 +        print
 +        self.print_recreate_object(ks, name, sys.stdout)
 +        print
 +
 +    def describe_columnfamilies(self, ksname):
 +        print
 +        if ksname is None:
 +            for k in self.get_keyspaces():
 +                name = protect_name(k.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(k.name)))
 +                print
 +        else:
 +            cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(ksname)))
 +            print
 +
 +    def describe_functions(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.functions.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.functions.keys())
 +
 +    def describe_function(self, ksname, functionname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        functions = filter(lambda f: f.name == functionname, ksmeta.functions.values())
 +        if len(functions) == 0:
 +            raise FunctionNotFound("User defined function %r not found" % functionname)
 +        print "\n\n".join(func.as_cql_query(formatted=True) for func in functions)
 +        print
 +
 +    def describe_aggregates(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.aggregates.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.aggregates.keys())
 +
 +    def describe_aggregate(self, ksname, aggregatename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        aggregates = filter(lambda f: f.name == aggregatename, ksmeta.aggregates.values())
 +        if len(aggregates) == 0:
 +            raise FunctionNotFound("User defined aggregate %r not found" % aggregatename)
 +        print "\n\n".join(aggr.as_cql_query(formatted=True) for aggr in aggregates)
 +        print
 +
 +    def describe_usertypes(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +
 +    def describe_usertype(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        try:
 +            usertype = ksmeta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +        print usertype.as_cql_query(formatted=True)
 +        print
 +
 +    def _columnize_unicode(self, name_list, quote=False):
 +        """
 +        Used when columnizing identifiers that may contain unicode
 +        """
 +        names = [n.encode('utf-8') for n in name_list]
 +        if quote:
 +            names = protect_names(names)
 +        cmd.Cmd.columnize(self, names)
 +        print
 +
 +    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\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(self.current_keyspace)
 +            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):
 +        print
 +        for k in self.get_keyspaces():
 +            if include_system or k.name not in cql3handling.SYSTEM_KEYSPACES:
 +                self.print_recreate_keyspace(k, sys.stdout)
 +                print
 +
 +    def do_describe(self, parsed):
 +        """
 +        DESCRIBE [cqlsh only]
 +
 +        (DESC may be used as a shorthand.)
 +
 +          Outputs information about the connected Cassandra cluster, or about
 +          the data objects stored in the cluster. Use in one of the following ways:
 +
 +        DESCRIBE KEYSPACES
 +
 +          Output the names of all keyspaces.
 +
 +        DESCRIBE KEYSPACE [<keyspacename>]
 +
 +          Output CQL commands that could be used to recreate the given keyspace,
 +          and the objects in it (such as tables, types, functions, etc.).
 +          In some cases, as the CQL interface matures, there will be some metadata
 +          about a keyspace that is not representable with CQL. That metadata will not be shown.
 +
 +          The '<keyspacename>' argument may be omitted, in which case the current
 +          keyspace will be described.
 +
 +        DESCRIBE TABLES
 +
 +          Output the names of all tables in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TABLE [<keyspace>.]<tablename>
 +
 +          Output CQL commands that could be used to recreate the given table.
 +          In some cases, as above, there may be table metadata which is not
 +          representable and which will not be shown.
 +
 +        DESCRIBE INDEX <indexname>
 +
 +          Output the CQL command that could be used to recreate the given index.
 +          In some cases, there may be index metadata which is not representable
 +          and which will not be shown.
 +
 +        DESCRIBE CLUSTER
 +
 +          Output information about the connected Cassandra cluster, such as the
 +          cluster name, and the partitioner and snitch in use. When you are
 +          connected to a non-system keyspace, also shows endpoint-range
 +          ownership information for the Cassandra ring.
 +
 +        DESCRIBE [FULL] SCHEMA
 +
 +          Output CQL commands that could be used to recreate the entire (non-system) schema.
 +          Works as though "DESCRIBE KEYSPACE k" was invoked for each non-system keyspace
 +          k. Use DESCRIBE FULL SCHEMA to include the system keyspaces.
 +
 +        DESCRIBE TYPES
 +
 +          Output the names of all user-defined-types in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TYPE [<keyspace>.]<type>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-type.
 +
 +        DESCRIBE FUNCTIONS
 +
 +          Output the names of all user-defined-functions in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE FUNCTION [<keyspace>.]<function>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-function.
 +
 +        DESCRIBE AGGREGATES
 +
 +          Output the names of all user-defined-aggregates in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE AGGREGATE [<keyspace>.]<aggregate>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-aggregate.
 +
 +        DESCRIBE <objname>
 +
 +          Output CQL commands that could be used to recreate the entire object schema,
 +          where object can be either a keyspace or a table or an index (in this order).
 +  """
 +        what = parsed.matched[1][1].lower()
 +        if what == 'functions':
 +            self.describe_functions(self.current_keyspace)
 +        elif what == 'function':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            functionname = self.cql_unprotect_name(parsed.get_binding('udfname'))
 +            self.describe_function(ksname, functionname)
 +        elif what == 'aggregates':
 +            self.describe_aggregates(self.current_keyspace)
 +        elif what == 'aggregate':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            aggregatename = self.cql_unprotect_name(parsed.get_binding('udaname'))
 +            self.describe_aggregate(ksname, aggregatename)
 +        elif what == 'keyspaces':
 +            self.describe_keyspaces()
 +        elif what == 'keyspace':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', ''))
 +            if not ksname:
 +                ksname = self.current_keyspace
 +                if ksname is None:
 +                    self.printerr('Not in any keyspace.')
 +                    return
 +            self.describe_keyspace(ksname)
 +        elif what in ('columnfamily', 'table'):
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            self.describe_columnfamily(ks, cf)
 +        elif what == 'index':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            idx = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_index(ks, idx)
 +        elif what in ('columnfamilies', 'tables'):
 +            self.describe_columnfamilies(self.current_keyspace)
 +        elif what == 'types':
 +            self.describe_usertypes(self.current_keyspace)
 +        elif what == 'type':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            ut = self.cql_unprotect_name(parsed.get_binding('utname'))
 +            self.describe_usertype(ks, ut)
 +        elif what == 'cluster':
 +            self.describe_cluster()
 +        elif what == 'schema':
 +            self.describe_schema(False)
 +        elif what == 'full' and parsed.matched[2][1].lower() == 'schema':
 +            self.describe_schema(True)
 +        elif what:
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            name = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            if not name:
 +                name = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_object(ks, name)
 +    do_desc = do_describe
 +
 +    def do_copy(self, parsed):
 +        r"""
 +        COPY [cqlsh only]
 +
 +          COPY x FROM: Imports CSV data into a Cassandra table
 +          COPY x TO: Exports data from a Cassandra table in CSV format.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             FROM ( '<file_pattern_1, file_pattern_2, ... file_pattern_n>' | STDIN )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        File patterns are either file names or valid python glob expressions, e.g. *.csv or folder/*.csv.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             TO ( '<filename>' | STDOUT )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        Available common COPY options and defaults:
 +
 +          DELIMITER=','           - character that appears between records
 +          QUOTE='"'               - quoting character to be used to quote fields
 +          ESCAPE='\'              - character to appear before the QUOTE char when quoted
 +          HEADER=false            - whether to ignore the first line
 +          NULL=''                 - string that represents a null value
 +          DATETIMEFORMAT=         - timestamp strftime format
 +            '%Y-%m-%d %H:%M:%S%z'   defaults to time_format value in cqlshrc
 +          MAXATTEMPTS=5           - the maximum number of attempts per batch or range
 +          REPORTFREQUENCY=0.25    - the frequency with which we display status updates in seconds
 +          DECIMALSEP='.'          - the separator for decimal values
 +          THOUSANDSSEP=''         - the separator for thousands digit groups
 +          BOOLSTYLE='True,False'  - the representation for booleans, case insensitive, specify true followed by false,
 +                                    for example yes,no or 1,0
 +          NUMPROCESSES=n          - the number of worker processes, by default the number of cores minus one
 +                                    capped at 16
 +          CONFIGFILE=''           - a configuration file with the same format as .cqlshrc (see the Python ConfigParser
 +                                    documentation) where you can specify WITH options under the following optional
 +                                    sections: [copy], [copy-to], [copy-from], [copy:ks.table], [copy-to:ks.table],
 +                                    [copy-from:ks.table], where <ks> is your keyspace name and <table> is your table
 +                                    name. Options are read from these sections, in the order specified
 +                                    above, and command line options always override options in configuration files.
 +                                    Depending on the COPY direction, only the relevant copy-from or copy-to sections
 +                                    are used. If no configfile is specified then .cqlshrc is searched instead.
 +          RATEFILE=''             - an optional file where to print the output statistics
 +
 +        Available COPY FROM options and defaults:
 +
 +          CHUNKSIZE=5000          - the size of chunks passed to worker processes
 +          INGESTRATE=100000       - an approximate ingest rate in rows per second
 +          MINBATCHSIZE=10         - the minimum size of an import batch
 +          MAXBATCHSIZE=20         - the maximum size of an import batch
 +          MAXROWS=-1              - the maximum number of rows, -1 means no maximum
 +          SKIPROWS=0              - the number of rows to skip
 +          SKIPCOLS=''             - a comma separated list of column names to skip
 +          MAXPARSEERRORS=-1       - the maximum global number of parsing errors, -1 means no maximum
 +          MAXINSERTERRORS=-1      - the maximum global number of insert errors, -1 means no maximum
 +          ERRFILE=''              - a file where to store all rows that could not be imported, by default this is
 +                                    import_ks_table.err where <ks> is your keyspace and <table> is your table name.
 +          PREPAREDSTATEMENTS=True - whether to use prepared statements when importing, by default True. Set this to
 +                                    False if you don't mind shifting data parsing to the cluster. The cluster will also
 +                                    have to compile every batch statement. For large and oversized clusters
 +                                    this will result in a faster import but for smaller clusters it may generate
 +                                    timeouts.
 +
 +        Available COPY TO options and defaults:
 +
 +          ENCODING='utf8'          - encoding for CSV output
 +          PAGESIZE='1000'          - the page size for fetching results
 +          PAGETIMEOUT=10           - the page timeout in seconds for fetching results
 +          BEGINTOKEN=''            - the minimum token string to consider when exporting data
 +          ENDTOKEN=''              - the maximum token string to consider when exporting data
 +          MAXREQUESTS=6            - the maximum number of requests each worker process can work on in parallel
 +          MAXOUTPUTSIZE='-1'       - the maximum size of the output file measured in number of lines,
 +                                     beyond this maximum the output file will be split into segments,
 +                                     -1 means unlimited.
 +
 +        When entering CSV data on STDIN, you can use the sequence "\."
 +        on a line by itself to end the data input.
 +        """
 +
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        if ks is None:
 +            ks = self.current_keyspace
 +            if ks is None:
 +                raise NoKeyspaceError("Not in any keyspace.")
 +        table = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        columns = parsed.get_binding('colnames', None)
 +        if columns is not None:
 +            columns = map(self.cql_unprotect_name, columns)
 +        else:
 +            # default to all known columns
 +            columns = self.get_column_names(ks, table)
 +
 +        fname = parsed.get_binding('fname', None)
 +        if fname is not None:
 +            fname = self.cql_unprotect_value(fname)
 +
 +        copyoptnames = map(str.lower, parsed.get_binding('optnames', ()))
 +        copyoptvals = map(self.cql_unprotect_value, parsed.get_binding('optvals', ()))
 +        opts = dict(zip(copyoptnames, copyoptvals))
 +
 +        direction = parsed.get_binding('dir').upper()
 +        if direction == 'FROM':
 +            task = ImportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        elif direction == 'TO':
 +            task = ExportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        else:
 +            raise SyntaxError("Unknown direction %s" % direction)
 +
 +        task.run()
 +
 +    def do_show(self, parsed):
 +        """
 +        SHOW [cqlsh only]
 +
 +          Displays information about the current cqlsh session. Can be called in
 +          the following ways:
 +
 +        SHOW VERSION
 +
 +          Shows the version and build of the connected Cassandra instance, as
 +          well as the versions of the CQL spec and the Thrift protocol that
 +          the connected Cassandra instance understands.
 +
 +        SHOW HOST
 +
 +          Shows where cqlsh is currently connected.
 +
 +        SHOW SESSION <sessionid>
 +
 +          Pretty-prints the requested tracing session.
 +        """
 +        showwhat = parsed.get_binding('what').lower()
 +        if showwhat == 'version':
 +            self.get_connection_versions()
 +            self.show_version()
 +        elif showwhat == 'host':
 +            self.show_host()
 +        elif showwhat.startswith('session'):
 +            session_id = parsed.get_binding('sessionid').lower()
 +            self.show_session(UUID(session_id))
 +        else:
 +            self.printerr('Wait, how do I show %r?' % (showwhat,))
 +
 +    def do_source(self, parsed):
 +        """
 +        SOURCE [cqlsh only]
 +
 +        Executes a file containing CQL statements. Gives the output for each
 +        statement in turn, if any, or any errors that occur along the way.
 +
 +        Errors do NOT abort execution of the CQL source file.
 +
 +        Usage:
 +
 +          SOURCE '<file>';
 +
 +        That is, the path to the file to be executed must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        See also the --file option to cqlsh.
 +        """
 +        fname = parsed.get_binding('fname')
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            encoding, bom_size = get_file_encoding_bomsize(fname)
 +            f = codecs.open(fname, 'r', encoding)
 +            f.seek(bom_size)
 +        except IOError, e:
 +            self.printerr('Could not open %r: %s' % (fname, e))
 +            return
 +        username = self.auth_provider.username if self.auth_provider else None
 +        password = self.auth_provider.password if self.auth_provider else None
 +        subshell = Shell(self.hostname, self.port, color=self.color,
 +                         username=username, password=password,
 +                         encoding=self.encoding, stdin=f, tty=False, use_conn=self.conn,
 +                         cqlver=self.cql_version, keyspace=self.current_keyspace,
 +                         tracing_enabled=self.tracing_enabled,
 +                         display_nanotime_format=self.display_nanotime_format,
 +                         display_timestamp_format=self.display_timestamp_format,
 +                         display_date_format=self.display_date_format,
 +                         display_float_precision=self.display_float_precision,
 +                         display_timezone=self.display_timezone,
 +                         max_trace_wait=self.max_trace_wait, ssl=self.ssl,
 +                         request_timeout=self.session.default_timeout,
 +                         connect_timeout=self.conn.connect_timeout)
 +        subshell.cmdloop()
 +        f.close()
 +
 +    def do_capture(self, parsed):
 +        """
 +        CAPTURE [cqlsh only]
 +
 +        Begins capturing command output and appending it to a specified file.
 +        Output will not be shown at the console while it is captured.
 +
 +        Usage:
 +
 +          CAPTURE '<file>';
 +          CAPTURE OFF;
 +          CAPTURE;
 +
 +        That is, the path to the file to be appended to must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        Only query result output is captured. Errors and output from cqlsh-only
 +        commands will still be shown in the cqlsh session.
 +
 +        To stop capturing output and show it in the cqlsh session again, use
 +        CAPTURE OFF.
 +
 +        To inspect the current capture configuration, use CAPTURE with no
 +        arguments.
 +        """
 +        fname = parsed.get_binding('fname')
 +        if fname is None:
 +            if self.shunted_query_out is not None:
 +                print "Currently capturing query output to %r." % (self.query_out.name,)
 +            else:
 +                print "Currently not capturing query output."
 +            return
 +
 +        if fname.upper() == 'OFF':
 +            if self.shunted_query_out is None:
 +                self.printerr('Not currently capturing output.')
 +                return
 +            self.query_out.close()
 +            self.query_out = self.shunted_query_out
 +            self.color = self.shunted_color
 +            self.shunted_query_out = None
 +            del self.shunted_color
 +            return
 +
 +        if self.shunted_query_out is not None:
 +            self.printerr('Already capturing output to %s. Use CAPTURE OFF'
 +                          ' to disable.' % (self.query_out.name,))
 +            return
 +
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            f = open(fname, 'a')
 +        except IOError, e:
 +            self.printerr('Could not open %r for append: %s' % (fname, e))
 +            return
 +        self.shunted_query_out = self.query_out
 +        self.shunted_color = self.color
 +        self.query_out = f
 +        self.color = False
 +        print 'Now capturing query output to %r.' % (fname,)
 +
 +    def do_tracing(self, parsed):
 +        """
 +        TRACING [cqlsh]
 +
 +          Enables or disables request tracing.
 +
 +        TRACING ON
 +
 +          Enables tracing for all further requests.
 +
 +        TRACING OFF
 +
 +          Disables tracing.
 +
 +        TRACING
 +
 +          TRACING with no arguments shows the current tracing status.
 +        """
 +        self.tracing_enabled = SwitchCommand("TRACING", "Tracing").execute(self.tracing_enabled, parsed, self.printerr)
 +
 +    def do_expand(self, parsed):
 +        """
 +        EXPAND [cqlsh]
 +
 +          Enables or disables expanded (vertical) output.
 +
 +        EXPAND ON
 +
 +          Enables expanded (vertical) output.
 +
 +        EXPAND OFF
 +
 +          Disables expanded (vertical) output.
 +
 +        EXPAND
 +
 +          EXPAND with no arguments shows the current value of expand setting.
 +        """
 +        self.expand_enabled = SwitchCommand("EXPAND", "Expanded output").execute(self.expand_enabled, parsed, self.printerr)
 +
 +    def do_consistency(self, parsed):
 +        """
 +        CONSISTENCY [cqlsh only]
 +
 +           Overrides default consistency level (default level is ONE).
 +
 +        CONSISTENCY <level>
 +
 +           Sets consistency level for future requests.
 +
 +           Valid consistency levels:
 +
 +           ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM, SERIAL and LOCAL_SERIAL.
 +
 +           SERIAL and LOCAL_SERIAL may be used only for SELECTs; will be rejected with updates.
 +
 +        CONSISTENCY
 +
 +           CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.consistency_level])
 +            return
 +
 +        self.consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Consistency level set to %s.' % (level.upper(),)
 +
 +    def do_serial(self, parsed):
 +        """
 +        SERIAL CONSISTENCY [cqlsh only]
 +
 +           Overrides serial consistency level (default level is SERIAL).
 +
 +        SERIAL CONSISTENCY <level>
 +
 +           Sets consistency level for future conditional updates.
 +
 +           Valid consistency levels:
 +
 +           SERIAL, LOCAL_SERIAL.
 +
 +        SERIAL CONSISTENCY
 +
 +           SERIAL CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current serial consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.serial_consistency_level])
 +            return
 +
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Serial consistency level set to %s.' % (level.upper(),)
 +
 +    def do_login(self, parsed):
 +        """
 +        LOGIN [cqlsh only]
 +
 +           Changes login information without requiring restart.
 +
 +        LOGIN <username> (<password>)
 +
 +           Login using the specified username. If password is specified, it will be used
 +           otherwise, you will be prompted to enter.
 +        """
 +        username = parsed.get_binding('username')
 +        password = parsed.get_binding('password')
 +        if password is None:
 +            password = getpass.getpass()
 +        else:
 +            password = password[1:-1]
 +
 +        auth_provider = PlainTextAuthProvider(username=username, password=password)
 +
 +        conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=self.conn.cql_version,
 +                       protocol_version=self.conn.protocol_version,
 +                       auth_provider=auth_provider,
 +                       ssl_options=self.conn.ssl_options,
 +                       load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                       control_connection_timeout=self.conn.connect_timeout,
 +                       connect_timeout=self.conn.connect_timeout)
 +
 +        if self.current_keyspace:
 +            session = conn.connect(self.current_keyspace)
 +        else:
 +            session = conn.connect()
 +
 +        # Copy session properties
 +        session.default_timeout = self.session.default_timeout
 +        session.row_factory = self.session.row_factory
 +        session.default_consistency_level = self.session.default_consistency_level
 +        session.max_trace_wait = self.session.max_trace_wait
 +
 +        # Update after we've connected in case we fail to authenticate
 +        self.conn = conn
 +        self.auth_provider = auth_provider
 +        self.username = username
 +        self.session = session
 +
 +    def do_exit(self, parsed=None):
 +        """
 +        EXIT/QUIT [cqlsh only]
 +
 +        Exits cqlsh.
 +        """
 +        self.stop = True
 +        if self.owns_connection:
 +            self.conn.shutdown()
 +    do_quit = do_exit
 +
 +    def do_clear(self, parsed):
 +        """
 +        CLEAR/CLS [cqlsh only]
 +
 +        Clears the console.
 +        """
 +        import subprocess
 +

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[08/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
Merge branch 'cassandra-2.1' into cassandra-2.2


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

Branch: refs/heads/trunk
Commit: 503aec74a56a5aada7398bf38b67ceb8743b027e
Parents: b800f3c f8d73a3
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 05:58:04 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:01:14 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 266ed14,6e1ca85..055a35d
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -1,25 -1,9 +1,27 @@@
 -2.1.20
 +2.2.12
 + * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
 + * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
 + * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
++Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.1.19
 +2.2.11
 + * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
 + * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)
 + * Fix compaction and flush exception not captured (CASSANDRA-13833)
 + * Make BatchlogManagerMBean.forceBatchlogReplay() blocking (CASSANDRA-13809)
 + * Uncaught exceptions in Netty pipeline (CASSANDRA-13649)
 + * Prevent integer overflow on exabyte filesystems (CASSANDRA-13067) 
 + * Fix queries with LIMIT and filtering on clustering columns (CASSANDRA-11223)
 + * Fix potential NPE when resume bootstrap fails (CASSANDRA-13272)
 + * Fix toJSONString for the UDT, tuple and collection types (CASSANDRA-13592)
 + * Fix nested Tuples/UDTs validation (CASSANDRA-13646)
 + * Remove unused max_value_size_in_mb config setting from yaml (CASSANDRA-13625
 +Merged from 2.1:
   * Add storage port options to sstableloader (CASSANDRA-13844)
 - * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775) 
 + * Remove stress-test target in CircleCI as it's not existing (CASSANDRA-13775)
   * Clone HeartBeatState when building gossip messages. Make its generation/version volatile (CASSANDRA-13700)
  
  


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[05/23] cassandra git commit: More PEP8 compliance for cqlsh

Posted by ja...@apache.org.
More PEP8 compliance for cqlsh

patch by Michael Kjellman; reviewed by Jay Zhuang for CASSANDRA-14021


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

Branch: refs/heads/cassandra-3.11
Commit: f8d73a3acb00d807d09aa33e1612c89389b18480
Parents: d4fd82b
Author: Michael Kjellman <kj...@apple.com>
Authored: Tue Nov 14 20:51:37 2017 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 05:56:44 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 +-
 bin/cqlsh                      |  4 ++++
 pylib/cqlshlib/copyutil.py     |  6 +++---
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b4e6f75..6e1ca85 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
 2.1.20
- * 
+ * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 
 2.1.19
  * Add storage port options to sstableloader (CASSANDRA-13844)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 6317ec9..30840db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -83,6 +83,7 @@ def find_zip(libprefix):
         if zips:
             return max(zips)   # probably the highest version, if multiple
 
+
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
@@ -522,6 +523,8 @@ def show_warning_without_quoting_line(message, category, filename, lineno, file=
         file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
     except IOError:
         pass
+
+
 warnings.showwarning = show_warning_without_quoting_line
 warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 
@@ -2213,6 +2216,7 @@ def main(options, hostname, port):
     if batch_mode and shell.statement_error:
         sys.exit(2)
 
+
 # always call this regardless of module name: when a sub-process is spawned
 # on Windows then the module name is not __main__, see CASSANDRA-9304
 insert_driver_hooks()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py
index 3a45353..85e2678 100644
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@ -191,7 +191,7 @@ class OneWayChannels(object):
         for ch in self.channels:
             try:
                 ch.close()
-            except:
+            except Exception:
                 pass
 
 
@@ -1967,8 +1967,8 @@ class ImportConversion(object):
             pk_values = []
             for i in partition_key_indexes:
                 val = serialize(i, row[i])
-                l = len(val)
-                pk_values.append(struct.pack(">H%dsB" % l, l, val, 0))
+                length = len(val)
+                pk_values.append(struct.pack(">H%dsB" % length, length, val, 0))
             return b"".join(pk_values)
 
         if len(partition_key_indexes) == 1:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 029e0c7..012e383 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,6 +34,7 @@ class UnexpectedTableStructure(UserWarning):
     def __str__(self):
         return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
 
+
 SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 NONALTERBALE_KEYSPACES = ('system')
 
@@ -109,6 +110,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
             cqlword = cqlword[1:-1].replace("''", "'")
         return cqlword
 
+
 CqlRuleSet = Cql3ParsingRuleSet()
 
 # convenience for remainder of module
@@ -306,6 +308,7 @@ def prop_equals_completer(ctxt, cass):
             return ()
     return ['=']
 
+
 completer_for('property', 'propeq')(prop_equals_completer)
 
 
@@ -529,6 +532,7 @@ def ks_name_completer(ctxt, cass):
 def cf_ks_name_completer(ctxt, cass):
     return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
 
+
 completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 
 
@@ -538,6 +542,7 @@ def cf_ks_dot_completer(ctxt, cass):
         return ['.']
     return []
 
+
 completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 
 
@@ -554,6 +559,7 @@ def cf_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, cfnames)
 
+
 completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
 
 completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
@@ -606,6 +612,7 @@ def working_on_keyspace(ctxt):
         return True
     return False
 
+
 syntax_rules += r'''
 <useStatement> ::= "USE" <keyspaceName>
                  ;
@@ -694,6 +701,7 @@ def select_relation_lhs_completer(ctxt, cass):
 def select_count_star_completer(ctxt, cass):
     return ['*']
 
+
 explain_completion('selector', 'colname')
 
 syntax_rules += r'''
@@ -770,6 +778,7 @@ def insert_option_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <updateStatement> ::= "UPDATE" cf=<columnFamilyName>
                         ( "USING" [updateopt]=<usingOption>
@@ -863,6 +872,7 @@ def update_indexbracket_completer(ctxt, cass):
         return ['[']
     return []
 
+
 syntax_rules += r'''
 <deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
                         "FROM" cf=<columnFamilyName>
@@ -890,6 +900,7 @@ def delete_delcol_completer(ctxt, cass):
     layout = get_table_meta(ctxt, cass)
     return map(maybe_escape_name, regular_column_names(layout))
 
+
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
                         ( "USING" [batchopt]=<usingOption>
@@ -912,6 +923,7 @@ def batch_opt_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
                       ;
@@ -931,6 +943,7 @@ def create_ks_wat_completer(ctxt, cass):
         return ['KEYSPACE']
     return ['KEYSPACE', 'SCHEMA']
 
+
 syntax_rules += r'''
 <createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
                                     ( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
@@ -979,6 +992,7 @@ def create_cf_wat_completer(ctxt, cass):
         return ['TABLE']
     return ['TABLE', 'COLUMNFAMILY']
 
+
 explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
 explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
 
@@ -1033,6 +1047,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
         return ()
     return [',']
 
+
 syntax_rules += r'''
 
 <idxName> ::= <identifier>
@@ -1065,6 +1080,7 @@ def create_index_col_completer(ctxt, cass):
     colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
+
 syntax_rules += r'''
 <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                           ;
@@ -1113,6 +1129,7 @@ def idx_ks_idx_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, idxnames)
 
+
 syntax_rules += r'''
 <alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
                                <alterInstructions>
@@ -1149,6 +1166,7 @@ def alter_type_field_completer(ctxt, cass):
     fields = [tuple[0] for tuple in layout]
     return map(maybe_escape_name, fields)
 
+
 explain_completion('alterInstructions', 'newcol', '<new_column_name>')
 explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
 
@@ -1227,6 +1245,7 @@ def username_name_completer(ctxt, cass):
     session = cass.session
     return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
+
 syntax_rules += r'''
 <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
@@ -1251,6 +1270,7 @@ def alter_type_field_completer(ctxt, cass):
     names = get_trigger_names(ctxt, cass)
     return map(maybe_escape_name, names)
 
+
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/displaying.py b/pylib/cqlshlib/displaying.py
index 7b260c2..09068ca 100644
--- a/pylib/cqlshlib/displaying.py
+++ b/pylib/cqlshlib/displaying.py
@@ -99,6 +99,7 @@ class FormattedValue:
         """
         return self.coloredval + self._pad(width, fill)
 
+
 DEFAULT_VALUE_COLORS = dict(
     default=YELLOW,
     text=YELLOW,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index abb4896..eac1810 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -38,6 +38,7 @@ def _show_control_chars(match):
         txt = txt[1:-1]
     return txt
 
+
 bits_to_turn_red_re = re.compile(r'\\([^uUx]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|U[0-9a-fA-F]{8})')
 
 
@@ -49,6 +50,7 @@ def _make_turn_bits_red_f(color1, color2):
         return color1 + txt + color2
     return _turn_bits_red
 
+
 default_null_placeholder = 'null'
 default_time_format = ''
 default_float_precision = 3
@@ -101,6 +103,7 @@ def format_value_default(val, colormap, **_):
     bval = controlchars_re.sub(_show_control_chars, escapedval)
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap)
 
+
 # Mapping cql type base names ("int", "map", etc) to formatter functions,
 # making format_value a generic function
 _formatters = {}
@@ -128,6 +131,8 @@ def formatter_for(typname):
 def format_value_blob(val, colormap, **_):
     bval = '0x' + binascii.hexlify(str(val))
     return colorme(bval, colormap, 'blob')
+
+
 formatter_for('buffer')(format_value_blob)
 
 
@@ -188,6 +193,7 @@ def format_floating_point_type(val, colormap, float_precision, decimal_sep=None,
 
     return colorme(bval, colormap, 'float')
 
+
 formatter_for('float')(format_floating_point_type)
 
 
@@ -196,6 +202,7 @@ def format_integer_type(val, colormap, thousands_sep=None, **_):
     bval = format_integer_with_thousands_sep(val, thousands_sep) if thousands_sep else str(val)
     return colorme(bval, colormap, 'int')
 
+
 # We can get rid of this in cassandra-2.2
 if sys.version_info >= (2, 7):
     def format_integer_with_thousands_sep(val, thousands_sep=','):
@@ -221,6 +228,7 @@ def format_value_timestamp(val, colormap, time_format, quote=False, **_):
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+
 formatter_for('datetime')(format_value_timestamp)
 
 
@@ -241,6 +249,7 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
 
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
 
+
 # name alias
 formatter_for('unicode')(format_value_text)
 
@@ -286,6 +295,8 @@ def format_value_set(val, encoding, colormap, time_format, float_precision, null
     return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval,
                                     decimal_sep, thousands_sep, boolean_styles)
+
+
 formatter_for('frozenset')(format_value_set)
 # This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 # and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
@@ -314,6 +325,8 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, null
         + 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)
 formatter_for('OrderedMap')(format_value_map)
 formatter_for('OrderedMapSerializedKey')(format_value_map)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index 9cf0f4e..7b11eac 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -518,6 +518,7 @@ class ParsingRuleSet:
         pattern.match(ctxt, completions)
         return completions
 
+
 import sys
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/wcwidth.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/wcwidth.py b/pylib/cqlshlib/wcwidth.py
index bc55c31..985fd41 100644
--- a/pylib/cqlshlib/wcwidth.py
+++ b/pylib/cqlshlib/wcwidth.py
@@ -94,6 +94,7 @@ def bisearch(ucs, table):
             return 1
     return 0
 
+
 # The following two functions define the column width of an ISO 10646
 # character as follows:
 #
@@ -178,6 +179,7 @@ combining = (
     (0xE0100, 0xE01EF)
 )
 
+
 # sorted list of non-overlapping intervals of East Asian Ambiguous
 # characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 ambiguous = (
@@ -321,6 +323,7 @@ def wcwidth_cjk(c):
 def wcswidth_cjk(s):
     return mk_wcswidth_cjk(map(ord, s))
 
+
 if __name__ == "__main__":
     samples = (
         ('MUSIC SHARP SIGN', 1),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[07/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/bin/cqlsh.py
----------------------------------------------------------------------
diff --cc bin/cqlsh.py
index 1f63826,0000000..e242d42
mode 100644,000000..100644
--- a/bin/cqlsh.py
+++ b/bin/cqlsh.py
@@@ -1,2588 -1,0 +1,2592 @@@
 +#!/bin/sh
 +# -*- mode: Python -*-
 +
 +# 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.
 +
 +""":"
 +# bash code here; finds a suitable python interpreter and execs this file.
 +# prefer unqualified "python" if suitable:
 +python -c 'import sys; sys.exit(not (0x020700b0 < sys.hexversion < 0x03000000))' 2>/dev/null \
 +    && exec python "$0" "$@"
 +for pyver in 2.7; do
 +    which python$pyver > /dev/null 2>&1 && exec python$pyver "$0" "$@"
 +done
 +echo "No appropriate python interpreter found." >&2
 +exit 1
 +":"""
 +
 +from __future__ import with_statement
 +
 +import cmd
 +import codecs
 +import ConfigParser
 +import csv
 +import getpass
 +import optparse
 +import os
 +import platform
 +import sys
 +import traceback
 +import warnings
 +import webbrowser
 +from StringIO import StringIO
 +from contextlib import contextmanager
 +from glob import glob
 +from uuid import UUID
 +
 +if sys.version_info[0] != 2 or sys.version_info[1] != 7:
 +    sys.exit("\nCQL Shell supports only Python 2.7\n")
 +
 +UTF8 = 'utf-8'
 +CP65001 = 'cp65001'  # Win utf-8 variant
 +
 +description = "CQL Shell for Apache Cassandra"
 +version = "5.0.1"
 +
 +readline = None
 +try:
 +    # check if tty first, cause readline doesn't check, and only cares
 +    # about $TERM. we don't want the funky escape code stuff to be
 +    # output if not a tty.
 +    if sys.stdin.isatty():
 +        import readline
 +except ImportError:
 +    pass
 +
 +CQL_LIB_PREFIX = 'cassandra-driver-internal-only-'
 +
 +CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
 +CASSANDRA_CQL_HTML_FALLBACK = 'https://cassandra.apache.org/doc/cql3/CQL-2.2.html'
 +
 +if os.path.exists(CASSANDRA_PATH + '/doc/cql3/CQL.html'):
 +    # default location of local CQL.html
 +    CASSANDRA_CQL_HTML = 'file://' + CASSANDRA_PATH + '/doc/cql3/CQL.html'
 +elif os.path.exists('/usr/share/doc/cassandra/CQL.html'):
 +    # fallback to package file
 +    CASSANDRA_CQL_HTML = 'file:///usr/share/doc/cassandra/CQL.html'
 +else:
 +    # fallback to online version
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +
 +# On Linux, the Python webbrowser module uses the 'xdg-open' executable
 +# to open a file/URL. But that only works, if the current session has been
 +# opened from _within_ a desktop environment. I.e. 'xdg-open' will fail,
 +# if the session's been opened via ssh to a remote box.
 +#
 +# Use 'python' to get some information about the detected browsers.
 +# >>> import webbrowser
 +# >>> webbrowser._tryorder
 +# >>> webbrowser._browser
 +#
 +if len(webbrowser._tryorder) == 0:
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +elif webbrowser._tryorder[0] == 'xdg-open' and os.environ.get('XDG_DATA_DIRS', '') == '':
 +    # only on Linux (some OS with xdg-open)
 +    webbrowser._tryorder.remove('xdg-open')
 +    webbrowser._tryorder.append('xdg-open')
 +
 +# use bundled libs for python-cql and thrift, if available. if there
 +# is a ../lib dir, use bundled libs there preferentially.
 +ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')]
 +myplatform = platform.system()
 +is_win = myplatform == 'Windows'
 +
 +# Workaround for supporting CP65001 encoding on python < 3.3 (https://bugs.python.org/issue13216)
 +if is_win and sys.version_info < (3, 3):
 +    codecs.register(lambda name: codecs.lookup(UTF8) if name == CP65001 else None)
 +
 +if myplatform == 'Linux':
 +    ZIPLIB_DIRS.append('/usr/share/cassandra/lib')
 +
 +if os.environ.get('CQLSH_NO_BUNDLED', ''):
 +    ZIPLIB_DIRS = ()
 +
 +
 +def find_zip(libprefix):
 +    for ziplibdir in ZIPLIB_DIRS:
 +        zips = glob(os.path.join(ziplibdir, libprefix + '*.zip'))
 +        if zips:
 +            return max(zips)   # probably the highest version, if multiple
 +
++
 +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, 'cassandra-driver-' + ver))
 +
 +third_parties = ('futures-', 'six-')
 +
 +for lib in third_parties:
 +    lib_zip = find_zip(lib)
 +    if lib_zip:
 +        sys.path.insert(0, lib_zip)
 +
 +warnings.filterwarnings("ignore", r".*blist.*")
 +try:
 +    import cassandra
 +except ImportError, e:
 +    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))
 +
 +from cassandra.auth import PlainTextAuthProvider
 +from cassandra.cluster import Cluster
 +from cassandra.metadata import (ColumnMetadata, KeyspaceMetadata,
 +                                TableMetadata, protect_name, protect_names)
 +from cassandra.policies import WhiteListRoundRobinPolicy
 +from cassandra.query import SimpleStatement, ordered_dict_factory, TraceUnavailable
 +
 +# cqlsh should run correctly when run out of a Cassandra source tree,
 +# out of an unpacked Cassandra tarball, and after a proper package install.
 +cqlshlibdir = os.path.join(CASSANDRA_PATH, 'pylib')
 +if os.path.isdir(cqlshlibdir):
 +    sys.path.insert(0, cqlshlibdir)
 +
 +from cqlshlib import cql3handling, cqlhandling, pylexotron, sslhandling
 +from cqlshlib.copyutil import ExportTask, ImportTask
 +from cqlshlib.displaying import (ANSI_RESET, BLUE, COLUMN_NAME_COLORS, CYAN,
 +                                 RED, FormattedValue, colorme)
 +from cqlshlib.formatting import (DEFAULT_DATE_FORMAT, DEFAULT_NANOTIME_FORMAT,
 +                                 DEFAULT_TIMESTAMP_FORMAT, DateTimeFormat,
 +                                 format_by_type, format_value_utype,
 +                                 formatter_for)
 +from cqlshlib.tracing import print_trace, print_trace_session
 +from cqlshlib.util import get_file_encoding_bomsize, trim_if_present
 +
 +DEFAULT_HOST = '127.0.0.1'
 +DEFAULT_PORT = 9042
 +DEFAULT_CQLVER = '3.3.1'
 +DEFAULT_PROTOCOL_VERSION = 4
 +DEFAULT_CONNECT_TIMEOUT_SECONDS = 5
 +DEFAULT_REQUEST_TIMEOUT_SECONDS = 10
 +
 +DEFAULT_FLOAT_PRECISION = 5
 +DEFAULT_MAX_TRACE_WAIT = 10
 +
 +if readline is not None and readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +    DEFAULT_COMPLETEKEY = '\t'
 +else:
 +    DEFAULT_COMPLETEKEY = 'tab'
 +
 +cqldocs = None
 +cqlruleset = None
 +
 +epilog = """Connects to %(DEFAULT_HOST)s:%(DEFAULT_PORT)d by default. These
 +defaults can be changed by setting $CQLSH_HOST and/or $CQLSH_PORT. When a
 +host (and optional port number) are given on the command line, they take
 +precedence over any defaults.""" % globals()
 +
 +parser = optparse.OptionParser(description=description, epilog=epilog,
 +                               usage="Usage: %prog [options] [host [port]]",
 +                               version='cqlsh ' + version)
 +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("--browser", dest='browser', help="""The browser to use to display CQL help, where BROWSER can be:
 +                                                    - one of the supported browsers in https://docs.python.org/2/library/webbrowser.html.
 +                                                    - browser path followed by %s, example: /usr/bin/google-chrome-stable %s""")
 +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('--debug', action='store_true',
 +                  help='Show additional debugging information')
 +parser.add_option("--encoding", help="Specify a non-default encoding for output." +
 +                  " (Default: %s)" % (UTF8,))
 +parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.")
 +parser.add_option('--cqlversion', default=DEFAULT_CQLVER,
 +                  help='Specify a particular CQL version (default: %default).'
 +                       ' Examples: "3.0.3", "3.1.0"')
 +parser.add_option("-e", "--execute", help='Execute the statement and quit.')
 +parser.add_option("--connect-timeout", default=DEFAULT_CONNECT_TIMEOUT_SECONDS, dest='connect_timeout',
 +                  help='Specify the connection timeout in seconds (default: %default seconds).')
 +parser.add_option("--request-timeout", default=DEFAULT_REQUEST_TIMEOUT_SECONDS, dest='request_timeout',
 +                  help='Specify the default request timeout in seconds (default: %default seconds).')
 +parser.add_option("-t", "--tty", action='store_true', dest='tty',
 +                  help='Force tty mode (command prompt).')
 +
 +optvalues = optparse.Values()
 +(options, arguments) = parser.parse_args(sys.argv[1:], values=optvalues)
 +
 +# BEGIN history/config definition
 +HISTORY_DIR = os.path.expanduser(os.path.join('~', '.cassandra'))
 +
 +if hasattr(options, 'cqlshrc'):
 +    CONFIG_FILE = options.cqlshrc
 +    if not os.path.exists(CONFIG_FILE):
 +        print '\nWarning: Specified cqlshrc location `%s` does not exist.  Using `%s` instead.\n' % (CONFIG_FILE, HISTORY_DIR)
 +        CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +else:
 +    CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +
 +HISTORY = os.path.join(HISTORY_DIR, 'cqlsh_history')
 +if not os.path.exists(HISTORY_DIR):
 +    try:
 +        os.mkdir(HISTORY_DIR)
 +    except OSError:
 +        print '\nWarning: Cannot create directory at `%s`. Command history will not be saved.\n' % HISTORY_DIR
 +
 +OLD_CONFIG_FILE = os.path.expanduser(os.path.join('~', '.cqlshrc'))
 +if os.path.exists(OLD_CONFIG_FILE):
 +    if os.path.exists(CONFIG_FILE):
 +        print '\nWarning: cqlshrc config files were found at both the old location (%s) and \
 +                the new location (%s), the old config file will not be migrated to the new \
 +                location, and the new location will be used for now.  You should manually \
 +                consolidate the config files at the new location and remove the old file.' \
 +                % (OLD_CONFIG_FILE, CONFIG_FILE)
 +    else:
 +        os.rename(OLD_CONFIG_FILE, CONFIG_FILE)
 +OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
 +if os.path.exists(OLD_HISTORY):
 +    os.rename(OLD_HISTORY, HISTORY)
 +# END history/config definition
 +
 +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.protocol.ErrorMessage, cassandra.protocol.InternalError, cassandra.query.TraceUnavailable
 +)
 +
 +debug_completion = bool(os.environ.get('CQLSH_DEBUG_COMPLETION', '') == 'YES')
 +
 +# we want the cql parser to understand our cqlsh-specific commands too
 +my_commands_ending_with_newline = (
 +    'help',
 +    '?',
 +    'consistency',
 +    'serial',
 +    'describe',
 +    'desc',
 +    'show',
 +    'source',
 +    'capture',
 +    'login',
 +    'debug',
 +    'tracing',
 +    'expand',
 +    'paging',
 +    'exit',
 +    'quit',
 +    'clear',
 +    'cls'
 +)
 +
 +
 +cqlsh_syntax_completers = []
 +
 +
 +def cqlsh_syntax_completer(rulename, termname):
 +    def registrator(f):
 +        cqlsh_syntax_completers.append((rulename, termname, f))
 +        return f
 +    return registrator
 +
 +
 +cqlsh_extra_syntax_rules = r'''
 +<cqlshCommand> ::= <CQL_Statement>
 +                 | <specialCommand> ( ";" | "\n" )
 +                 ;
 +
 +<specialCommand> ::= <describeCommand>
 +                   | <consistencyCommand>
 +                   | <serialConsistencyCommand>
 +                   | <showCommand>
 +                   | <sourceCommand>
 +                   | <captureCommand>
 +                   | <copyCommand>
 +                   | <loginCommand>
 +                   | <debugCommand>
 +                   | <helpCommand>
 +                   | <tracingCommand>
 +                   | <expandCommand>
 +                   | <exitCommand>
 +                   | <pagingCommand>
 +                   | <clearCommand>
 +                   ;
 +
 +<describeCommand> ::= ( "DESCRIBE" | "DESC" )
 +                                  ( "FUNCTIONS"
 +                                  | "FUNCTION" udf=<anyFunctionName>
 +                                  | "AGGREGATES"
 +                                  | "AGGREGATE" uda=<userAggregateName>
 +                                  | "KEYSPACES"
 +                                  | "KEYSPACE" ksname=<keyspaceName>?
 +                                  | ( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
 +                                  | "INDEX" idx=<indexName>
 +                                  | ( "COLUMNFAMILIES" | "TABLES" )
 +                                  | "FULL"? "SCHEMA"
 +                                  | "CLUSTER"
 +                                  | "TYPES"
 +                                  | "TYPE" ut=<userTypeName>
 +                                  | (ksname=<keyspaceName> | cf=<columnFamilyName> | idx=<indexName>))
 +                    ;
 +
 +<consistencyCommand> ::= "CONSISTENCY" ( level=<consistencyLevel> )?
 +                       ;
 +
 +<consistencyLevel> ::= "ANY"
 +                     | "ONE"
 +                     | "TWO"
 +                     | "THREE"
 +                     | "QUORUM"
 +                     | "ALL"
 +                     | "LOCAL_QUORUM"
 +                     | "EACH_QUORUM"
 +                     | "SERIAL"
 +                     | "LOCAL_SERIAL"
 +                     | "LOCAL_ONE"
 +                     ;
 +
 +<serialConsistencyCommand> ::= "SERIAL" "CONSISTENCY" ( level=<serialConsistencyLevel> )?
 +                             ;
 +
 +<serialConsistencyLevel> ::= "SERIAL"
 +                           | "LOCAL_SERIAL"
 +                           ;
 +
 +<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid=<uuid> )
 +                ;
 +
 +<sourceCommand> ::= "SOURCE" fname=<stringLiteral>
 +                  ;
 +
 +<captureCommand> ::= "CAPTURE" ( fname=( <stringLiteral> | "OFF" ) )?
 +                   ;
 +
 +<copyCommand> ::= "COPY" cf=<columnFamilyName>
 +                         ( "(" [colnames]=<colname> ( "," [colnames]=<colname> )* ")" )?
 +                         ( dir="FROM" ( fname=<stringLiteral> | "STDIN" )
 +                         | dir="TO"   ( fname=<stringLiteral> | "STDOUT" ) )
 +                         ( "WITH" <copyOption> ( "AND" <copyOption> )* )?
 +                ;
 +
 +<copyOption> ::= [optnames]=(<identifier>|<reserved_identifier>) "=" [optvals]=<copyOptionVal>
 +               ;
 +
 +<copyOptionVal> ::= <identifier>
 +                  | <reserved_identifier>
 +                  | <term>
 +                  ;
 +
 +# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal
 +<debugCommand> ::= "DEBUG" "THINGS"?
 +                 ;
 +
 +<helpCommand> ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )*
 +                ;
 +
 +<tracingCommand> ::= "TRACING" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<expandCommand> ::= "EXPAND" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<pagingCommand> ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )?
 +                  ;
 +
 +<loginCommand> ::= "LOGIN" username=<username> (password=<stringLiteral>)?
 +                 ;
 +
 +<exitCommand> ::= "exit" | "quit"
 +                ;
 +
 +<clearCommand> ::= "CLEAR" | "CLS"
 +                 ;
 +
 +<qmark> ::= "?" ;
 +'''
 +
 +
 +@cqlsh_syntax_completer('helpCommand', 'topic')
 +def complete_help(ctxt, cqlsh):
 +    return sorted([t.upper() for t in cqldocs.get_help_topics() + cqlsh.get_help_topics()])
 +
 +
 +def complete_source_quoted_filename(ctxt, cqlsh):
 +    partial_path = ctxt.get_binding('partial', '')
 +    head, tail = os.path.split(partial_path)
 +    exhead = os.path.expanduser(head)
 +    try:
 +        contents = os.listdir(exhead or '.')
 +    except OSError:
 +        return ()
 +    matches = filter(lambda f: f.startswith(tail), contents)
 +    annotated = []
 +    for f in matches:
 +        match = os.path.join(head, f)
 +        if os.path.isdir(os.path.join(exhead, f)):
 +            match += '/'
 +        annotated.append(match)
 +    return annotated
 +
 +
 +cqlsh_syntax_completer('sourceCommand', 'fname')(complete_source_quoted_filename)
 +cqlsh_syntax_completer('captureCommand', 'fname')(complete_source_quoted_filename)
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'fname')
 +def copy_fname_completer(ctxt, cqlsh):
 +    lasttype = ctxt.get_binding('*LASTTYPE*')
 +    if lasttype == 'unclosedString':
 +        return complete_source_quoted_filename(ctxt, cqlsh)
 +    partial_path = ctxt.get_binding('partial')
 +    if partial_path == '':
 +        return ["'"]
 +    return ()
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'colnames')
 +def complete_copy_column_names(ctxt, cqlsh):
 +    existcols = map(cqlsh.cql_unprotect_name, ctxt.get_binding('colnames', ()))
 +    ks = cqlsh.cql_unprotect_name(ctxt.get_binding('ksname', None))
 +    cf = cqlsh.cql_unprotect_name(ctxt.get_binding('cfname'))
 +    colnames = cqlsh.get_column_names(ks, cf)
 +    if len(existcols) == 0:
 +        return [colnames[0]]
 +    return set(colnames[1:]) - set(existcols)
 +
 +
 +COPY_COMMON_OPTIONS = ['DELIMITER', 'QUOTE', 'ESCAPE', 'HEADER', 'NULL', 'DATETIMEFORMAT',
 +                       'MAXATTEMPTS', 'REPORTFREQUENCY', 'DECIMALSEP', 'THOUSANDSSEP', 'BOOLSTYLE',
 +                       'NUMPROCESSES', 'CONFIGFILE', 'RATEFILE']
 +COPY_FROM_OPTIONS = ['CHUNKSIZE', 'INGESTRATE', 'MAXBATCHSIZE', 'MINBATCHSIZE', 'MAXROWS',
 +                     'SKIPROWS', 'SKIPCOLS', 'MAXPARSEERRORS', 'MAXINSERTERRORS', 'ERRFILE', 'PREPAREDSTATEMENTS']
 +COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS']
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optnames')
 +def complete_copy_options(ctxt, cqlsh):
 +    optnames = map(str.upper, ctxt.get_binding('optnames', ()))
 +    direction = ctxt.get_binding('dir').upper()
 +    if direction == 'FROM':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_FROM_OPTIONS) - set(optnames)
 +    elif direction == 'TO':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_TO_OPTIONS) - set(optnames)
 +    return opts
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optvals')
 +def complete_copy_opt_values(ctxt, cqlsh):
 +    optnames = ctxt.get_binding('optnames', ())
 +    lastopt = optnames[-1].lower()
 +    if lastopt == 'header':
 +        return ['true', 'false']
 +    return [cqlhandling.Hint('<single_character_string>')]
 +
 +
 +class NoKeyspaceError(Exception):
 +    pass
 +
 +
 +class KeyspaceNotFound(Exception):
 +    pass
 +
 +
 +class ColumnFamilyNotFound(Exception):
 +    pass
 +
 +
 +class IndexNotFound(Exception):
 +    pass
 +
 +
 +class ObjectNotFound(Exception):
 +    pass
 +
 +
 +class VersionNotSupported(Exception):
 +    pass
 +
 +
 +class UserTypeNotFound(Exception):
 +    pass
 +
 +
 +class FunctionNotFound(Exception):
 +    pass
 +
 +
 +class AggregateNotFound(Exception):
 +    pass
 +
 +
 +class DecodeError(Exception):
 +    verb = 'decode'
 +
 +    def __init__(self, thebytes, err, colname=None):
 +        self.thebytes = thebytes
 +        self.err = err
 +        self.colname = colname
 +
 +    def __str__(self):
 +        return str(self.thebytes)
 +
 +    def message(self):
 +        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 : %s' \
 +               % (self.verb, what, self.err)
 +
 +    def __repr__(self):
 +        return '<%s %s>' % (self.__class__.__name__, self.message())
 +
 +
 +class FormatError(DecodeError):
 +    verb = 'format'
 +
 +
 +def full_cql_version(ver):
 +    while ver.count('.') < 2:
 +        ver += '.0'
 +    ver_parts = ver.split('-', 1) + ['']
 +    vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
 +    return ver, vertuple
 +
 +
 +def format_value(val, output_encoding, addcolor=False, date_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))
 +    return format_by_type(type(val), val, output_encoding, colormap=colormap,
 +                          addcolor=addcolor, nullval=nullval, date_time_format=date_time_format,
 +                          float_precision=float_precision)
 +
 +
 +def show_warning_without_quoting_line(message, category, filename, lineno, file=None, line=None):
 +    if file is None:
 +        file = sys.stderr
 +    try:
 +        file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
 +    except IOError:
 +        pass
++
++
 +warnings.showwarning = show_warning_without_quoting_line
 +warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 +
 +
 +def insert_driver_hooks():
 +    extend_cql_deserialization()
 +    auto_format_udts()
 +
 +
 +def extend_cql_deserialization():
 +    """
 +    The python driver returns BLOBs as string, but we expect them as bytearrays; therefore we change
 +    the implementation of cassandra.cqltypes.BytesType.deserialize.
 +
 +    The deserializers package exists only when the driver has been compiled with cython extensions and
 +    cassandra.deserializers.DesBytesType replaces cassandra.cqltypes.BytesType.deserialize.
 +
 +    DesBytesTypeByteArray is a fast deserializer that converts blobs into bytearrays but it was
 +    only introduced recently (3.1.0). If it is available we use it, otherwise we remove
 +    cassandra.deserializers.DesBytesType so that we fall back onto cassandra.cqltypes.BytesType.deserialize
 +    just like in the case where no cython extensions are present.
 +    """
 +    if hasattr(cassandra, 'deserializers'):
 +        if hasattr(cassandra.deserializers, 'DesBytesTypeByteArray'):
 +            cassandra.deserializers.DesBytesType = cassandra.deserializers.DesBytesTypeByteArray
 +        else:
 +            del cassandra.deserializers.DesBytesType
 +
 +    cassandra.cqltypes.BytesType.deserialize = staticmethod(lambda byts, protocol_version: bytearray(byts))
 +    cassandra.cqltypes.CassandraType.support_empty_values = True
 +
 +
 +def auto_format_udts():
 +    # when we see a new user defined type, set up the shell formatting for it
 +    udt_apply_params = cassandra.cqltypes.UserType.apply_parameters
 +
 +    def new_apply_params(cls, *args, **kwargs):
 +        udt_class = udt_apply_params(*args, **kwargs)
 +        formatter_for(udt_class.typename)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.udt_apply_parameters = classmethod(new_apply_params)
 +
 +    make_udt_class = cassandra.cqltypes.UserType.make_udt_class
 +
 +    def new_make_udt_class(cls, *args, **kwargs):
 +        udt_class = make_udt_class(*args, **kwargs)
 +        formatter_for(udt_class.tuple_type.__name__)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.make_udt_class = classmethod(new_make_udt_class)
 +
 +
 +class FrozenType(cassandra.cqltypes._ParameterizedType):
 +    """
 +    Needed until the bundled python driver adds FrozenType.
 +    """
 +    typename = "frozen"
 +    num_subtypes = 1
 +
 +    @classmethod
 +    def deserialize_safe(cls, byts, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.from_binary(byts)
 +
 +    @classmethod
 +    def serialize_safe(cls, val, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.to_binary(val, protocol_version)
 +
 +
 +class Shell(cmd.Cmd):
 +    custom_prompt = os.getenv('CQLSH_PROMPT', '')
 +    if custom_prompt is not '':
 +        custom_prompt += "\n"
 +    default_prompt = custom_prompt + "cqlsh> "
 +    continue_prompt = "   ... "
 +    keyspace_prompt = custom_prompt + "cqlsh:%s> "
 +    keyspace_continue_prompt = "%s    ... "
 +    show_line_nums = False
 +    debug = False
 +    stop = False
 +    last_hist = None
 +    shunted_query_out = None
 +    use_paging = True
 +
 +    default_page_size = 100
 +
 +    def __init__(self, hostname, port, color=False,
 +                 username=None, password=None, encoding=None, stdin=None, tty=True,
 +                 completekey=DEFAULT_COMPLETEKEY, browser=None, use_conn=None,
 +                 cqlver=DEFAULT_CQLVER, keyspace=None,
 +                 tracing_enabled=False, expand_enabled=False,
 +                 display_nanotime_format=DEFAULT_NANOTIME_FORMAT,
 +                 display_timestamp_format=DEFAULT_TIMESTAMP_FORMAT,
 +                 display_date_format=DEFAULT_DATE_FORMAT,
 +                 display_float_precision=DEFAULT_FLOAT_PRECISION,
 +                 display_timezone=None,
 +                 max_trace_wait=DEFAULT_MAX_TRACE_WAIT,
 +                 ssl=False,
 +                 single_statement=None,
 +                 request_timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS,
 +                 protocol_version=DEFAULT_PROTOCOL_VERSION,
 +                 connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS):
 +        cmd.Cmd.__init__(self, completekey=completekey)
 +        self.hostname = hostname
 +        self.port = port
 +        self.auth_provider = None
 +        if username:
 +            if not password:
 +                password = getpass.getpass()
 +            self.auth_provider = PlainTextAuthProvider(username=username, password=password)
 +        self.username = username
 +        self.keyspace = keyspace
 +        self.ssl = ssl
 +        self.tracing_enabled = tracing_enabled
 +        self.page_size = self.default_page_size
 +        self.expand_enabled = expand_enabled
 +        if use_conn:
 +            self.conn = use_conn
 +        else:
 +            self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
 +                                protocol_version=protocol_version,
 +                                auth_provider=self.auth_provider,
 +                                ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,
 +                                load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                                control_connection_timeout=connect_timeout,
 +                                connect_timeout=connect_timeout)
 +        self.owns_connection = not use_conn
 +        self.set_expanded_cql_version(cqlver)
 +
 +        if keyspace:
 +            self.session = self.conn.connect(keyspace)
 +        else:
 +            self.session = self.conn.connect()
 +
 +        if browser == "":
 +            browser = None
 +        self.browser = browser
 +        self.color = color
 +
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_date_format = display_date_format
 +
 +        self.display_float_precision = display_float_precision
 +
 +        self.display_timezone = display_timezone
 +
 +        self.session.default_timeout = request_timeout
 +        self.session.row_factory = ordered_dict_factory
 +        self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.get_connection_versions()
 +
 +        self.current_keyspace = keyspace
 +
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_date_format = display_date_format
 +
 +        self.max_trace_wait = max_trace_wait
 +        self.session.max_trace_wait = max_trace_wait
 +
 +        self.tty = tty
 +        self.encoding = encoding
 +        self.check_windows_encoding()
 +
 +        self.output_codec = codecs.lookup(encoding)
 +
 +        self.statement = StringIO()
 +        self.lineno = 1
 +        self.in_comment = False
 +
 +        self.prompt = ''
 +        if stdin is None:
 +            stdin = sys.stdin
 +
 +        if tty:
 +            self.reset_prompt()
 +            self.report_connection()
 +            print 'Use HELP for help.'
 +        else:
 +            self.show_line_nums = True
 +        self.stdin = stdin
 +        self.query_out = sys.stdout
 +        self.consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.SERIAL
 +
 +        self.empty_lines = 0
 +        self.statement_error = False
 +        self.single_statement = single_statement
 +
 +    @property
 +    def is_using_utf8(self):
 +        # utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html
 +        return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8', CP65001]
 +
 +    def check_windows_encoding(self):
 +        if is_win and os.name == 'nt' and self.tty and \
 +           self.is_using_utf8 and sys.stdout.encoding != CP65001:
 +            self.printerr("\nWARNING: console codepage must be set to cp65001 "
 +                          "to support {} encoding on Windows platforms.\n"
 +                          "If you experience encoding problems, change your console"
 +                          " codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding))
 +
 +    def set_expanded_cql_version(self, ver):
 +        ver, vertuple = full_cql_version(ver)
 +        self.cql_version = ver
 +        self.cql_ver_tuple = vertuple
 +
 +    def cqlver_atleast(self, major, minor=0, patch=0):
 +        return self.cql_ver_tuple[:3] >= (major, minor, patch)
 +
 +    def myformat_value(self, val, **kwargs):
 +        if isinstance(val, DecodeError):
 +            self.decoding_errors.append(val)
 +        try:
 +            dtformats = DateTimeFormat(timestamp_format=self.display_timestamp_format,
 +                                       date_format=self.display_date_format, nanotime_format=self.display_nanotime_format,
 +                                       timezone=self.display_timezone)
 +            return format_value(val, self.output_codec.name,
 +                                addcolor=self.color, date_time_format=dtformats,
 +                                float_precision=self.display_float_precision, **kwargs)
 +        except Exception, e:
 +            err = FormatError(val, e)
 +            self.decoding_errors.append(err)
 +            return format_value(err, self.output_codec.name, addcolor=self.color)
 +
 +    def myformat_colname(self, name, table_meta=None):
 +        column_colors = COLUMN_NAME_COLORS.copy()
 +        # check column role and color appropriately
 +        if table_meta:
 +            if name in [col.name for col in table_meta.partition_key]:
 +                column_colors.default_factory = lambda: RED
 +            elif name in [col.name for col in table_meta.clustering_key]:
 +                column_colors.default_factory = lambda: CYAN
 +        return self.myformat_value(name, colormap=column_colors)
 +
 +    def report_connection(self):
 +        self.show_host()
 +        self.show_version()
 +
 +    def show_host(self):
 +        print "Connected to %s at %s:%d." % \
 +            (self.applycolor(self.get_cluster_name(), BLUE),
 +              self.hostname,
 +              self.port)
 +
 +    def show_version(self):
 +        vers = self.connection_versions.copy()
 +        vers['shver'] = version
 +        # 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 | Native protocol v%(protocol)s]" % vers
 +
 +    def show_session(self, sessionid, partial_session=False):
 +        print_trace_session(self, self.session, sessionid, partial_session)
 +
 +    def get_connection_versions(self):
 +        result, = self.session.execute("select * from system.local where key = 'local'")
 +        vers = {
 +            'build': result['release_version'],
 +            'protocol': result['native_protocol_version'],
 +            'cql': result['cql_version'],
 +        }
 +        self.connection_versions = vers
 +
 +    def get_keyspace_names(self):
 +        return map(str, self.conn.metadata.keyspaces.keys())
 +
 +    def get_columnfamily_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).tables.keys())
 +
 +    def get_index_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).indexes.keys())
 +
 +    def get_column_names(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        layout = self.get_table_meta(ksname, cfname)
 +        return [unicode(col) for col in layout.columns]
 +
 +    def get_usertype_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return self.get_keyspace_meta(ksname).user_types.keys()
 +
 +    def get_usertype_layout(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        ks_meta = self.get_keyspace_meta(ksname)
 +
 +        try:
 +            user_type = ks_meta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +
 +        return [(field_name, field_type.cql_parameterized_type())
 +                for field_name, field_type in zip(user_type.field_names, user_type.field_types)]
 +
 +    def get_userfunction_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).functions.values())
 +
 +    def get_useraggregate_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).aggregates.values())
 +
 +    def get_cluster_name(self):
 +        return self.conn.metadata.cluster_name
 +
 +    def get_partitioner(self):
 +        return self.conn.metadata.partitioner
 +
 +    def get_keyspace_meta(self, ksname):
 +        if ksname not in self.conn.metadata.keyspaces:
 +            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
 +        return self.conn.metadata.keyspaces[ksname]
 +
 +    def get_keyspaces(self):
 +        return self.conn.metadata.keyspaces.values()
 +
 +    def get_ring(self, ks):
 +        self.conn.metadata.token_map.rebuild_keyspace(ks, build_if_absent=True)
 +        return self.conn.metadata.token_map.tokens_to_hosts_by_ks[ks]
 +
 +    def get_table_meta(self, ksname, tablename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if tablename not in ksmeta.tables:
 +            if ksname == 'system_auth' and tablename in ['roles', 'role_permissions']:
 +                self.get_fake_auth_table_meta(ksname, tablename)
 +            else:
 +                raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +        else:
 +            return ksmeta.tables[tablename]
 +
 +    def get_fake_auth_table_meta(self, ksname, tablename):
 +        # may be using external auth implementation so internal tables
 +        # aren't actually defined in schema. In this case, we'll fake
 +        # them up
 +        if tablename == 'roles':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'roles')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['is_superuser'] = ColumnMetadata(table_meta, 'is_superuser', cassandra.cqltypes.BooleanType)
 +            table_meta.columns['can_login'] = ColumnMetadata(table_meta, 'can_login', cassandra.cqltypes.BooleanType)
 +        elif tablename == 'role_permissions':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'role_permissions')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['resource'] = ColumnMetadata(table_meta, 'resource', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['permission'] = ColumnMetadata(table_meta, 'permission', cassandra.cqltypes.UTF8Type)
 +        else:
 +            raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +
 +    def get_index_meta(self, ksname, idxname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if idxname not in ksmeta.indexes:
 +            raise IndexNotFound("Index %r not found" % idxname)
 +
 +        return ksmeta.indexes[idxname]
 +
 +    def get_object_meta(self, ks, name):
 +        if name is None:
 +            if ks and ks in self.conn.metadata.keyspaces:
 +                return self.conn.metadata.keyspaces[ks]
 +            elif self.current_keyspace is None:
 +                raise ObjectNotFound("%r not found in keyspaces" % (ks))
 +            else:
 +                name = ks
 +                ks = self.current_keyspace
 +
 +        if ks is None:
 +            ks = self.current_keyspace
 +
 +        ksmeta = self.get_keyspace_meta(ks)
 +
 +        if name in ksmeta.tables:
 +            return ksmeta.tables[name]
 +        elif name in ksmeta.indexes:
 +            return ksmeta.indexes[name]
 +
 +        raise ObjectNotFound("%r not found in keyspace %r" % (name, ks))
 +
 +    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)
 +
 +    def get_trigger_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return [trigger.name
 +                for table in self.get_keyspace_meta(ksname).tables.values()
 +                for trigger in table.triggers.values()]
 +
 +    def reset_statement(self):
 +        self.reset_prompt()
 +        self.statement.truncate(0)
 +        self.empty_lines = 0
 +
 +    def reset_prompt(self):
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.default_prompt, True)
 +        else:
 +            self.set_prompt(self.keyspace_prompt % self.current_keyspace, True)
 +
 +    def set_continue_prompt(self):
 +        if self.empty_lines >= 3:
 +            self.set_prompt("Statements are terminated with a ';'.  You can press CTRL-C to cancel an incomplete statement.")
 +            self.empty_lines = 0
 +            return
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.continue_prompt)
 +        else:
 +            spaces = ' ' * len(str(self.current_keyspace))
 +            self.set_prompt(self.keyspace_continue_prompt % spaces)
 +        self.empty_lines = self.empty_lines + 1 if not self.lastcmd else 0
 +
 +    @contextmanager
 +    def prepare_loop(self):
 +        readline = None
 +        if self.tty and self.completekey:
 +            try:
 +                import readline
 +            except ImportError:
 +                if is_win:
 +                    print "WARNING: pyreadline dependency missing.  Install to enable tab completion."
 +                pass
 +            else:
 +                old_completer = readline.get_completer()
 +                readline.set_completer(self.complete)
 +                if readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +                    readline.parse_and_bind("bind -e")
 +                    readline.parse_and_bind("bind '" + self.completekey + "' rl_complete")
 +                    readline.parse_and_bind("bind ^R em-inc-search-prev")
 +                else:
 +                    readline.parse_and_bind(self.completekey + ": complete")
 +        try:
 +            yield
 +        finally:
 +            if readline is not None:
 +                readline.set_completer(old_completer)
 +
 +    def get_input_line(self, prompt=''):
 +        if self.tty:
 +            try:
 +                self.lastcmd = raw_input(prompt).decode(self.encoding)
 +            except UnicodeDecodeError:
 +                self.lastcmd = ''
 +                traceback.print_exc()
 +                self.check_windows_encoding()
 +            line = self.lastcmd + '\n'
 +        else:
 +            self.lastcmd = self.stdin.readline()
 +            line = self.lastcmd
 +            if not len(line):
 +                raise EOFError
 +        self.lineno += 1
 +        return line
 +
 +    def use_stdin_reader(self, until='', prompt=''):
 +        until += '\n'
 +        while True:
 +            try:
 +                newline = self.get_input_line(prompt=prompt)
 +            except EOFError:
 +                return
 +            if newline == until:
 +                return
 +            yield newline
 +
 +    def cmdloop(self):
 +        """
 +        Adapted from cmd.Cmd's version, because there is literally no way with
 +        cmd.Cmd.cmdloop() to tell the difference between "EOF" showing up in
 +        input and an actual EOF.
 +        """
 +        with self.prepare_loop():
 +            while not self.stop:
 +                try:
 +                    if self.single_statement:
 +                        line = self.single_statement
 +                        self.stop = True
 +                    else:
 +                        line = self.get_input_line(self.prompt)
 +                    self.statement.write(line)
 +                    if self.onecmd(self.statement.getvalue()):
 +                        self.reset_statement()
 +                except EOFError:
 +                    self.handle_eof()
 +                except CQL_ERRORS, cqlerr:
 +                    self.printerr(cqlerr.message.decode(encoding='utf-8'))
 +                except KeyboardInterrupt:
 +                    self.reset_statement()
 +                    print
 +
 +    def onecmd(self, statementtext):
 +        """
 +        Returns true if the statement is complete and was handled (meaning it
 +        can be reset).
 +        """
 +
 +        try:
 +            statements, endtoken_escaped = cqlruleset.cql_split_statements(statementtext)
 +        except pylexotron.LexingError, e:
 +            if self.show_line_nums:
 +                self.printerr('Invalid syntax at char %d' % (e.charnum,))
 +            else:
 +                self.printerr('Invalid syntax at line %d, char %d'
 +                              % (e.linenum, e.charnum))
 +            statementline = statementtext.split('\n')[e.linenum - 1]
 +            self.printerr('  %s' % statementline)
 +            self.printerr(' %s^' % (' ' * e.charnum))
 +            return True
 +
 +        while statements and not statements[-1]:
 +            statements = statements[:-1]
 +        if not statements:
 +            return True
 +        if endtoken_escaped or statements[-1][-1][0] != 'endtoken':
 +            self.set_continue_prompt()
 +            return
 +        for st in statements:
 +            try:
 +                self.handle_statement(st, statementtext)
 +            except Exception, e:
 +                if self.debug:
 +                    traceback.print_exc()
 +                else:
 +                    self.printerr(e)
 +        return True
 +
 +    def handle_eof(self):
 +        if self.tty:
 +            print
 +        statement = self.statement.getvalue()
 +        if statement.strip():
 +            if not self.onecmd(statement):
 +                self.printerr('Incomplete statement at end of file')
 +        self.do_exit()
 +
 +    def handle_statement(self, tokens, srcstr):
 +        # Concat multi-line statements and insert into history
 +        if readline is not None:
 +            nl_count = srcstr.count("\n")
 +
 +            new_hist = srcstr.replace("\n", " ").rstrip()
 +
 +            if nl_count > 1 and self.last_hist != new_hist:
 +                readline.add_history(new_hist.encode(self.encoding))
 +
 +            self.last_hist = new_hist
 +        cmdword = tokens[0][1]
 +        if cmdword == '?':
 +            cmdword = 'help'
 +        custom_handler = getattr(self, 'do_' + cmdword.lower(), None)
 +        if custom_handler:
 +            parsed = cqlruleset.cql_whole_parse_tokens(tokens, srcstr=srcstr,
 +                                                       startsymbol='cqlshCommand')
 +            if parsed and not parsed.remainder:
 +                # successful complete parse
 +                return custom_handler(parsed)
 +            else:
 +                return self.handle_parse_error(cmdword, tokens, parsed, srcstr)
 +        return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +
 +    def handle_parse_error(self, cmdword, tokens, parsed, srcstr):
 +        if cmdword.lower() in ('select', 'insert', 'update', 'delete', 'truncate',
 +                               'create', 'drop', 'alter', 'grant', 'revoke',
 +                               'batch', 'list'):
 +            # hey, maybe they know about some new syntax we don't. type
 +            # assumptions won't work, but maybe the query will.
 +            return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +        if parsed:
 +            self.printerr('Improper %s command (problem at %r).' % (cmdword, parsed.remainder[0]))
 +        else:
 +            self.printerr('Improper %s command.' % cmdword)
 +
 +    def do_use(self, parsed):
 +        ksname = parsed.get_binding('ksname')
 +        success, _ = self.perform_simple_statement(SimpleStatement(parsed.extract_orig()))
 +        if success:
 +            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):
 +        tracing_was_enabled = self.tracing_enabled
 +        ksname = parsed.get_binding('ksname')
 +        stop_tracing = ksname == 'system_traces' or (ksname is None and self.current_keyspace == 'system_traces')
 +        self.tracing_enabled = self.tracing_enabled and not stop_tracing
 +        statement = parsed.extract_orig()
 +        self.perform_statement(statement)
 +        self.tracing_enabled = tracing_was_enabled
 +
 +    def perform_statement(self, statement):
 +        stmt = SimpleStatement(statement, consistency_level=self.consistency_level, serial_consistency_level=self.serial_consistency_level, fetch_size=self.page_size if self.use_paging else None)
 +        success, future = self.perform_simple_statement(stmt)
 +
 +        if future:
 +            if future.warnings:
 +                self.print_warnings(future.warnings)
 +
 +            if self.tracing_enabled:
 +                try:
 +                    for trace in future.get_all_query_traces(max_wait_per=self.max_trace_wait, query_cl=self.consistency_level):
 +                        print_trace(self, trace)
 +                except TraceUnavailable:
 +                    msg = "Statement trace did not complete within %d seconds; trace data may be incomplete." % (self.session.max_trace_wait,)
 +                    self.writeresult(msg, color=RED)
 +                    for trace_id in future.get_query_trace_ids():
 +                        self.show_session(trace_id, partial_session=True)
 +                except Exception, err:
 +                    self.printerr("Unable to fetch query trace: %s" % (str(err),))
 +
 +        return success
 +
 +    def parse_for_table_meta(self, query_string):
 +        try:
 +            parsed = cqlruleset.cql_parse(query_string)[1]
 +        except IndexError:
 +            return None
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        return self.get_table_meta(ks, cf)
 +
 +    def perform_simple_statement(self, statement):
 +        if not statement:
 +            return False, None
 +
 +        future = self.session.execute_async(statement, trace=self.tracing_enabled)
 +        result = None
 +        try:
 +            result = future.result()
 +        except CQL_ERRORS, err:
 +            self.printerr(unicode(err.__class__.__name__) + u": " + err.message.decode(encoding='utf-8'))
 +        except Exception:
 +            import traceback
 +            self.printerr(traceback.format_exc())
 +
 +        # Even if statement failed we try to refresh schema if not agreed (see CASSANDRA-9689)
 +        if not future.is_schema_agreed:
 +            try:
 +                self.conn.refresh_schema_metadata(5)  # will throw exception if there is a schema mismatch
 +            except Exception:
 +                self.printerr("Warning: schema version mismatch detected; check the schema versions of your "
 +                              "nodes in system.local and system.peers.")
 +                self.conn.refresh_schema_metadata(-1)
 +
 +        if result is None:
 +            return False, None
 +
 +        if statement.query_string[:6].lower() == 'select':
 +            self.print_result(result, self.parse_for_table_meta(statement.query_string))
 +        elif statement.query_string.lower().startswith("list users") or statement.query_string.lower().startswith("list roles"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'roles'))
 +        elif statement.query_string.lower().startswith("list"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'role_permissions'))
 +        elif result:
 +            # CAS INSERT/UPDATE
 +            self.writeresult("")
 +            self.print_static_result(result.column_names, list(result), self.parse_for_table_meta(statement.query_string))
 +        self.flush_output()
 +        return True, future
 +
 +    def print_result(self, result, table_meta):
 +        self.decoding_errors = []
 +
 +        self.writeresult("")
 +        if result.has_more_pages and self.tty:
 +            num_rows = 0
 +            while True:
 +                page = result.current_rows
 +                if page:
 +                    num_rows += len(page)
 +                    self.print_static_result(result.column_names, page, table_meta)
 +                if result.has_more_pages:
 +                    raw_input("---MORE---")
 +                    result.fetch_next_page()
 +                else:
 +                    break
 +        else:
 +            rows = list(result)
 +            num_rows = len(rows)
 +            self.print_static_result(result.column_names, rows, table_meta)
 +        self.writeresult("(%d rows)" % num_rows)
 +
 +        if self.decoding_errors:
 +            for err in self.decoding_errors[:2]:
 +                self.writeresult(err.message(), color=RED)
 +            if len(self.decoding_errors) > 2:
 +                self.writeresult('%d more decoding errors suppressed.'
 +                                 % (len(self.decoding_errors) - 2), color=RED)
 +
 +    def print_static_result(self, column_names, rows, table_meta):
 +        if not column_names and not table_meta:
 +            return
 +
 +        column_names = column_names or table_meta.columns.keys()
 +        formatted_names = [self.myformat_colname(name, table_meta) for name in column_names]
 +        if not rows:
 +            # print header only
 +            self.print_formatted_result(formatted_names, None)
 +            return
 +        formatted_values = [map(self.myformat_value, row.values()) for row in rows]
 +
 +        if self.expand_enabled:
 +            self.print_formatted_result_vertically(formatted_names, formatted_values)
 +        else:
 +            self.print_formatted_result(formatted_names, formatted_values)
 +
 +    def print_formatted_result(self, formatted_names, formatted_values):
 +        # determine column widths
 +        widths = [n.displaywidth for n in formatted_names]
 +        if formatted_values is not None:
 +            for fmtrow in formatted_values:
 +                for num, col in enumerate(fmtrow):
 +                    widths[num] = max(widths[num], col.displaywidth)
 +
 +        # print header
 +        header = ' | '.join(hdr.ljust(w, color=self.color) for (hdr, w) in zip(formatted_names, widths))
 +        self.writeresult(' ' + header.rstrip())
 +        self.writeresult('-%s-' % '-+-'.join('-' * w for w in widths))
 +
 +        # stop if there are no rows
 +        if formatted_values is None:
 +            self.writeresult("")
 +            return
 +
 +        # print row data
 +        for row in formatted_values:
 +            line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
 +            self.writeresult(' ' + line)
 +
 +        self.writeresult("")
 +
 +    def print_formatted_result_vertically(self, formatted_names, formatted_values):
 +        max_col_width = max([n.displaywidth for n in formatted_names])
 +        max_val_width = max([n.displaywidth for row in formatted_values for n in row])
 +
 +        # for each row returned, list all the column-value pairs
 +        for row_id, row in enumerate(formatted_values):
 +            self.writeresult("@ Row %d" % (row_id + 1))
 +            self.writeresult('-%s-' % '-+-'.join(['-' * max_col_width, '-' * max_val_width]))
 +            for field_id, field in enumerate(row):
 +                column = formatted_names[field_id].ljust(max_col_width, color=self.color)
 +                value = field.ljust(field.displaywidth, color=self.color)
 +                self.writeresult(' ' + " | ".join([column, value]))
 +            self.writeresult('')
 +
 +    def print_warnings(self, warnings):
 +        if warnings is None or len(warnings) == 0:
 +            return
 +
 +        self.writeresult('')
 +        self.writeresult('Warnings :')
 +        for warning in warnings:
 +            self.writeresult(warning)
 +            self.writeresult('')
 +
 +    def emptyline(self):
 +        pass
 +
 +    def parseline(self, line):
 +        # this shouldn't be needed
 +        raise NotImplementedError
 +
 +    def complete(self, text, state):
 +        if readline is None:
 +            return
 +        if state == 0:
 +            try:
 +                self.completion_matches = self.find_completions(text)
 +            except Exception:
 +                if debug_completion:
 +                    import traceback
 +                    traceback.print_exc()
 +                else:
 +                    raise
 +        try:
 +            return self.completion_matches[state]
 +        except IndexError:
 +            return None
 +
 +    def find_completions(self, text):
 +        curline = readline.get_line_buffer()
 +        prevlines = self.statement.getvalue()
 +        wholestmt = prevlines + curline
 +        begidx = readline.get_begidx() + len(prevlines)
 +        stuff_to_complete = wholestmt[:begidx]
 +        return cqlruleset.cql_complete(stuff_to_complete, text, cassandra_conn=self,
 +                                       debug=debug_completion, startsymbol='cqlshCommand')
 +
 +    def set_prompt(self, prompt, prepend_user=False):
 +        if prepend_user and self.username:
 +            self.prompt = "%s@%s" % (self.username, prompt)
 +            return
 +        self.prompt = prompt
 +
 +    def cql_unprotect_name(self, namestr):
 +        if namestr is None:
 +            return
 +        return cqlruleset.dequote_name(namestr)
 +
 +    def cql_unprotect_value(self, valstr):
 +        if valstr is not None:
 +            return cqlruleset.dequote_value(valstr)
 +
 +    def print_recreate_keyspace(self, ksdef, out):
 +        out.write(ksdef.export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_columnfamily(self, ksname, cfname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given table.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_table_meta(ksname, cfname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_index(self, ksname, idxname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given index.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_index_meta(ksname, idxname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_object(self, ks, name, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given object (ks, table or index).
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_object_meta(ks, name).export_as_string())
 +        out.write("\n")
 +
 +    def describe_keyspaces(self):
 +        print
 +        cmd.Cmd.columnize(self, protect_names(self.get_keyspace_names()))
 +        print
 +
 +    def describe_keyspace(self, ksname):
 +        print
 +        self.print_recreate_keyspace(self.get_keyspace_meta(ksname), sys.stdout)
 +        print
 +
 +    def describe_columnfamily(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        self.print_recreate_columnfamily(ksname, cfname, sys.stdout)
 +        print
 +
 +    def describe_index(self, ksname, idxname):
 +        print
 +        self.print_recreate_index(ksname, idxname, sys.stdout)
 +        print
 +
 +    def describe_object(self, ks, name):
 +        print
 +        self.print_recreate_object(ks, name, sys.stdout)
 +        print
 +
 +    def describe_columnfamilies(self, ksname):
 +        print
 +        if ksname is None:
 +            for k in self.get_keyspaces():
 +                name = protect_name(k.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(k.name)))
 +                print
 +        else:
 +            cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(ksname)))
 +            print
 +
 +    def describe_functions(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.functions.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.functions.keys())
 +
 +    def describe_function(self, ksname, functionname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        functions = filter(lambda f: f.name == functionname, ksmeta.functions.values())
 +        if len(functions) == 0:
 +            raise FunctionNotFound("User defined function %r not found" % functionname)
 +        print "\n\n".join(func.as_cql_query(formatted=True) for func in functions)
 +        print
 +
 +    def describe_aggregates(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.aggregates.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.aggregates.keys())
 +
 +    def describe_aggregate(self, ksname, aggregatename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        aggregates = filter(lambda f: f.name == aggregatename, ksmeta.aggregates.values())
 +        if len(aggregates) == 0:
 +            raise FunctionNotFound("User defined aggregate %r not found" % aggregatename)
 +        print "\n\n".join(aggr.as_cql_query(formatted=True) for aggr in aggregates)
 +        print
 +
 +    def describe_usertypes(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +
 +    def describe_usertype(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        try:
 +            usertype = ksmeta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +        print usertype.as_cql_query(formatted=True)
 +        print
 +
 +    def _columnize_unicode(self, name_list, quote=False):
 +        """
 +        Used when columnizing identifiers that may contain unicode
 +        """
 +        names = [n.encode('utf-8') for n in name_list]
 +        if quote:
 +            names = protect_names(names)
 +        cmd.Cmd.columnize(self, names)
 +        print
 +
 +    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\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(self.current_keyspace)
 +            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):
 +        print
 +        for k in self.get_keyspaces():
 +            if include_system or k.name not in cql3handling.SYSTEM_KEYSPACES:
 +                self.print_recreate_keyspace(k, sys.stdout)
 +                print
 +
 +    def do_describe(self, parsed):
 +        """
 +        DESCRIBE [cqlsh only]
 +
 +        (DESC may be used as a shorthand.)
 +
 +          Outputs information about the connected Cassandra cluster, or about
 +          the data objects stored in the cluster. Use in one of the following ways:
 +
 +        DESCRIBE KEYSPACES
 +
 +          Output the names of all keyspaces.
 +
 +        DESCRIBE KEYSPACE [<keyspacename>]
 +
 +          Output CQL commands that could be used to recreate the given keyspace,
 +          and the objects in it (such as tables, types, functions, etc.).
 +          In some cases, as the CQL interface matures, there will be some metadata
 +          about a keyspace that is not representable with CQL. That metadata will not be shown.
 +
 +          The '<keyspacename>' argument may be omitted, in which case the current
 +          keyspace will be described.
 +
 +        DESCRIBE TABLES
 +
 +          Output the names of all tables in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TABLE [<keyspace>.]<tablename>
 +
 +          Output CQL commands that could be used to recreate the given table.
 +          In some cases, as above, there may be table metadata which is not
 +          representable and which will not be shown.
 +
 +        DESCRIBE INDEX <indexname>
 +
 +          Output the CQL command that could be used to recreate the given index.
 +          In some cases, there may be index metadata which is not representable
 +          and which will not be shown.
 +
 +        DESCRIBE CLUSTER
 +
 +          Output information about the connected Cassandra cluster, such as the
 +          cluster name, and the partitioner and snitch in use. When you are
 +          connected to a non-system keyspace, also shows endpoint-range
 +          ownership information for the Cassandra ring.
 +
 +        DESCRIBE [FULL] SCHEMA
 +
 +          Output CQL commands that could be used to recreate the entire (non-system) schema.
 +          Works as though "DESCRIBE KEYSPACE k" was invoked for each non-system keyspace
 +          k. Use DESCRIBE FULL SCHEMA to include the system keyspaces.
 +
 +        DESCRIBE TYPES
 +
 +          Output the names of all user-defined-types in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TYPE [<keyspace>.]<type>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-type.
 +
 +        DESCRIBE FUNCTIONS
 +
 +          Output the names of all user-defined-functions in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE FUNCTION [<keyspace>.]<function>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-function.
 +
 +        DESCRIBE AGGREGATES
 +
 +          Output the names of all user-defined-aggregates in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE AGGREGATE [<keyspace>.]<aggregate>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-aggregate.
 +
 +        DESCRIBE <objname>
 +
 +          Output CQL commands that could be used to recreate the entire object schema,
 +          where object can be either a keyspace or a table or an index (in this order).
 +  """
 +        what = parsed.matched[1][1].lower()
 +        if what == 'functions':
 +            self.describe_functions(self.current_keyspace)
 +        elif what == 'function':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            functionname = self.cql_unprotect_name(parsed.get_binding('udfname'))
 +            self.describe_function(ksname, functionname)
 +        elif what == 'aggregates':
 +            self.describe_aggregates(self.current_keyspace)
 +        elif what == 'aggregate':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            aggregatename = self.cql_unprotect_name(parsed.get_binding('udaname'))
 +            self.describe_aggregate(ksname, aggregatename)
 +        elif what == 'keyspaces':
 +            self.describe_keyspaces()
 +        elif what == 'keyspace':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', ''))
 +            if not ksname:
 +                ksname = self.current_keyspace
 +                if ksname is None:
 +                    self.printerr('Not in any keyspace.')
 +                    return
 +            self.describe_keyspace(ksname)
 +        elif what in ('columnfamily', 'table'):
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            self.describe_columnfamily(ks, cf)
 +        elif what == 'index':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            idx = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_index(ks, idx)
 +        elif what in ('columnfamilies', 'tables'):
 +            self.describe_columnfamilies(self.current_keyspace)
 +        elif what == 'types':
 +            self.describe_usertypes(self.current_keyspace)
 +        elif what == 'type':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            ut = self.cql_unprotect_name(parsed.get_binding('utname'))
 +            self.describe_usertype(ks, ut)
 +        elif what == 'cluster':
 +            self.describe_cluster()
 +        elif what == 'schema':
 +            self.describe_schema(False)
 +        elif what == 'full' and parsed.matched[2][1].lower() == 'schema':
 +            self.describe_schema(True)
 +        elif what:
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            name = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            if not name:
 +                name = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_object(ks, name)
 +    do_desc = do_describe
 +
 +    def do_copy(self, parsed):
 +        r"""
 +        COPY [cqlsh only]
 +
 +          COPY x FROM: Imports CSV data into a Cassandra table
 +          COPY x TO: Exports data from a Cassandra table in CSV format.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             FROM ( '<file_pattern_1, file_pattern_2, ... file_pattern_n>' | STDIN )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        File patterns are either file names or valid python glob expressions, e.g. *.csv or folder/*.csv.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             TO ( '<filename>' | STDOUT )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        Available common COPY options and defaults:
 +
 +          DELIMITER=','           - character that appears between records
 +          QUOTE='"'               - quoting character to be used to quote fields
 +          ESCAPE='\'              - character to appear before the QUOTE char when quoted
 +          HEADER=false            - whether to ignore the first line
 +          NULL=''                 - string that represents a null value
 +          DATETIMEFORMAT=         - timestamp strftime format
 +            '%Y-%m-%d %H:%M:%S%z'   defaults to time_format value in cqlshrc
 +          MAXATTEMPTS=5           - the maximum number of attempts per batch or range
 +          REPORTFREQUENCY=0.25    - the frequency with which we display status updates in seconds
 +          DECIMALSEP='.'          - the separator for decimal values
 +          THOUSANDSSEP=''         - the separator for thousands digit groups
 +          BOOLSTYLE='True,False'  - the representation for booleans, case insensitive, specify true followed by false,
 +                                    for example yes,no or 1,0
 +          NUMPROCESSES=n          - the number of worker processes, by default the number of cores minus one
 +                                    capped at 16
 +          CONFIGFILE=''           - a configuration file with the same format as .cqlshrc (see the Python ConfigParser
 +                                    documentation) where you can specify WITH options under the following optional
 +                                    sections: [copy], [copy-to], [copy-from], [copy:ks.table], [copy-to:ks.table],
 +                                    [copy-from:ks.table], where <ks> is your keyspace name and <table> is your table
 +                                    name. Options are read from these sections, in the order specified
 +                                    above, and command line options always override options in configuration files.
 +                                    Depending on the COPY direction, only the relevant copy-from or copy-to sections
 +                                    are used. If no configfile is specified then .cqlshrc is searched instead.
 +          RATEFILE=''             - an optional file where to print the output statistics
 +
 +        Available COPY FROM options and defaults:
 +
 +          CHUNKSIZE=5000          - the size of chunks passed to worker processes
 +          INGESTRATE=100000       - an approximate ingest rate in rows per second
 +          MINBATCHSIZE=10         - the minimum size of an import batch
 +          MAXBATCHSIZE=20         - the maximum size of an import batch
 +          MAXROWS=-1              - the maximum number of rows, -1 means no maximum
 +          SKIPROWS=0              - the number of rows to skip
 +          SKIPCOLS=''             - a comma separated list of column names to skip
 +          MAXPARSEERRORS=-1       - the maximum global number of parsing errors, -1 means no maximum
 +          MAXINSERTERRORS=-1      - the maximum global number of insert errors, -1 means no maximum
 +          ERRFILE=''              - a file where to store all rows that could not be imported, by default this is
 +                                    import_ks_table.err where <ks> is your keyspace and <table> is your table name.
 +          PREPAREDSTATEMENTS=True - whether to use prepared statements when importing, by default True. Set this to
 +                                    False if you don't mind shifting data parsing to the cluster. The cluster will also
 +                                    have to compile every batch statement. For large and oversized clusters
 +                                    this will result in a faster import but for smaller clusters it may generate
 +                                    timeouts.
 +
 +        Available COPY TO options and defaults:
 +
 +          ENCODING='utf8'          - encoding for CSV output
 +          PAGESIZE='1000'          - the page size for fetching results
 +          PAGETIMEOUT=10           - the page timeout in seconds for fetching results
 +          BEGINTOKEN=''            - the minimum token string to consider when exporting data
 +          ENDTOKEN=''              - the maximum token string to consider when exporting data
 +          MAXREQUESTS=6            - the maximum number of requests each worker process can work on in parallel
 +          MAXOUTPUTSIZE='-1'       - the maximum size of the output file measured in number of lines,
 +                                     beyond this maximum the output file will be split into segments,
 +                                     -1 means unlimited.
 +
 +        When entering CSV data on STDIN, you can use the sequence "\."
 +        on a line by itself to end the data input.
 +        """
 +
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        if ks is None:
 +            ks = self.current_keyspace
 +            if ks is None:
 +                raise NoKeyspaceError("Not in any keyspace.")
 +        table = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        columns = parsed.get_binding('colnames', None)
 +        if columns is not None:
 +            columns = map(self.cql_unprotect_name, columns)
 +        else:
 +            # default to all known columns
 +            columns = self.get_column_names(ks, table)
 +
 +        fname = parsed.get_binding('fname', None)
 +        if fname is not None:
 +            fname = self.cql_unprotect_value(fname)
 +
 +        copyoptnames = map(str.lower, parsed.get_binding('optnames', ()))
 +        copyoptvals = map(self.cql_unprotect_value, parsed.get_binding('optvals', ()))
 +        opts = dict(zip(copyoptnames, copyoptvals))
 +
 +        direction = parsed.get_binding('dir').upper()
 +        if direction == 'FROM':
 +            task = ImportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        elif direction == 'TO':
 +            task = ExportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        else:
 +            raise SyntaxError("Unknown direction %s" % direction)
 +
 +        task.run()
 +
 +    def do_show(self, parsed):
 +        """
 +        SHOW [cqlsh only]
 +
 +          Displays information about the current cqlsh session. Can be called in
 +          the following ways:
 +
 +        SHOW VERSION
 +
 +          Shows the version and build of the connected Cassandra instance, as
 +          well as the versions of the CQL spec and the Thrift protocol that
 +          the connected Cassandra instance understands.
 +
 +        SHOW HOST
 +
 +          Shows where cqlsh is currently connected.
 +
 +        SHOW SESSION <sessionid>
 +
 +          Pretty-prints the requested tracing session.
 +        """
 +        showwhat = parsed.get_binding('what').lower()
 +        if showwhat == 'version':
 +            self.get_connection_versions()
 +            self.show_version()
 +        elif showwhat == 'host':
 +            self.show_host()
 +        elif showwhat.startswith('session'):
 +            session_id = parsed.get_binding('sessionid').lower()
 +            self.show_session(UUID(session_id))
 +        else:
 +            self.printerr('Wait, how do I show %r?' % (showwhat,))
 +
 +    def do_source(self, parsed):
 +        """
 +        SOURCE [cqlsh only]
 +
 +        Executes a file containing CQL statements. Gives the output for each
 +        statement in turn, if any, or any errors that occur along the way.
 +
 +        Errors do NOT abort execution of the CQL source file.
 +
 +        Usage:
 +
 +          SOURCE '<file>';
 +
 +        That is, the path to the file to be executed must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        See also the --file option to cqlsh.
 +        """
 +        fname = parsed.get_binding('fname')
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            encoding, bom_size = get_file_encoding_bomsize(fname)
 +            f = codecs.open(fname, 'r', encoding)
 +            f.seek(bom_size)
 +        except IOError, e:
 +            self.printerr('Could not open %r: %s' % (fname, e))
 +            return
 +        username = self.auth_provider.username if self.auth_provider else None
 +        password = self.auth_provider.password if self.auth_provider else None
 +        subshell = Shell(self.hostname, self.port, color=self.color,
 +                         username=username, password=password,
 +                         encoding=self.encoding, stdin=f, tty=False, use_conn=self.conn,
 +                         cqlver=self.cql_version, keyspace=self.current_keyspace,
 +                         tracing_enabled=self.tracing_enabled,
 +                         display_nanotime_format=self.display_nanotime_format,
 +                         display_timestamp_format=self.display_timestamp_format,
 +                         display_date_format=self.display_date_format,
 +                         display_float_precision=self.display_float_precision,
 +                         display_timezone=self.display_timezone,
 +                         max_trace_wait=self.max_trace_wait, ssl=self.ssl,
 +                         request_timeout=self.session.default_timeout,
 +                         connect_timeout=self.conn.connect_timeout)
 +        subshell.cmdloop()
 +        f.close()
 +
 +    def do_capture(self, parsed):
 +        """
 +        CAPTURE [cqlsh only]
 +
 +        Begins capturing command output and appending it to a specified file.
 +        Output will not be shown at the console while it is captured.
 +
 +        Usage:
 +
 +          CAPTURE '<file>';
 +          CAPTURE OFF;
 +          CAPTURE;
 +
 +        That is, the path to the file to be appended to must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        Only query result output is captured. Errors and output from cqlsh-only
 +        commands will still be shown in the cqlsh session.
 +
 +        To stop capturing output and show it in the cqlsh session again, use
 +        CAPTURE OFF.
 +
 +        To inspect the current capture configuration, use CAPTURE with no
 +        arguments.
 +        """
 +        fname = parsed.get_binding('fname')
 +        if fname is None:
 +            if self.shunted_query_out is not None:
 +                print "Currently capturing query output to %r." % (self.query_out.name,)
 +            else:
 +                print "Currently not capturing query output."
 +            return
 +
 +        if fname.upper() == 'OFF':
 +            if self.shunted_query_out is None:
 +                self.printerr('Not currently capturing output.')
 +                return
 +            self.query_out.close()
 +            self.query_out = self.shunted_query_out
 +            self.color = self.shunted_color
 +            self.shunted_query_out = None
 +            del self.shunted_color
 +            return
 +
 +        if self.shunted_query_out is not None:
 +            self.printerr('Already capturing output to %s. Use CAPTURE OFF'
 +                          ' to disable.' % (self.query_out.name,))
 +            return
 +
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            f = open(fname, 'a')
 +        except IOError, e:
 +            self.printerr('Could not open %r for append: %s' % (fname, e))
 +            return
 +        self.shunted_query_out = self.query_out
 +        self.shunted_color = self.color
 +        self.query_out = f
 +        self.color = False
 +        print 'Now capturing query output to %r.' % (fname,)
 +
 +    def do_tracing(self, parsed):
 +        """
 +        TRACING [cqlsh]
 +
 +          Enables or disables request tracing.
 +
 +        TRACING ON
 +
 +          Enables tracing for all further requests.
 +
 +        TRACING OFF
 +
 +          Disables tracing.
 +
 +        TRACING
 +
 +          TRACING with no arguments shows the current tracing status.
 +        """
 +        self.tracing_enabled = SwitchCommand("TRACING", "Tracing").execute(self.tracing_enabled, parsed, self.printerr)
 +
 +    def do_expand(self, parsed):
 +        """
 +        EXPAND [cqlsh]
 +
 +          Enables or disables expanded (vertical) output.
 +
 +        EXPAND ON
 +
 +          Enables expanded (vertical) output.
 +
 +        EXPAND OFF
 +
 +          Disables expanded (vertical) output.
 +
 +        EXPAND
 +
 +          EXPAND with no arguments shows the current value of expand setting.
 +        """
 +        self.expand_enabled = SwitchCommand("EXPAND", "Expanded output").execute(self.expand_enabled, parsed, self.printerr)
 +
 +    def do_consistency(self, parsed):
 +        """
 +        CONSISTENCY [cqlsh only]
 +
 +           Overrides default consistency level (default level is ONE).
 +
 +        CONSISTENCY <level>
 +
 +           Sets consistency level for future requests.
 +
 +           Valid consistency levels:
 +
 +           ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM, SERIAL and LOCAL_SERIAL.
 +
 +           SERIAL and LOCAL_SERIAL may be used only for SELECTs; will be rejected with updates.
 +
 +        CONSISTENCY
 +
 +           CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.consistency_level])
 +            return
 +
 +        self.consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Consistency level set to %s.' % (level.upper(),)
 +
 +    def do_serial(self, parsed):
 +        """
 +        SERIAL CONSISTENCY [cqlsh only]
 +
 +           Overrides serial consistency level (default level is SERIAL).
 +
 +        SERIAL CONSISTENCY <level>
 +
 +           Sets consistency level for future conditional updates.
 +
 +           Valid consistency levels:
 +
 +           SERIAL, LOCAL_SERIAL.
 +
 +        SERIAL CONSISTENCY
 +
 +           SERIAL CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current serial consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.serial_consistency_level])
 +            return
 +
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Serial consistency level set to %s.' % (level.upper(),)
 +
 +    def do_login(self, parsed):
 +        """
 +        LOGIN [cqlsh only]
 +
 +           Changes login information without requiring restart.
 +
 +        LOGIN <username> (<password>)
 +
 +           Login using the specified username. If password is specified, it will be used
 +           otherwise, you will be prompted to enter.
 +        """
 +        username = parsed.get_binding('username')
 +        password = parsed.get_binding('password')
 +        if password is None:
 +            password = getpass.getpass()
 +        else:
 +            password = password[1:-1]
 +
 +        auth_provider = PlainTextAuthProvider(username=username, password=password)
 +
 +        conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=self.conn.cql_version,
 +                       protocol_version=self.conn.protocol_version,
 +                       auth_provider=auth_provider,
 +                       ssl_options=self.conn.ssl_options,
 +                       load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                       control_connection_timeout=self.conn.connect_timeout,
 +                       connect_timeout=self.conn.connect_timeout)
 +
 +        if self.current_keyspace:
 +            session = conn.connect(self.current_keyspace)
 +        else:
 +            session = conn.connect()
 +
 +        # Copy session properties
 +        session.default_timeout = self.session.default_timeout
 +        session.row_factory = self.session.row_factory
 +        session.default_consistency_level = self.session.default_consistency_level
 +        session.max_trace_wait = self.session.max_trace_wait
 +
 +        # Update after we've connected in case we fail to authenticate
 +        self.conn = conn
 +        self.auth_provider = auth_provider
 +        self.username = username
 +        self.session = session
 +
 +    def do_exit(self, parsed=None):
 +        """
 +        EXIT/QUIT [cqlsh only]
 +
 +        Exits cqlsh.
 +        """
 +        self.stop = True
 +        if self.owns_connection:
 +            self.conn.shutdown()
 +    do_quit = do_exit
 +
 +    def do_clear(self, parsed):
 +        """
 +        CLEAR/CLS [cqlsh only]
 +
 +        Clears the console.
 +        """
 +        import subprocess
 +

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[22/23] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.11

Posted by ja...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.11


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

Branch: refs/heads/trunk
Commit: 02bbdd63422c57efa4ba2356e72d87a28aebaaf8
Parents: 36375f8 685dde1
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:03:50 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:05:04 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 18 ++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 18 ++++++++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 53 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 973939e,8696653..ebb7a66
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -41,23 -25,11 +41,25 @@@ Merged from 2.2
   * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
 - * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 -
 -
 -3.0.15
++ * More PEP8 compiance for cqlsh (CASSANDRA-14021)
 +
 +
 +3.11.1
 + * Fix the computation of cdc_total_space_in_mb for exabyte filesystems (CASSANDRA-13808)
 + * AbstractTokenTreeBuilder#serializedSize returns wrong value when there is a single leaf and overflow collisions (CASSANDRA-13869)
 + * Add a compaction option to TWCS to ignore sstables overlapping checks (CASSANDRA-13418)
 + * BTree.Builder memory leak (CASSANDRA-13754)
 + * Revert CASSANDRA-10368 of supporting non-pk column filtering due to correctness (CASSANDRA-13798)
 + * Add a skip read validation flag to cassandra-stress (CASSANDRA-13772)
 + * Fix cassandra-stress hang issues when an error during cluster connection happens (CASSANDRA-12938)
 + * Better bootstrap failure message when blocked by (potential) range movement (CASSANDRA-13744)
 + * "ignore" option is ignored in sstableloader (CASSANDRA-13721)
 + * Deadlock in AbstractCommitLogSegmentManager (CASSANDRA-13652)
 + * Duplicate the buffer before passing it to analyser in SASI operation (CASSANDRA-13512)
 + * Properly evict pstmts from prepared statements cache (CASSANDRA-13641)
 +Merged from 3.0:
   * Improve TRUNCATE performance (CASSANDRA-13909)
   * Implement short read protection on partition boundaries (CASSANDRA-13595)
   * Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index cf3b32d,dfef609..803ea63
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -100,18 -99,19 +102,19 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
  DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
  DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 -DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
  
 -if platform.system() == 'Windows':
 -    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +DEFAULT_TIMESTAMP_FORMAT = os.environ.get('CQLSH_DEFAULT_TIMESTAMP_FORMAT', '')
 +if not DEFAULT_TIMESTAMP_FORMAT:
 +    DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S.%f%z'
  
  
 -class DateTimeFormat():
 +class DateTimeFormat:
  
      def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 -                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None, milliseconds_only=False):
          self.timestamp_format = timestamp_format
          self.date_format = date_format
          self.nanotime_format = nanotime_format
@@@ -237,8 -152,9 +241,10 @@@ def formatter_for(typname)
  def format_value_blob(val, colormap, **_):
      bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
 +formatter_for('blob')(format_value_blob)
  
  
  def format_python_formatted_type(val, colormap, color, quote=False):
@@@ -259,9 -175,7 +265,10 @@@ def format_value_decimal(val, float_pre
  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)
@@@ -273,9 -187,7 +280,10 @@@ def format_value_boolean(val, colormap
          val = boolean_styles[0] if val else boolean_styles[1]
      return format_python_formatted_type(val, colormap, 'boolean')
  
+ 
 +formatter_for('boolean')(format_value_boolean)
 +
 +
  def format_floating_point_type(val, colormap, float_precision, decimal_sep=None, thousands_sep=None, **_):
      if math.isnan(val):
          bval = 'NaN'
@@@ -302,8 -214,8 +310,9 @@@
  
      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, thousands_sep=None, **_):
@@@ -348,12 -249,9 +358,13 @@@ def format_value_timestamp(val, colorma
          bval = "'%s'" % bval
      return colorme(bval, colormap, 'timestamp')
  
+ 
 -def strftime(time_format, seconds, timezone=None):
 -    ret_dt = datetime_from_timestamp(seconds).replace(tzinfo=UTC())
 +formatter_for('timestamp')(format_value_timestamp)
 +
 +
 +def strftime(time_format, seconds, microseconds=0, timezone=None):
 +    ret_dt = datetime_from_timestamp(seconds) + datetime.timedelta(microseconds=microseconds)
 +    ret_dt = ret_dt.replace(tzinfo=UTC())
      if timezone:
          ret_dt = ret_dt.astimezone(timezone)
      try:
@@@ -366,24 -264,7 +377,25 @@@
          # able to correctly import timestamps exported as milliseconds since the epoch.
          return '%d' % (seconds * 1000.0)
  
+ 
 +microseconds_regex = re.compile("(.*)(?:\.(\d{1,6}))(.*)")
 +
 +
 +def round_microseconds(val):
 +    """
 +    For COPY TO, we need to round microsecond to milliseconds because server side
 +    TimestampSerializer.dateStringPatterns only parses milliseconds. If we keep microseconds,
 +    users may try to import with COPY FROM a file generated with COPY TO and have problems if
 +    prepared statements are disabled, see CASSANDRA-11631.
 +    """
 +    m = microseconds_regex.match(val)
 +    if not m:
 +        return val
 +
 +    milliseconds = int(m.group(2)) * pow(10, 3 - len(m.group(2)))
 +    return '%s.%03d%s' % (m.group(1), milliseconds, '' if not m.group(3) else m.group(3))
 +
 +
  @formatter_for('Date')
  def format_value_date(val, colormap, **_):
      return format_python_formatted_type(val, colormap, 'date')
@@@ -475,16 -287,15 +487,17 @@@ def format_value_text(val, encoding, co
  
      return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
  
+ 
  # name alias
  formatter_for('unicode')(format_value_text)
 +formatter_for('text')(format_value_text)
 +formatter_for('ascii')(format_value_text)
  
  
 -def format_simple_collection(val, lbracket, rbracket, encoding,
 +def format_simple_collection(val, cqltype, lbracket, rbracket, encoding,
                               colormap, date_time_format, float_precision, nullval,
                               decimal_sep, thousands_sep, boolean_styles):
 -    subs = [format_value(type(sval), sval, encoding=encoding, colormap=colormap,
 +    subs = [format_value(sval, cqltype=stype, encoding=encoding, colormap=colormap,
                           date_time_format=date_time_format, float_precision=float_precision,
                           nullval=nullval, quote=True, decimal_sep=decimal_sep,
                           thousands_sep=thousands_sep, boolean_styles=boolean_styles)
@@@ -517,11 -328,13 +530,13 @@@ def format_value_tuple(val, cqltype, en
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
 +def format_value_set(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
 -    return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 +    return format_simple_collection(sorted(val), cqltype, '{', '}', encoding, colormap,
                                      date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
  formatter_for('sortedset')(format_value_set)
  formatter_for('SortedSet')(format_value_set)
@@@ -580,10 -393,3 +597,11 @@@ def format_value_utype(val, cqltype, en
          + rb
      displaywidth = 4 * len(subs) + sum(k.displaywidth + v.displaywidth for (k, v) in subs)
      return FormattedValue(bval, coloredval, displaywidth)
 +
++
 +NANOS_PER_MICRO = 1000
 +NANOS_PER_MILLI = 1000 * NANOS_PER_MICRO
 +NANOS_PER_SECOND = 1000 * NANOS_PER_MILLI
 +NANOS_PER_MINUTE = 60 * NANOS_PER_SECOND
 +NANOS_PER_HOUR = 60 * NANOS_PER_MINUTE
 +MONTHS_PER_YEAR = 12


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[02/23] cassandra git commit: More PEP8 compliance for cqlsh

Posted by ja...@apache.org.
More PEP8 compliance for cqlsh

patch by Michael Kjellman; reviewed by Jay Zhuang for CASSANDRA-14021


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

Branch: refs/heads/cassandra-2.2
Commit: f8d73a3acb00d807d09aa33e1612c89389b18480
Parents: d4fd82b
Author: Michael Kjellman <kj...@apple.com>
Authored: Tue Nov 14 20:51:37 2017 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 05:56:44 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 +-
 bin/cqlsh                      |  4 ++++
 pylib/cqlshlib/copyutil.py     |  6 +++---
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b4e6f75..6e1ca85 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
 2.1.20
- * 
+ * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 
 2.1.19
  * Add storage port options to sstableloader (CASSANDRA-13844)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 6317ec9..30840db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -83,6 +83,7 @@ def find_zip(libprefix):
         if zips:
             return max(zips)   # probably the highest version, if multiple
 
+
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
@@ -522,6 +523,8 @@ def show_warning_without_quoting_line(message, category, filename, lineno, file=
         file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
     except IOError:
         pass
+
+
 warnings.showwarning = show_warning_without_quoting_line
 warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 
@@ -2213,6 +2216,7 @@ def main(options, hostname, port):
     if batch_mode and shell.statement_error:
         sys.exit(2)
 
+
 # always call this regardless of module name: when a sub-process is spawned
 # on Windows then the module name is not __main__, see CASSANDRA-9304
 insert_driver_hooks()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py
index 3a45353..85e2678 100644
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@ -191,7 +191,7 @@ class OneWayChannels(object):
         for ch in self.channels:
             try:
                 ch.close()
-            except:
+            except Exception:
                 pass
 
 
@@ -1967,8 +1967,8 @@ class ImportConversion(object):
             pk_values = []
             for i in partition_key_indexes:
                 val = serialize(i, row[i])
-                l = len(val)
-                pk_values.append(struct.pack(">H%dsB" % l, l, val, 0))
+                length = len(val)
+                pk_values.append(struct.pack(">H%dsB" % length, length, val, 0))
             return b"".join(pk_values)
 
         if len(partition_key_indexes) == 1:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 029e0c7..012e383 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,6 +34,7 @@ class UnexpectedTableStructure(UserWarning):
     def __str__(self):
         return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
 
+
 SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 NONALTERBALE_KEYSPACES = ('system')
 
@@ -109,6 +110,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
             cqlword = cqlword[1:-1].replace("''", "'")
         return cqlword
 
+
 CqlRuleSet = Cql3ParsingRuleSet()
 
 # convenience for remainder of module
@@ -306,6 +308,7 @@ def prop_equals_completer(ctxt, cass):
             return ()
     return ['=']
 
+
 completer_for('property', 'propeq')(prop_equals_completer)
 
 
@@ -529,6 +532,7 @@ def ks_name_completer(ctxt, cass):
 def cf_ks_name_completer(ctxt, cass):
     return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
 
+
 completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 
 
@@ -538,6 +542,7 @@ def cf_ks_dot_completer(ctxt, cass):
         return ['.']
     return []
 
+
 completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 
 
@@ -554,6 +559,7 @@ def cf_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, cfnames)
 
+
 completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
 
 completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
@@ -606,6 +612,7 @@ def working_on_keyspace(ctxt):
         return True
     return False
 
+
 syntax_rules += r'''
 <useStatement> ::= "USE" <keyspaceName>
                  ;
@@ -694,6 +701,7 @@ def select_relation_lhs_completer(ctxt, cass):
 def select_count_star_completer(ctxt, cass):
     return ['*']
 
+
 explain_completion('selector', 'colname')
 
 syntax_rules += r'''
@@ -770,6 +778,7 @@ def insert_option_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <updateStatement> ::= "UPDATE" cf=<columnFamilyName>
                         ( "USING" [updateopt]=<usingOption>
@@ -863,6 +872,7 @@ def update_indexbracket_completer(ctxt, cass):
         return ['[']
     return []
 
+
 syntax_rules += r'''
 <deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
                         "FROM" cf=<columnFamilyName>
@@ -890,6 +900,7 @@ def delete_delcol_completer(ctxt, cass):
     layout = get_table_meta(ctxt, cass)
     return map(maybe_escape_name, regular_column_names(layout))
 
+
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
                         ( "USING" [batchopt]=<usingOption>
@@ -912,6 +923,7 @@ def batch_opt_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
                       ;
@@ -931,6 +943,7 @@ def create_ks_wat_completer(ctxt, cass):
         return ['KEYSPACE']
     return ['KEYSPACE', 'SCHEMA']
 
+
 syntax_rules += r'''
 <createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
                                     ( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
@@ -979,6 +992,7 @@ def create_cf_wat_completer(ctxt, cass):
         return ['TABLE']
     return ['TABLE', 'COLUMNFAMILY']
 
+
 explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
 explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
 
@@ -1033,6 +1047,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
         return ()
     return [',']
 
+
 syntax_rules += r'''
 
 <idxName> ::= <identifier>
@@ -1065,6 +1080,7 @@ def create_index_col_completer(ctxt, cass):
     colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
+
 syntax_rules += r'''
 <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                           ;
@@ -1113,6 +1129,7 @@ def idx_ks_idx_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, idxnames)
 
+
 syntax_rules += r'''
 <alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
                                <alterInstructions>
@@ -1149,6 +1166,7 @@ def alter_type_field_completer(ctxt, cass):
     fields = [tuple[0] for tuple in layout]
     return map(maybe_escape_name, fields)
 
+
 explain_completion('alterInstructions', 'newcol', '<new_column_name>')
 explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
 
@@ -1227,6 +1245,7 @@ def username_name_completer(ctxt, cass):
     session = cass.session
     return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
+
 syntax_rules += r'''
 <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
@@ -1251,6 +1270,7 @@ def alter_type_field_completer(ctxt, cass):
     names = get_trigger_names(ctxt, cass)
     return map(maybe_escape_name, names)
 
+
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/displaying.py b/pylib/cqlshlib/displaying.py
index 7b260c2..09068ca 100644
--- a/pylib/cqlshlib/displaying.py
+++ b/pylib/cqlshlib/displaying.py
@@ -99,6 +99,7 @@ class FormattedValue:
         """
         return self.coloredval + self._pad(width, fill)
 
+
 DEFAULT_VALUE_COLORS = dict(
     default=YELLOW,
     text=YELLOW,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index abb4896..eac1810 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -38,6 +38,7 @@ def _show_control_chars(match):
         txt = txt[1:-1]
     return txt
 
+
 bits_to_turn_red_re = re.compile(r'\\([^uUx]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|U[0-9a-fA-F]{8})')
 
 
@@ -49,6 +50,7 @@ def _make_turn_bits_red_f(color1, color2):
         return color1 + txt + color2
     return _turn_bits_red
 
+
 default_null_placeholder = 'null'
 default_time_format = ''
 default_float_precision = 3
@@ -101,6 +103,7 @@ def format_value_default(val, colormap, **_):
     bval = controlchars_re.sub(_show_control_chars, escapedval)
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap)
 
+
 # Mapping cql type base names ("int", "map", etc) to formatter functions,
 # making format_value a generic function
 _formatters = {}
@@ -128,6 +131,8 @@ def formatter_for(typname):
 def format_value_blob(val, colormap, **_):
     bval = '0x' + binascii.hexlify(str(val))
     return colorme(bval, colormap, 'blob')
+
+
 formatter_for('buffer')(format_value_blob)
 
 
@@ -188,6 +193,7 @@ def format_floating_point_type(val, colormap, float_precision, decimal_sep=None,
 
     return colorme(bval, colormap, 'float')
 
+
 formatter_for('float')(format_floating_point_type)
 
 
@@ -196,6 +202,7 @@ def format_integer_type(val, colormap, thousands_sep=None, **_):
     bval = format_integer_with_thousands_sep(val, thousands_sep) if thousands_sep else str(val)
     return colorme(bval, colormap, 'int')
 
+
 # We can get rid of this in cassandra-2.2
 if sys.version_info >= (2, 7):
     def format_integer_with_thousands_sep(val, thousands_sep=','):
@@ -221,6 +228,7 @@ def format_value_timestamp(val, colormap, time_format, quote=False, **_):
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+
 formatter_for('datetime')(format_value_timestamp)
 
 
@@ -241,6 +249,7 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
 
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
 
+
 # name alias
 formatter_for('unicode')(format_value_text)
 
@@ -286,6 +295,8 @@ def format_value_set(val, encoding, colormap, time_format, float_precision, null
     return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval,
                                     decimal_sep, thousands_sep, boolean_styles)
+
+
 formatter_for('frozenset')(format_value_set)
 # This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 # and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
@@ -314,6 +325,8 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, null
         + 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)
 formatter_for('OrderedMap')(format_value_map)
 formatter_for('OrderedMapSerializedKey')(format_value_map)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index 9cf0f4e..7b11eac 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -518,6 +518,7 @@ class ParsingRuleSet:
         pattern.match(ctxt, completions)
         return completions
 
+
 import sys
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/wcwidth.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/wcwidth.py b/pylib/cqlshlib/wcwidth.py
index bc55c31..985fd41 100644
--- a/pylib/cqlshlib/wcwidth.py
+++ b/pylib/cqlshlib/wcwidth.py
@@ -94,6 +94,7 @@ def bisearch(ucs, table):
             return 1
     return 0
 
+
 # The following two functions define the column width of an ISO 10646
 # character as follows:
 #
@@ -178,6 +179,7 @@ combining = (
     (0xE0100, 0xE01EF)
 )
 
+
 # sorted list of non-overlapping intervals of East Asian Ambiguous
 # characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 ambiguous = (
@@ -321,6 +323,7 @@ def wcwidth_cjk(c):
 def wcswidth_cjk(s):
     return mk_wcswidth_cjk(map(ord, s))
 
+
 if __name__ == "__main__":
     samples = (
         ('MUSIC SHARP SIGN', 1),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[21/23] cassandra git commit: Merge branch 'cassandra-3.0' into cassandra-3.11

Posted by ja...@apache.org.
Merge branch 'cassandra-3.0' into cassandra-3.11


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

Branch: refs/heads/cassandra-3.11
Commit: 02bbdd63422c57efa4ba2356e72d87a28aebaaf8
Parents: 36375f8 685dde1
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:03:50 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:05:04 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 18 ++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 18 ++++++++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 53 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 973939e,8696653..ebb7a66
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -41,23 -25,11 +41,25 @@@ Merged from 2.2
   * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
 + * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
 - * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 -
 -
 -3.0.15
++ * More PEP8 compiance for cqlsh (CASSANDRA-14021)
 +
 +
 +3.11.1
 + * Fix the computation of cdc_total_space_in_mb for exabyte filesystems (CASSANDRA-13808)
 + * AbstractTokenTreeBuilder#serializedSize returns wrong value when there is a single leaf and overflow collisions (CASSANDRA-13869)
 + * Add a compaction option to TWCS to ignore sstables overlapping checks (CASSANDRA-13418)
 + * BTree.Builder memory leak (CASSANDRA-13754)
 + * Revert CASSANDRA-10368 of supporting non-pk column filtering due to correctness (CASSANDRA-13798)
 + * Add a skip read validation flag to cassandra-stress (CASSANDRA-13772)
 + * Fix cassandra-stress hang issues when an error during cluster connection happens (CASSANDRA-12938)
 + * Better bootstrap failure message when blocked by (potential) range movement (CASSANDRA-13744)
 + * "ignore" option is ignored in sstableloader (CASSANDRA-13721)
 + * Deadlock in AbstractCommitLogSegmentManager (CASSANDRA-13652)
 + * Duplicate the buffer before passing it to analyser in SASI operation (CASSANDRA-13512)
 + * Properly evict pstmts from prepared statements cache (CASSANDRA-13641)
 +Merged from 3.0:
   * Improve TRUNCATE performance (CASSANDRA-13909)
   * Implement short read protection on partition boundaries (CASSANDRA-13595)
   * Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/02bbdd63/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index cf3b32d,dfef609..803ea63
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -100,18 -99,19 +102,19 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
  DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
  DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 -DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
  
 -if platform.system() == 'Windows':
 -    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +DEFAULT_TIMESTAMP_FORMAT = os.environ.get('CQLSH_DEFAULT_TIMESTAMP_FORMAT', '')
 +if not DEFAULT_TIMESTAMP_FORMAT:
 +    DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S.%f%z'
  
  
 -class DateTimeFormat():
 +class DateTimeFormat:
  
      def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 -                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None, milliseconds_only=False):
          self.timestamp_format = timestamp_format
          self.date_format = date_format
          self.nanotime_format = nanotime_format
@@@ -237,8 -152,9 +241,10 @@@ def formatter_for(typname)
  def format_value_blob(val, colormap, **_):
      bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
 +formatter_for('blob')(format_value_blob)
  
  
  def format_python_formatted_type(val, colormap, color, quote=False):
@@@ -259,9 -175,7 +265,10 @@@ def format_value_decimal(val, float_pre
  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)
@@@ -273,9 -187,7 +280,10 @@@ def format_value_boolean(val, colormap
          val = boolean_styles[0] if val else boolean_styles[1]
      return format_python_formatted_type(val, colormap, 'boolean')
  
+ 
 +formatter_for('boolean')(format_value_boolean)
 +
 +
  def format_floating_point_type(val, colormap, float_precision, decimal_sep=None, thousands_sep=None, **_):
      if math.isnan(val):
          bval = 'NaN'
@@@ -302,8 -214,8 +310,9 @@@
  
      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, thousands_sep=None, **_):
@@@ -348,12 -249,9 +358,13 @@@ def format_value_timestamp(val, colorma
          bval = "'%s'" % bval
      return colorme(bval, colormap, 'timestamp')
  
+ 
 -def strftime(time_format, seconds, timezone=None):
 -    ret_dt = datetime_from_timestamp(seconds).replace(tzinfo=UTC())
 +formatter_for('timestamp')(format_value_timestamp)
 +
 +
 +def strftime(time_format, seconds, microseconds=0, timezone=None):
 +    ret_dt = datetime_from_timestamp(seconds) + datetime.timedelta(microseconds=microseconds)
 +    ret_dt = ret_dt.replace(tzinfo=UTC())
      if timezone:
          ret_dt = ret_dt.astimezone(timezone)
      try:
@@@ -366,24 -264,7 +377,25 @@@
          # able to correctly import timestamps exported as milliseconds since the epoch.
          return '%d' % (seconds * 1000.0)
  
+ 
 +microseconds_regex = re.compile("(.*)(?:\.(\d{1,6}))(.*)")
 +
 +
 +def round_microseconds(val):
 +    """
 +    For COPY TO, we need to round microsecond to milliseconds because server side
 +    TimestampSerializer.dateStringPatterns only parses milliseconds. If we keep microseconds,
 +    users may try to import with COPY FROM a file generated with COPY TO and have problems if
 +    prepared statements are disabled, see CASSANDRA-11631.
 +    """
 +    m = microseconds_regex.match(val)
 +    if not m:
 +        return val
 +
 +    milliseconds = int(m.group(2)) * pow(10, 3 - len(m.group(2)))
 +    return '%s.%03d%s' % (m.group(1), milliseconds, '' if not m.group(3) else m.group(3))
 +
 +
  @formatter_for('Date')
  def format_value_date(val, colormap, **_):
      return format_python_formatted_type(val, colormap, 'date')
@@@ -475,16 -287,15 +487,17 @@@ def format_value_text(val, encoding, co
  
      return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
  
+ 
  # name alias
  formatter_for('unicode')(format_value_text)
 +formatter_for('text')(format_value_text)
 +formatter_for('ascii')(format_value_text)
  
  
 -def format_simple_collection(val, lbracket, rbracket, encoding,
 +def format_simple_collection(val, cqltype, lbracket, rbracket, encoding,
                               colormap, date_time_format, float_precision, nullval,
                               decimal_sep, thousands_sep, boolean_styles):
 -    subs = [format_value(type(sval), sval, encoding=encoding, colormap=colormap,
 +    subs = [format_value(sval, cqltype=stype, encoding=encoding, colormap=colormap,
                           date_time_format=date_time_format, float_precision=float_precision,
                           nullval=nullval, quote=True, decimal_sep=decimal_sep,
                           thousands_sep=thousands_sep, boolean_styles=boolean_styles)
@@@ -517,11 -328,13 +530,13 @@@ def format_value_tuple(val, cqltype, en
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
 +def format_value_set(val, cqltype, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
 -    return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 +    return format_simple_collection(sorted(val), cqltype, '{', '}', encoding, colormap,
                                      date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
  formatter_for('sortedset')(format_value_set)
  formatter_for('SortedSet')(format_value_set)
@@@ -580,10 -393,3 +597,11 @@@ def format_value_utype(val, cqltype, en
          + rb
      displaywidth = 4 * len(subs) + sum(k.displaywidth + v.displaywidth for (k, v) in subs)
      return FormattedValue(bval, coloredval, displaywidth)
 +
++
 +NANOS_PER_MICRO = 1000
 +NANOS_PER_MILLI = 1000 * NANOS_PER_MICRO
 +NANOS_PER_SECOND = 1000 * NANOS_PER_MILLI
 +NANOS_PER_MINUTE = 60 * NANOS_PER_SECOND
 +NANOS_PER_HOUR = 60 * NANOS_PER_MINUTE
 +MONTHS_PER_YEAR = 12


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[20/23] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by ja...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


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

Branch: refs/heads/cassandra-3.0
Commit: 685dde10e3a6b4a27936893840f536fa25ae9da5
Parents: 51bf518 503aec7
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:01:38 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:03:22 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  3 ++-
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 0453ddd,055a35d..8696653
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -25,67 -2,11 +25,68 @@@ Merged from 2.2
   * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
-- * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.2.11
 +
 +3.0.15
 + * Improve TRUNCATE performance (CASSANDRA-13909)
 + * Implement short read protection on partition boundaries (CASSANDRA-13595)
 + * Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)
 + * Filter header only commit logs before recovery (CASSANDRA-13918)
 + * AssertionError prepending to a list (CASSANDRA-13149)
 + * Fix support for SuperColumn tables (CASSANDRA-12373)
 + * Handle limit correctly on tables with strict liveness (CASSANDRA-13883)
 + * Fix missing original update in TriggerExecutor (CASSANDRA-13894)
 + * Remove non-rpc-ready nodes from counter leader candidates (CASSANDRA-13043)
 + * Improve short read protection performance (CASSANDRA-13794)
 + * Fix sstable reader to support range-tombstone-marker for multi-slices (CASSANDRA-13787)
 + * Fix short read protection for tables with no clustering columns (CASSANDRA-13880)
 + * Make isBuilt volatile in PartitionUpdate (CASSANDRA-13619)
 + * Prevent integer overflow of timestamps in CellTest and RowsTest (CASSANDRA-13866)
 + * Fix counter application order in short read protection (CASSANDRA-12872)
 + * Don't block RepairJob execution on validation futures (CASSANDRA-13797)
 + * Wait for all management tasks to complete before shutting down CLSM (CASSANDRA-13123)
 + * INSERT statement fails when Tuple type is used as clustering column with default DESC order (CASSANDRA-13717)
 + * Fix pending view mutations handling and cleanup batchlog when there are local and remote paired mutations (CASSANDRA-13069)
 + * Improve config validation and documentation on overflow and NPE (CASSANDRA-13622)
 + * Range deletes in a CAS batch are ignored (CASSANDRA-13655)
 + * Avoid assertion error when IndexSummary > 2G (CASSANDRA-12014)
 + * Change repair midpoint logging for tiny ranges (CASSANDRA-13603)
 + * Better handle corrupt final commitlog segment (CASSANDRA-11995)
 + * StreamingHistogram is not thread safe (CASSANDRA-13756)
 + * Fix MV timestamp issues (CASSANDRA-11500)
 + * Better tolerate improperly formatted bcrypt hashes (CASSANDRA-13626) 
 + * Fix race condition in read command serialization (CASSANDRA-13363)
 + * Enable segement creation before recovering commitlogs (CASSANDRA-13587)
 + * Fix AssertionError in short read protection (CASSANDRA-13747)
 + * Don't skip corrupted sstables on startup (CASSANDRA-13620)
 + * Fix the merging of cells with different user type versions (CASSANDRA-13776)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13640)
 + * Potential AssertionError during ReadRepair of range tombstone and partition deletions (CASSANDRA-13719)
 + * Don't let stress write warmup data if n=0 (CASSANDRA-13773)
 + * Gossip thread slows down when using batch commit log (CASSANDRA-12966)
 + * Randomize batchlog endpoint selection with only 1 or 2 racks (CASSANDRA-12884)
 + * Fix digest calculation for counter cells (CASSANDRA-13750)
 + * Fix ColumnDefinition.cellValueType() for non-frozen collection and change SSTabledump to use type.toJSONString() (CASSANDRA-13573)
 + * Skip materialized view addition if the base table doesn't exist (CASSANDRA-13737)
 + * Drop table should remove corresponding entries in dropped_columns table (CASSANDRA-13730)
 + * Log warn message until legacy auth tables have been migrated (CASSANDRA-13371)
 + * Fix incorrect [2.1 <- 3.0] serialization of counter cells created in 2.0 (CASSANDRA-13691)
 + * Fix invalid writetime for null cells (CASSANDRA-13711)
 + * Fix ALTER TABLE statement to atomically propagate changes to the table and its MVs (CASSANDRA-12952)
 + * Fixed ambiguous output of nodetool tablestats command (CASSANDRA-13722)
 + * JMXEnabledThreadPoolExecutor with corePoolSize equal to maxPoolSize (Backport CASSANDRA-13329)
 + * Fix Digest mismatch Exception if hints file has UnknownColumnFamily (CASSANDRA-13696)
 + * Purge tombstones created by expired cells (CASSANDRA-13643)
 + * Make concat work with iterators that have different subsets of columns (CASSANDRA-13482)
 + * Set test.runners based on cores and memory size (CASSANDRA-13078)
 + * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557)
 + * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606)
 + * Fix secondary index queries on COMPACT tables (CASSANDRA-13627)
 + * Nodetool listsnapshots output is missing a newline, if there are no snapshots (CASSANDRA-13568)
 + * sstabledump reports incorrect usage for argument order (CASSANDRA-13532)
 +Merged from 2.2:
   * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
   * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
   * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 2a8b560,8224ad9..0f42e6e
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,8 -34,9 +34,9 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
 -NONALTERBALE_KEYSPACES = ('system')
 +SYSTEM_KEYSPACES = ('system', 'system_schema', 'system_traces', 'system_auth', 'system_distributed')
 +NONALTERBALE_KEYSPACES = ('system', 'system_schema')
  
  
  class Cql3ParsingRuleSet(CqlParsingRuleSet):
@@@ -579,8 -571,8 +582,9 @@@ def ks_name_completer(ctxt, cass)
  def cf_ks_name_completer(ctxt, cass):
      return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
  
+ 
  completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 +completer_for('materializedViewName', 'ksname')(cf_ks_name_completer)
  
  
  def cf_ks_dot_completer(ctxt, cass):
@@@ -589,8 -581,8 +593,9 @@@
          return ['.']
      return []
  
+ 
  completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 +completer_for('materializedViewName', 'dot')(cf_ks_dot_completer)
  
  
  @completer_for('columnFamilyName', 'cfname')
@@@ -607,19 -599,6 +612,20 @@@ def cf_name_completer(ctxt, cass)
      return map(maybe_escape_name, cfnames)
  
  
 +@completer_for('materializedViewName', 'mvname')
 +def mv_name_completer(ctxt, cass):
 +    ks = ctxt.get_binding('ksname', None)
 +    if ks is not None:
 +        ks = dequote_name(ks)
 +    try:
 +        mvnames = cass.get_materialized_view_names(ks)
 +    except Exception:
 +        if ks is None:
 +            return ()
 +        raise
 +    return map(maybe_escape_name, mvnames)
 +
++
  completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
  
  completer_for('userTypeName', 'dot')(cf_ks_dot_completer)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[15/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/copyutil.py
index b72b517,85e2678..c9c5829
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@@ -150,37 -129,28 +150,37 @@@ class SendingChannel(object)
      def num_pending(self):
          return self.pending_messages.qsize() if self.pending_messages else 0
  
 -    def recv(self):
 -        with self.rlock:
 -            return self.reader.recv()
 +    def close(self):
 +        self.pipe.close()
 +
 +
 +class SendingChannels(object):
 +    """
 +    A group of one way channels for sending messages.
 +    """
 +    def __init__(self, num_channels):
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [SendingChannel(p) for p in self.pipes]
 +        self.num_channels = num_channels
  
      def close(self):
 -        self.reader.close()
 -        self.writer.close()
 +        for ch in self.channels:
 +            try:
 +                ch.close()
-             except:
++            except Exception:
 +                pass
  
  
 -class OneWayChannels(object):
 +class ReceivingChannels(object):
      """
 -    A group of one way channels.
 +    A group of one way channels for receiving messages.
      """
      def __init__(self, num_channels):
 -        self.channels = [OneWayChannel() for _ in xrange(num_channels)]
 -        self._readers = [ch.reader for ch in self.channels]
 -        self._rlocks = [ch.rlock for ch in self.channels]
 -        self._rlocks_by_readers = dict([(ch.reader, ch.rlock) for ch in self.channels])
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [ReceivingChannel(p) for p in self.pipes]
 +        self._readers = [p.reader for p in self.pipes]
 +        self._rlocks = [p.rlock for p in self.pipes]
 +        self._rlocks_by_readers = dict([(p.reader, p.rlock) for p in self.pipes])
          self.num_channels = num_channels
  
          self.recv = self.recv_select if IS_LINUX else self.recv_polling

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 897ee16,012e383..8224ad9
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,7 -34,8 +34,8 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 +SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
  NONALTERBALE_KEYSPACES = ('system')
  
  
@@@ -785,10 -691,17 +792,11 @@@ def select_relation_lhs_completer(ctxt
              filterable.add(layout.clustering_key[num].name)
          else:
              break
 -    for cd in layout.columns.values():
 -        if cd.index:
 -            filterable.add(cd.name)
 +    for idx in layout.indexes.itervalues():
 +        filterable.add(idx.index_options["target"])
      return map(maybe_escape_name, filterable)
  
+ 
 -@completer_for('selectClause', 'star')
 -def select_count_star_completer(ctxt, cass):
 -    return ['*']
 -
 -
  explain_completion('selector', 'colname')
  
  syntax_rules += r'''
@@@ -1178,12 -1076,11 +1193,13 @@@ explain_completion('createUserTypeState
  
  @completer_for('createIndexStatement', 'col')
  def create_index_col_completer(ctxt, cass):
 +    """ Return the columns for which an index doesn't exist yet. """
      layout = get_table_meta(ctxt, cass)
 -    colnames = [cd.name for cd in layout.columns.values() if not cd.index]
 +    idx_targets = [idx.index_options["target"] for idx in layout.indexes.itervalues()]
 +    colnames = [cd.name for cd in layout.columns.values() if cd.name not in idx_targets]
      return map(maybe_escape_name, colnames)
  
+ 
  syntax_rules += r'''
  <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                            ;
@@@ -1403,20 -1246,6 +1421,21 @@@ def username_name_completer(ctxt, cass)
      return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
  
  
 +@completer_for('rolename', 'role')
 +def rolename_completer(ctxt, cass):
 +    def maybe_quote(name):
 +        if CqlRuleSet.is_valid_cql3_name(name):
 +            return name
 +        return "'%s'" % name
 +
 +    # disable completion for CREATE ROLE.
 +    if ctxt.matched[0][1].upper() == 'CREATE':
 +        return [Hint('<rolename>')]
 +
 +    session = cass.session
 +    return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")]
 +
++
  syntax_rules += r'''
  <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                 "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index dcd08da,eac1810..f88fc5d
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -53,7 -50,9 +54,8 @@@ def _make_turn_bits_red_f(color1, color
          return color1 + txt + color2
      return _turn_bits_red
  
+ 
  default_null_placeholder = 'null'
 -default_time_format = ''
  default_float_precision = 3
  default_colormap = DEFAULT_VALUE_COLORS
  empty_colormap = defaultdict(lambda: '')
@@@ -97,24 -96,7 +99,25 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
 +DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
 +DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 +DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
 +
 +if platform.system() == 'Windows':
 +    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +
 +
 +class DateTimeFormat():
 +
 +    def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +        self.timestamp_format = timestamp_format
 +        self.date_format = date_format
 +        self.nanotime_format = nanotime_format
 +        self.timezone = timezone
 +
 +
  def format_value_default(val, colormap, **_):
      val = str(val)
      escapedval = val.replace('\\', '\\\\')
@@@ -146,8 -129,10 +150,10 @@@ def formatter_for(typname)
  
  @formatter_for('bytearray')
  def format_value_blob(val, colormap, **_):
 -    bval = '0x' + binascii.hexlify(str(val))
 +    bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
  
  
@@@ -311,14 -290,18 +320,16 @@@ def format_value_tuple(val, encoding, c
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, time_format, float_precision, nullval,
 +def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
      return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 -                                    time_format, float_precision, nullval,
 +                                    date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
 -# This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 -# and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
 -formatter_for('SortedSet')(format_value_set)
  formatter_for('sortedset')(format_value_set)
 +formatter_for('SortedSet')(format_value_set)
  
  
  @formatter_for('dict')


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[09/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/copyutil.py
index b72b517,85e2678..c9c5829
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@@ -150,37 -129,28 +150,37 @@@ class SendingChannel(object)
      def num_pending(self):
          return self.pending_messages.qsize() if self.pending_messages else 0
  
 -    def recv(self):
 -        with self.rlock:
 -            return self.reader.recv()
 +    def close(self):
 +        self.pipe.close()
 +
 +
 +class SendingChannels(object):
 +    """
 +    A group of one way channels for sending messages.
 +    """
 +    def __init__(self, num_channels):
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [SendingChannel(p) for p in self.pipes]
 +        self.num_channels = num_channels
  
      def close(self):
 -        self.reader.close()
 -        self.writer.close()
 +        for ch in self.channels:
 +            try:
 +                ch.close()
-             except:
++            except Exception:
 +                pass
  
  
 -class OneWayChannels(object):
 +class ReceivingChannels(object):
      """
 -    A group of one way channels.
 +    A group of one way channels for receiving messages.
      """
      def __init__(self, num_channels):
 -        self.channels = [OneWayChannel() for _ in xrange(num_channels)]
 -        self._readers = [ch.reader for ch in self.channels]
 -        self._rlocks = [ch.rlock for ch in self.channels]
 -        self._rlocks_by_readers = dict([(ch.reader, ch.rlock) for ch in self.channels])
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [ReceivingChannel(p) for p in self.pipes]
 +        self._readers = [p.reader for p in self.pipes]
 +        self._rlocks = [p.rlock for p in self.pipes]
 +        self._rlocks_by_readers = dict([(p.reader, p.rlock) for p in self.pipes])
          self.num_channels = num_channels
  
          self.recv = self.recv_select if IS_LINUX else self.recv_polling

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 897ee16,012e383..8224ad9
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,7 -34,8 +34,8 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 +SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
  NONALTERBALE_KEYSPACES = ('system')
  
  
@@@ -785,10 -691,17 +792,11 @@@ def select_relation_lhs_completer(ctxt
              filterable.add(layout.clustering_key[num].name)
          else:
              break
 -    for cd in layout.columns.values():
 -        if cd.index:
 -            filterable.add(cd.name)
 +    for idx in layout.indexes.itervalues():
 +        filterable.add(idx.index_options["target"])
      return map(maybe_escape_name, filterable)
  
+ 
 -@completer_for('selectClause', 'star')
 -def select_count_star_completer(ctxt, cass):
 -    return ['*']
 -
 -
  explain_completion('selector', 'colname')
  
  syntax_rules += r'''
@@@ -1178,12 -1076,11 +1193,13 @@@ explain_completion('createUserTypeState
  
  @completer_for('createIndexStatement', 'col')
  def create_index_col_completer(ctxt, cass):
 +    """ Return the columns for which an index doesn't exist yet. """
      layout = get_table_meta(ctxt, cass)
 -    colnames = [cd.name for cd in layout.columns.values() if not cd.index]
 +    idx_targets = [idx.index_options["target"] for idx in layout.indexes.itervalues()]
 +    colnames = [cd.name for cd in layout.columns.values() if cd.name not in idx_targets]
      return map(maybe_escape_name, colnames)
  
+ 
  syntax_rules += r'''
  <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                            ;
@@@ -1403,20 -1246,6 +1421,21 @@@ def username_name_completer(ctxt, cass)
      return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
  
  
 +@completer_for('rolename', 'role')
 +def rolename_completer(ctxt, cass):
 +    def maybe_quote(name):
 +        if CqlRuleSet.is_valid_cql3_name(name):
 +            return name
 +        return "'%s'" % name
 +
 +    # disable completion for CREATE ROLE.
 +    if ctxt.matched[0][1].upper() == 'CREATE':
 +        return [Hint('<rolename>')]
 +
 +    session = cass.session
 +    return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")]
 +
++
  syntax_rules += r'''
  <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                 "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index dcd08da,eac1810..f88fc5d
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -53,7 -50,9 +54,8 @@@ def _make_turn_bits_red_f(color1, color
          return color1 + txt + color2
      return _turn_bits_red
  
+ 
  default_null_placeholder = 'null'
 -default_time_format = ''
  default_float_precision = 3
  default_colormap = DEFAULT_VALUE_COLORS
  empty_colormap = defaultdict(lambda: '')
@@@ -97,24 -96,7 +99,25 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
 +DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
 +DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 +DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
 +
 +if platform.system() == 'Windows':
 +    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +
 +
 +class DateTimeFormat():
 +
 +    def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +        self.timestamp_format = timestamp_format
 +        self.date_format = date_format
 +        self.nanotime_format = nanotime_format
 +        self.timezone = timezone
 +
 +
  def format_value_default(val, colormap, **_):
      val = str(val)
      escapedval = val.replace('\\', '\\\\')
@@@ -146,8 -129,10 +150,10 @@@ def formatter_for(typname)
  
  @formatter_for('bytearray')
  def format_value_blob(val, colormap, **_):
 -    bval = '0x' + binascii.hexlify(str(val))
 +    bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
  
  
@@@ -311,14 -290,18 +320,16 @@@ def format_value_tuple(val, encoding, c
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, time_format, float_precision, nullval,
 +def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
      return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 -                                    time_format, float_precision, nullval,
 +                                    date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
 -# This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 -# and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
 -formatter_for('SortedSet')(format_value_set)
  formatter_for('sortedset')(format_value_set)
 +formatter_for('SortedSet')(format_value_set)
  
  
  @formatter_for('dict')


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[23/23] cassandra git commit: Merge branch 'cassandra-3.11' into trunk

Posted by ja...@apache.org.
Merge branch 'cassandra-3.11' into trunk


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

Branch: refs/heads/trunk
Commit: 6d324f9d769f24ac209f6ea7649fee02b0200ba0
Parents: 1e58a53 02bbdd6
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:05:35 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:06:51 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 ++
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 18 ++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 18 ++++++++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 53 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/6d324f9d/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index e38cd70,ebb7a66..0cda459
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -218,6 -42,8 +218,8 @@@ Merged from 2.2
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
   * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
 - * More PEP8 compiance for cqlsh (CASSANDRA-14021)
++ * More PEP8 compliance for cqlsh
  
  
  3.11.1

http://git-wip-us.apache.org/repos/asf/cassandra/blob/6d324f9d/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/6d324f9d/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[13/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/bin/cqlsh.py
----------------------------------------------------------------------
diff --cc bin/cqlsh.py
index 1f63826,0000000..e242d42
mode 100644,000000..100644
--- a/bin/cqlsh.py
+++ b/bin/cqlsh.py
@@@ -1,2588 -1,0 +1,2592 @@@
 +#!/bin/sh
 +# -*- mode: Python -*-
 +
 +# 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.
 +
 +""":"
 +# bash code here; finds a suitable python interpreter and execs this file.
 +# prefer unqualified "python" if suitable:
 +python -c 'import sys; sys.exit(not (0x020700b0 < sys.hexversion < 0x03000000))' 2>/dev/null \
 +    && exec python "$0" "$@"
 +for pyver in 2.7; do
 +    which python$pyver > /dev/null 2>&1 && exec python$pyver "$0" "$@"
 +done
 +echo "No appropriate python interpreter found." >&2
 +exit 1
 +":"""
 +
 +from __future__ import with_statement
 +
 +import cmd
 +import codecs
 +import ConfigParser
 +import csv
 +import getpass
 +import optparse
 +import os
 +import platform
 +import sys
 +import traceback
 +import warnings
 +import webbrowser
 +from StringIO import StringIO
 +from contextlib import contextmanager
 +from glob import glob
 +from uuid import UUID
 +
 +if sys.version_info[0] != 2 or sys.version_info[1] != 7:
 +    sys.exit("\nCQL Shell supports only Python 2.7\n")
 +
 +UTF8 = 'utf-8'
 +CP65001 = 'cp65001'  # Win utf-8 variant
 +
 +description = "CQL Shell for Apache Cassandra"
 +version = "5.0.1"
 +
 +readline = None
 +try:
 +    # check if tty first, cause readline doesn't check, and only cares
 +    # about $TERM. we don't want the funky escape code stuff to be
 +    # output if not a tty.
 +    if sys.stdin.isatty():
 +        import readline
 +except ImportError:
 +    pass
 +
 +CQL_LIB_PREFIX = 'cassandra-driver-internal-only-'
 +
 +CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
 +CASSANDRA_CQL_HTML_FALLBACK = 'https://cassandra.apache.org/doc/cql3/CQL-2.2.html'
 +
 +if os.path.exists(CASSANDRA_PATH + '/doc/cql3/CQL.html'):
 +    # default location of local CQL.html
 +    CASSANDRA_CQL_HTML = 'file://' + CASSANDRA_PATH + '/doc/cql3/CQL.html'
 +elif os.path.exists('/usr/share/doc/cassandra/CQL.html'):
 +    # fallback to package file
 +    CASSANDRA_CQL_HTML = 'file:///usr/share/doc/cassandra/CQL.html'
 +else:
 +    # fallback to online version
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +
 +# On Linux, the Python webbrowser module uses the 'xdg-open' executable
 +# to open a file/URL. But that only works, if the current session has been
 +# opened from _within_ a desktop environment. I.e. 'xdg-open' will fail,
 +# if the session's been opened via ssh to a remote box.
 +#
 +# Use 'python' to get some information about the detected browsers.
 +# >>> import webbrowser
 +# >>> webbrowser._tryorder
 +# >>> webbrowser._browser
 +#
 +if len(webbrowser._tryorder) == 0:
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +elif webbrowser._tryorder[0] == 'xdg-open' and os.environ.get('XDG_DATA_DIRS', '') == '':
 +    # only on Linux (some OS with xdg-open)
 +    webbrowser._tryorder.remove('xdg-open')
 +    webbrowser._tryorder.append('xdg-open')
 +
 +# use bundled libs for python-cql and thrift, if available. if there
 +# is a ../lib dir, use bundled libs there preferentially.
 +ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')]
 +myplatform = platform.system()
 +is_win = myplatform == 'Windows'
 +
 +# Workaround for supporting CP65001 encoding on python < 3.3 (https://bugs.python.org/issue13216)
 +if is_win and sys.version_info < (3, 3):
 +    codecs.register(lambda name: codecs.lookup(UTF8) if name == CP65001 else None)
 +
 +if myplatform == 'Linux':
 +    ZIPLIB_DIRS.append('/usr/share/cassandra/lib')
 +
 +if os.environ.get('CQLSH_NO_BUNDLED', ''):
 +    ZIPLIB_DIRS = ()
 +
 +
 +def find_zip(libprefix):
 +    for ziplibdir in ZIPLIB_DIRS:
 +        zips = glob(os.path.join(ziplibdir, libprefix + '*.zip'))
 +        if zips:
 +            return max(zips)   # probably the highest version, if multiple
 +
++
 +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, 'cassandra-driver-' + ver))
 +
 +third_parties = ('futures-', 'six-')
 +
 +for lib in third_parties:
 +    lib_zip = find_zip(lib)
 +    if lib_zip:
 +        sys.path.insert(0, lib_zip)
 +
 +warnings.filterwarnings("ignore", r".*blist.*")
 +try:
 +    import cassandra
 +except ImportError, e:
 +    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))
 +
 +from cassandra.auth import PlainTextAuthProvider
 +from cassandra.cluster import Cluster
 +from cassandra.metadata import (ColumnMetadata, KeyspaceMetadata,
 +                                TableMetadata, protect_name, protect_names)
 +from cassandra.policies import WhiteListRoundRobinPolicy
 +from cassandra.query import SimpleStatement, ordered_dict_factory, TraceUnavailable
 +
 +# cqlsh should run correctly when run out of a Cassandra source tree,
 +# out of an unpacked Cassandra tarball, and after a proper package install.
 +cqlshlibdir = os.path.join(CASSANDRA_PATH, 'pylib')
 +if os.path.isdir(cqlshlibdir):
 +    sys.path.insert(0, cqlshlibdir)
 +
 +from cqlshlib import cql3handling, cqlhandling, pylexotron, sslhandling
 +from cqlshlib.copyutil import ExportTask, ImportTask
 +from cqlshlib.displaying import (ANSI_RESET, BLUE, COLUMN_NAME_COLORS, CYAN,
 +                                 RED, FormattedValue, colorme)
 +from cqlshlib.formatting import (DEFAULT_DATE_FORMAT, DEFAULT_NANOTIME_FORMAT,
 +                                 DEFAULT_TIMESTAMP_FORMAT, DateTimeFormat,
 +                                 format_by_type, format_value_utype,
 +                                 formatter_for)
 +from cqlshlib.tracing import print_trace, print_trace_session
 +from cqlshlib.util import get_file_encoding_bomsize, trim_if_present
 +
 +DEFAULT_HOST = '127.0.0.1'
 +DEFAULT_PORT = 9042
 +DEFAULT_CQLVER = '3.3.1'
 +DEFAULT_PROTOCOL_VERSION = 4
 +DEFAULT_CONNECT_TIMEOUT_SECONDS = 5
 +DEFAULT_REQUEST_TIMEOUT_SECONDS = 10
 +
 +DEFAULT_FLOAT_PRECISION = 5
 +DEFAULT_MAX_TRACE_WAIT = 10
 +
 +if readline is not None and readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +    DEFAULT_COMPLETEKEY = '\t'
 +else:
 +    DEFAULT_COMPLETEKEY = 'tab'
 +
 +cqldocs = None
 +cqlruleset = None
 +
 +epilog = """Connects to %(DEFAULT_HOST)s:%(DEFAULT_PORT)d by default. These
 +defaults can be changed by setting $CQLSH_HOST and/or $CQLSH_PORT. When a
 +host (and optional port number) are given on the command line, they take
 +precedence over any defaults.""" % globals()
 +
 +parser = optparse.OptionParser(description=description, epilog=epilog,
 +                               usage="Usage: %prog [options] [host [port]]",
 +                               version='cqlsh ' + version)
 +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("--browser", dest='browser', help="""The browser to use to display CQL help, where BROWSER can be:
 +                                                    - one of the supported browsers in https://docs.python.org/2/library/webbrowser.html.
 +                                                    - browser path followed by %s, example: /usr/bin/google-chrome-stable %s""")
 +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('--debug', action='store_true',
 +                  help='Show additional debugging information')
 +parser.add_option("--encoding", help="Specify a non-default encoding for output." +
 +                  " (Default: %s)" % (UTF8,))
 +parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.")
 +parser.add_option('--cqlversion', default=DEFAULT_CQLVER,
 +                  help='Specify a particular CQL version (default: %default).'
 +                       ' Examples: "3.0.3", "3.1.0"')
 +parser.add_option("-e", "--execute", help='Execute the statement and quit.')
 +parser.add_option("--connect-timeout", default=DEFAULT_CONNECT_TIMEOUT_SECONDS, dest='connect_timeout',
 +                  help='Specify the connection timeout in seconds (default: %default seconds).')
 +parser.add_option("--request-timeout", default=DEFAULT_REQUEST_TIMEOUT_SECONDS, dest='request_timeout',
 +                  help='Specify the default request timeout in seconds (default: %default seconds).')
 +parser.add_option("-t", "--tty", action='store_true', dest='tty',
 +                  help='Force tty mode (command prompt).')
 +
 +optvalues = optparse.Values()
 +(options, arguments) = parser.parse_args(sys.argv[1:], values=optvalues)
 +
 +# BEGIN history/config definition
 +HISTORY_DIR = os.path.expanduser(os.path.join('~', '.cassandra'))
 +
 +if hasattr(options, 'cqlshrc'):
 +    CONFIG_FILE = options.cqlshrc
 +    if not os.path.exists(CONFIG_FILE):
 +        print '\nWarning: Specified cqlshrc location `%s` does not exist.  Using `%s` instead.\n' % (CONFIG_FILE, HISTORY_DIR)
 +        CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +else:
 +    CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +
 +HISTORY = os.path.join(HISTORY_DIR, 'cqlsh_history')
 +if not os.path.exists(HISTORY_DIR):
 +    try:
 +        os.mkdir(HISTORY_DIR)
 +    except OSError:
 +        print '\nWarning: Cannot create directory at `%s`. Command history will not be saved.\n' % HISTORY_DIR
 +
 +OLD_CONFIG_FILE = os.path.expanduser(os.path.join('~', '.cqlshrc'))
 +if os.path.exists(OLD_CONFIG_FILE):
 +    if os.path.exists(CONFIG_FILE):
 +        print '\nWarning: cqlshrc config files were found at both the old location (%s) and \
 +                the new location (%s), the old config file will not be migrated to the new \
 +                location, and the new location will be used for now.  You should manually \
 +                consolidate the config files at the new location and remove the old file.' \
 +                % (OLD_CONFIG_FILE, CONFIG_FILE)
 +    else:
 +        os.rename(OLD_CONFIG_FILE, CONFIG_FILE)
 +OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
 +if os.path.exists(OLD_HISTORY):
 +    os.rename(OLD_HISTORY, HISTORY)
 +# END history/config definition
 +
 +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.protocol.ErrorMessage, cassandra.protocol.InternalError, cassandra.query.TraceUnavailable
 +)
 +
 +debug_completion = bool(os.environ.get('CQLSH_DEBUG_COMPLETION', '') == 'YES')
 +
 +# we want the cql parser to understand our cqlsh-specific commands too
 +my_commands_ending_with_newline = (
 +    'help',
 +    '?',
 +    'consistency',
 +    'serial',
 +    'describe',
 +    'desc',
 +    'show',
 +    'source',
 +    'capture',
 +    'login',
 +    'debug',
 +    'tracing',
 +    'expand',
 +    'paging',
 +    'exit',
 +    'quit',
 +    'clear',
 +    'cls'
 +)
 +
 +
 +cqlsh_syntax_completers = []
 +
 +
 +def cqlsh_syntax_completer(rulename, termname):
 +    def registrator(f):
 +        cqlsh_syntax_completers.append((rulename, termname, f))
 +        return f
 +    return registrator
 +
 +
 +cqlsh_extra_syntax_rules = r'''
 +<cqlshCommand> ::= <CQL_Statement>
 +                 | <specialCommand> ( ";" | "\n" )
 +                 ;
 +
 +<specialCommand> ::= <describeCommand>
 +                   | <consistencyCommand>
 +                   | <serialConsistencyCommand>
 +                   | <showCommand>
 +                   | <sourceCommand>
 +                   | <captureCommand>
 +                   | <copyCommand>
 +                   | <loginCommand>
 +                   | <debugCommand>
 +                   | <helpCommand>
 +                   | <tracingCommand>
 +                   | <expandCommand>
 +                   | <exitCommand>
 +                   | <pagingCommand>
 +                   | <clearCommand>
 +                   ;
 +
 +<describeCommand> ::= ( "DESCRIBE" | "DESC" )
 +                                  ( "FUNCTIONS"
 +                                  | "FUNCTION" udf=<anyFunctionName>
 +                                  | "AGGREGATES"
 +                                  | "AGGREGATE" uda=<userAggregateName>
 +                                  | "KEYSPACES"
 +                                  | "KEYSPACE" ksname=<keyspaceName>?
 +                                  | ( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
 +                                  | "INDEX" idx=<indexName>
 +                                  | ( "COLUMNFAMILIES" | "TABLES" )
 +                                  | "FULL"? "SCHEMA"
 +                                  | "CLUSTER"
 +                                  | "TYPES"
 +                                  | "TYPE" ut=<userTypeName>
 +                                  | (ksname=<keyspaceName> | cf=<columnFamilyName> | idx=<indexName>))
 +                    ;
 +
 +<consistencyCommand> ::= "CONSISTENCY" ( level=<consistencyLevel> )?
 +                       ;
 +
 +<consistencyLevel> ::= "ANY"
 +                     | "ONE"
 +                     | "TWO"
 +                     | "THREE"
 +                     | "QUORUM"
 +                     | "ALL"
 +                     | "LOCAL_QUORUM"
 +                     | "EACH_QUORUM"
 +                     | "SERIAL"
 +                     | "LOCAL_SERIAL"
 +                     | "LOCAL_ONE"
 +                     ;
 +
 +<serialConsistencyCommand> ::= "SERIAL" "CONSISTENCY" ( level=<serialConsistencyLevel> )?
 +                             ;
 +
 +<serialConsistencyLevel> ::= "SERIAL"
 +                           | "LOCAL_SERIAL"
 +                           ;
 +
 +<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid=<uuid> )
 +                ;
 +
 +<sourceCommand> ::= "SOURCE" fname=<stringLiteral>
 +                  ;
 +
 +<captureCommand> ::= "CAPTURE" ( fname=( <stringLiteral> | "OFF" ) )?
 +                   ;
 +
 +<copyCommand> ::= "COPY" cf=<columnFamilyName>
 +                         ( "(" [colnames]=<colname> ( "," [colnames]=<colname> )* ")" )?
 +                         ( dir="FROM" ( fname=<stringLiteral> | "STDIN" )
 +                         | dir="TO"   ( fname=<stringLiteral> | "STDOUT" ) )
 +                         ( "WITH" <copyOption> ( "AND" <copyOption> )* )?
 +                ;
 +
 +<copyOption> ::= [optnames]=(<identifier>|<reserved_identifier>) "=" [optvals]=<copyOptionVal>
 +               ;
 +
 +<copyOptionVal> ::= <identifier>
 +                  | <reserved_identifier>
 +                  | <term>
 +                  ;
 +
 +# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal
 +<debugCommand> ::= "DEBUG" "THINGS"?
 +                 ;
 +
 +<helpCommand> ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )*
 +                ;
 +
 +<tracingCommand> ::= "TRACING" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<expandCommand> ::= "EXPAND" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<pagingCommand> ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )?
 +                  ;
 +
 +<loginCommand> ::= "LOGIN" username=<username> (password=<stringLiteral>)?
 +                 ;
 +
 +<exitCommand> ::= "exit" | "quit"
 +                ;
 +
 +<clearCommand> ::= "CLEAR" | "CLS"
 +                 ;
 +
 +<qmark> ::= "?" ;
 +'''
 +
 +
 +@cqlsh_syntax_completer('helpCommand', 'topic')
 +def complete_help(ctxt, cqlsh):
 +    return sorted([t.upper() for t in cqldocs.get_help_topics() + cqlsh.get_help_topics()])
 +
 +
 +def complete_source_quoted_filename(ctxt, cqlsh):
 +    partial_path = ctxt.get_binding('partial', '')
 +    head, tail = os.path.split(partial_path)
 +    exhead = os.path.expanduser(head)
 +    try:
 +        contents = os.listdir(exhead or '.')
 +    except OSError:
 +        return ()
 +    matches = filter(lambda f: f.startswith(tail), contents)
 +    annotated = []
 +    for f in matches:
 +        match = os.path.join(head, f)
 +        if os.path.isdir(os.path.join(exhead, f)):
 +            match += '/'
 +        annotated.append(match)
 +    return annotated
 +
 +
 +cqlsh_syntax_completer('sourceCommand', 'fname')(complete_source_quoted_filename)
 +cqlsh_syntax_completer('captureCommand', 'fname')(complete_source_quoted_filename)
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'fname')
 +def copy_fname_completer(ctxt, cqlsh):
 +    lasttype = ctxt.get_binding('*LASTTYPE*')
 +    if lasttype == 'unclosedString':
 +        return complete_source_quoted_filename(ctxt, cqlsh)
 +    partial_path = ctxt.get_binding('partial')
 +    if partial_path == '':
 +        return ["'"]
 +    return ()
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'colnames')
 +def complete_copy_column_names(ctxt, cqlsh):
 +    existcols = map(cqlsh.cql_unprotect_name, ctxt.get_binding('colnames', ()))
 +    ks = cqlsh.cql_unprotect_name(ctxt.get_binding('ksname', None))
 +    cf = cqlsh.cql_unprotect_name(ctxt.get_binding('cfname'))
 +    colnames = cqlsh.get_column_names(ks, cf)
 +    if len(existcols) == 0:
 +        return [colnames[0]]
 +    return set(colnames[1:]) - set(existcols)
 +
 +
 +COPY_COMMON_OPTIONS = ['DELIMITER', 'QUOTE', 'ESCAPE', 'HEADER', 'NULL', 'DATETIMEFORMAT',
 +                       'MAXATTEMPTS', 'REPORTFREQUENCY', 'DECIMALSEP', 'THOUSANDSSEP', 'BOOLSTYLE',
 +                       'NUMPROCESSES', 'CONFIGFILE', 'RATEFILE']
 +COPY_FROM_OPTIONS = ['CHUNKSIZE', 'INGESTRATE', 'MAXBATCHSIZE', 'MINBATCHSIZE', 'MAXROWS',
 +                     'SKIPROWS', 'SKIPCOLS', 'MAXPARSEERRORS', 'MAXINSERTERRORS', 'ERRFILE', 'PREPAREDSTATEMENTS']
 +COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS']
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optnames')
 +def complete_copy_options(ctxt, cqlsh):
 +    optnames = map(str.upper, ctxt.get_binding('optnames', ()))
 +    direction = ctxt.get_binding('dir').upper()
 +    if direction == 'FROM':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_FROM_OPTIONS) - set(optnames)
 +    elif direction == 'TO':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_TO_OPTIONS) - set(optnames)
 +    return opts
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optvals')
 +def complete_copy_opt_values(ctxt, cqlsh):
 +    optnames = ctxt.get_binding('optnames', ())
 +    lastopt = optnames[-1].lower()
 +    if lastopt == 'header':
 +        return ['true', 'false']
 +    return [cqlhandling.Hint('<single_character_string>')]
 +
 +
 +class NoKeyspaceError(Exception):
 +    pass
 +
 +
 +class KeyspaceNotFound(Exception):
 +    pass
 +
 +
 +class ColumnFamilyNotFound(Exception):
 +    pass
 +
 +
 +class IndexNotFound(Exception):
 +    pass
 +
 +
 +class ObjectNotFound(Exception):
 +    pass
 +
 +
 +class VersionNotSupported(Exception):
 +    pass
 +
 +
 +class UserTypeNotFound(Exception):
 +    pass
 +
 +
 +class FunctionNotFound(Exception):
 +    pass
 +
 +
 +class AggregateNotFound(Exception):
 +    pass
 +
 +
 +class DecodeError(Exception):
 +    verb = 'decode'
 +
 +    def __init__(self, thebytes, err, colname=None):
 +        self.thebytes = thebytes
 +        self.err = err
 +        self.colname = colname
 +
 +    def __str__(self):
 +        return str(self.thebytes)
 +
 +    def message(self):
 +        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 : %s' \
 +               % (self.verb, what, self.err)
 +
 +    def __repr__(self):
 +        return '<%s %s>' % (self.__class__.__name__, self.message())
 +
 +
 +class FormatError(DecodeError):
 +    verb = 'format'
 +
 +
 +def full_cql_version(ver):
 +    while ver.count('.') < 2:
 +        ver += '.0'
 +    ver_parts = ver.split('-', 1) + ['']
 +    vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
 +    return ver, vertuple
 +
 +
 +def format_value(val, output_encoding, addcolor=False, date_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))
 +    return format_by_type(type(val), val, output_encoding, colormap=colormap,
 +                          addcolor=addcolor, nullval=nullval, date_time_format=date_time_format,
 +                          float_precision=float_precision)
 +
 +
 +def show_warning_without_quoting_line(message, category, filename, lineno, file=None, line=None):
 +    if file is None:
 +        file = sys.stderr
 +    try:
 +        file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
 +    except IOError:
 +        pass
++
++
 +warnings.showwarning = show_warning_without_quoting_line
 +warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 +
 +
 +def insert_driver_hooks():
 +    extend_cql_deserialization()
 +    auto_format_udts()
 +
 +
 +def extend_cql_deserialization():
 +    """
 +    The python driver returns BLOBs as string, but we expect them as bytearrays; therefore we change
 +    the implementation of cassandra.cqltypes.BytesType.deserialize.
 +
 +    The deserializers package exists only when the driver has been compiled with cython extensions and
 +    cassandra.deserializers.DesBytesType replaces cassandra.cqltypes.BytesType.deserialize.
 +
 +    DesBytesTypeByteArray is a fast deserializer that converts blobs into bytearrays but it was
 +    only introduced recently (3.1.0). If it is available we use it, otherwise we remove
 +    cassandra.deserializers.DesBytesType so that we fall back onto cassandra.cqltypes.BytesType.deserialize
 +    just like in the case where no cython extensions are present.
 +    """
 +    if hasattr(cassandra, 'deserializers'):
 +        if hasattr(cassandra.deserializers, 'DesBytesTypeByteArray'):
 +            cassandra.deserializers.DesBytesType = cassandra.deserializers.DesBytesTypeByteArray
 +        else:
 +            del cassandra.deserializers.DesBytesType
 +
 +    cassandra.cqltypes.BytesType.deserialize = staticmethod(lambda byts, protocol_version: bytearray(byts))
 +    cassandra.cqltypes.CassandraType.support_empty_values = True
 +
 +
 +def auto_format_udts():
 +    # when we see a new user defined type, set up the shell formatting for it
 +    udt_apply_params = cassandra.cqltypes.UserType.apply_parameters
 +
 +    def new_apply_params(cls, *args, **kwargs):
 +        udt_class = udt_apply_params(*args, **kwargs)
 +        formatter_for(udt_class.typename)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.udt_apply_parameters = classmethod(new_apply_params)
 +
 +    make_udt_class = cassandra.cqltypes.UserType.make_udt_class
 +
 +    def new_make_udt_class(cls, *args, **kwargs):
 +        udt_class = make_udt_class(*args, **kwargs)
 +        formatter_for(udt_class.tuple_type.__name__)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.make_udt_class = classmethod(new_make_udt_class)
 +
 +
 +class FrozenType(cassandra.cqltypes._ParameterizedType):
 +    """
 +    Needed until the bundled python driver adds FrozenType.
 +    """
 +    typename = "frozen"
 +    num_subtypes = 1
 +
 +    @classmethod
 +    def deserialize_safe(cls, byts, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.from_binary(byts)
 +
 +    @classmethod
 +    def serialize_safe(cls, val, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.to_binary(val, protocol_version)
 +
 +
 +class Shell(cmd.Cmd):
 +    custom_prompt = os.getenv('CQLSH_PROMPT', '')
 +    if custom_prompt is not '':
 +        custom_prompt += "\n"
 +    default_prompt = custom_prompt + "cqlsh> "
 +    continue_prompt = "   ... "
 +    keyspace_prompt = custom_prompt + "cqlsh:%s> "
 +    keyspace_continue_prompt = "%s    ... "
 +    show_line_nums = False
 +    debug = False
 +    stop = False
 +    last_hist = None
 +    shunted_query_out = None
 +    use_paging = True
 +
 +    default_page_size = 100
 +
 +    def __init__(self, hostname, port, color=False,
 +                 username=None, password=None, encoding=None, stdin=None, tty=True,
 +                 completekey=DEFAULT_COMPLETEKEY, browser=None, use_conn=None,
 +                 cqlver=DEFAULT_CQLVER, keyspace=None,
 +                 tracing_enabled=False, expand_enabled=False,
 +                 display_nanotime_format=DEFAULT_NANOTIME_FORMAT,
 +                 display_timestamp_format=DEFAULT_TIMESTAMP_FORMAT,
 +                 display_date_format=DEFAULT_DATE_FORMAT,
 +                 display_float_precision=DEFAULT_FLOAT_PRECISION,
 +                 display_timezone=None,
 +                 max_trace_wait=DEFAULT_MAX_TRACE_WAIT,
 +                 ssl=False,
 +                 single_statement=None,
 +                 request_timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS,
 +                 protocol_version=DEFAULT_PROTOCOL_VERSION,
 +                 connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS):
 +        cmd.Cmd.__init__(self, completekey=completekey)
 +        self.hostname = hostname
 +        self.port = port
 +        self.auth_provider = None
 +        if username:
 +            if not password:
 +                password = getpass.getpass()
 +            self.auth_provider = PlainTextAuthProvider(username=username, password=password)
 +        self.username = username
 +        self.keyspace = keyspace
 +        self.ssl = ssl
 +        self.tracing_enabled = tracing_enabled
 +        self.page_size = self.default_page_size
 +        self.expand_enabled = expand_enabled
 +        if use_conn:
 +            self.conn = use_conn
 +        else:
 +            self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
 +                                protocol_version=protocol_version,
 +                                auth_provider=self.auth_provider,
 +                                ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,
 +                                load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                                control_connection_timeout=connect_timeout,
 +                                connect_timeout=connect_timeout)
 +        self.owns_connection = not use_conn
 +        self.set_expanded_cql_version(cqlver)
 +
 +        if keyspace:
 +            self.session = self.conn.connect(keyspace)
 +        else:
 +            self.session = self.conn.connect()
 +
 +        if browser == "":
 +            browser = None
 +        self.browser = browser
 +        self.color = color
 +
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_date_format = display_date_format
 +
 +        self.display_float_precision = display_float_precision
 +
 +        self.display_timezone = display_timezone
 +
 +        self.session.default_timeout = request_timeout
 +        self.session.row_factory = ordered_dict_factory
 +        self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.get_connection_versions()
 +
 +        self.current_keyspace = keyspace
 +
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_date_format = display_date_format
 +
 +        self.max_trace_wait = max_trace_wait
 +        self.session.max_trace_wait = max_trace_wait
 +
 +        self.tty = tty
 +        self.encoding = encoding
 +        self.check_windows_encoding()
 +
 +        self.output_codec = codecs.lookup(encoding)
 +
 +        self.statement = StringIO()
 +        self.lineno = 1
 +        self.in_comment = False
 +
 +        self.prompt = ''
 +        if stdin is None:
 +            stdin = sys.stdin
 +
 +        if tty:
 +            self.reset_prompt()
 +            self.report_connection()
 +            print 'Use HELP for help.'
 +        else:
 +            self.show_line_nums = True
 +        self.stdin = stdin
 +        self.query_out = sys.stdout
 +        self.consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.SERIAL
 +
 +        self.empty_lines = 0
 +        self.statement_error = False
 +        self.single_statement = single_statement
 +
 +    @property
 +    def is_using_utf8(self):
 +        # utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html
 +        return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8', CP65001]
 +
 +    def check_windows_encoding(self):
 +        if is_win and os.name == 'nt' and self.tty and \
 +           self.is_using_utf8 and sys.stdout.encoding != CP65001:
 +            self.printerr("\nWARNING: console codepage must be set to cp65001 "
 +                          "to support {} encoding on Windows platforms.\n"
 +                          "If you experience encoding problems, change your console"
 +                          " codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding))
 +
 +    def set_expanded_cql_version(self, ver):
 +        ver, vertuple = full_cql_version(ver)
 +        self.cql_version = ver
 +        self.cql_ver_tuple = vertuple
 +
 +    def cqlver_atleast(self, major, minor=0, patch=0):
 +        return self.cql_ver_tuple[:3] >= (major, minor, patch)
 +
 +    def myformat_value(self, val, **kwargs):
 +        if isinstance(val, DecodeError):
 +            self.decoding_errors.append(val)
 +        try:
 +            dtformats = DateTimeFormat(timestamp_format=self.display_timestamp_format,
 +                                       date_format=self.display_date_format, nanotime_format=self.display_nanotime_format,
 +                                       timezone=self.display_timezone)
 +            return format_value(val, self.output_codec.name,
 +                                addcolor=self.color, date_time_format=dtformats,
 +                                float_precision=self.display_float_precision, **kwargs)
 +        except Exception, e:
 +            err = FormatError(val, e)
 +            self.decoding_errors.append(err)
 +            return format_value(err, self.output_codec.name, addcolor=self.color)
 +
 +    def myformat_colname(self, name, table_meta=None):
 +        column_colors = COLUMN_NAME_COLORS.copy()
 +        # check column role and color appropriately
 +        if table_meta:
 +            if name in [col.name for col in table_meta.partition_key]:
 +                column_colors.default_factory = lambda: RED
 +            elif name in [col.name for col in table_meta.clustering_key]:
 +                column_colors.default_factory = lambda: CYAN
 +        return self.myformat_value(name, colormap=column_colors)
 +
 +    def report_connection(self):
 +        self.show_host()
 +        self.show_version()
 +
 +    def show_host(self):
 +        print "Connected to %s at %s:%d." % \
 +            (self.applycolor(self.get_cluster_name(), BLUE),
 +              self.hostname,
 +              self.port)
 +
 +    def show_version(self):
 +        vers = self.connection_versions.copy()
 +        vers['shver'] = version
 +        # 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 | Native protocol v%(protocol)s]" % vers
 +
 +    def show_session(self, sessionid, partial_session=False):
 +        print_trace_session(self, self.session, sessionid, partial_session)
 +
 +    def get_connection_versions(self):
 +        result, = self.session.execute("select * from system.local where key = 'local'")
 +        vers = {
 +            'build': result['release_version'],
 +            'protocol': result['native_protocol_version'],
 +            'cql': result['cql_version'],
 +        }
 +        self.connection_versions = vers
 +
 +    def get_keyspace_names(self):
 +        return map(str, self.conn.metadata.keyspaces.keys())
 +
 +    def get_columnfamily_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).tables.keys())
 +
 +    def get_index_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).indexes.keys())
 +
 +    def get_column_names(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        layout = self.get_table_meta(ksname, cfname)
 +        return [unicode(col) for col in layout.columns]
 +
 +    def get_usertype_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return self.get_keyspace_meta(ksname).user_types.keys()
 +
 +    def get_usertype_layout(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        ks_meta = self.get_keyspace_meta(ksname)
 +
 +        try:
 +            user_type = ks_meta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +
 +        return [(field_name, field_type.cql_parameterized_type())
 +                for field_name, field_type in zip(user_type.field_names, user_type.field_types)]
 +
 +    def get_userfunction_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).functions.values())
 +
 +    def get_useraggregate_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).aggregates.values())
 +
 +    def get_cluster_name(self):
 +        return self.conn.metadata.cluster_name
 +
 +    def get_partitioner(self):
 +        return self.conn.metadata.partitioner
 +
 +    def get_keyspace_meta(self, ksname):
 +        if ksname not in self.conn.metadata.keyspaces:
 +            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
 +        return self.conn.metadata.keyspaces[ksname]
 +
 +    def get_keyspaces(self):
 +        return self.conn.metadata.keyspaces.values()
 +
 +    def get_ring(self, ks):
 +        self.conn.metadata.token_map.rebuild_keyspace(ks, build_if_absent=True)
 +        return self.conn.metadata.token_map.tokens_to_hosts_by_ks[ks]
 +
 +    def get_table_meta(self, ksname, tablename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if tablename not in ksmeta.tables:
 +            if ksname == 'system_auth' and tablename in ['roles', 'role_permissions']:
 +                self.get_fake_auth_table_meta(ksname, tablename)
 +            else:
 +                raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +        else:
 +            return ksmeta.tables[tablename]
 +
 +    def get_fake_auth_table_meta(self, ksname, tablename):
 +        # may be using external auth implementation so internal tables
 +        # aren't actually defined in schema. In this case, we'll fake
 +        # them up
 +        if tablename == 'roles':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'roles')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['is_superuser'] = ColumnMetadata(table_meta, 'is_superuser', cassandra.cqltypes.BooleanType)
 +            table_meta.columns['can_login'] = ColumnMetadata(table_meta, 'can_login', cassandra.cqltypes.BooleanType)
 +        elif tablename == 'role_permissions':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'role_permissions')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['resource'] = ColumnMetadata(table_meta, 'resource', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['permission'] = ColumnMetadata(table_meta, 'permission', cassandra.cqltypes.UTF8Type)
 +        else:
 +            raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +
 +    def get_index_meta(self, ksname, idxname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if idxname not in ksmeta.indexes:
 +            raise IndexNotFound("Index %r not found" % idxname)
 +
 +        return ksmeta.indexes[idxname]
 +
 +    def get_object_meta(self, ks, name):
 +        if name is None:
 +            if ks and ks in self.conn.metadata.keyspaces:
 +                return self.conn.metadata.keyspaces[ks]
 +            elif self.current_keyspace is None:
 +                raise ObjectNotFound("%r not found in keyspaces" % (ks))
 +            else:
 +                name = ks
 +                ks = self.current_keyspace
 +
 +        if ks is None:
 +            ks = self.current_keyspace
 +
 +        ksmeta = self.get_keyspace_meta(ks)
 +
 +        if name in ksmeta.tables:
 +            return ksmeta.tables[name]
 +        elif name in ksmeta.indexes:
 +            return ksmeta.indexes[name]
 +
 +        raise ObjectNotFound("%r not found in keyspace %r" % (name, ks))
 +
 +    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)
 +
 +    def get_trigger_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return [trigger.name
 +                for table in self.get_keyspace_meta(ksname).tables.values()
 +                for trigger in table.triggers.values()]
 +
 +    def reset_statement(self):
 +        self.reset_prompt()
 +        self.statement.truncate(0)
 +        self.empty_lines = 0
 +
 +    def reset_prompt(self):
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.default_prompt, True)
 +        else:
 +            self.set_prompt(self.keyspace_prompt % self.current_keyspace, True)
 +
 +    def set_continue_prompt(self):
 +        if self.empty_lines >= 3:
 +            self.set_prompt("Statements are terminated with a ';'.  You can press CTRL-C to cancel an incomplete statement.")
 +            self.empty_lines = 0
 +            return
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.continue_prompt)
 +        else:
 +            spaces = ' ' * len(str(self.current_keyspace))
 +            self.set_prompt(self.keyspace_continue_prompt % spaces)
 +        self.empty_lines = self.empty_lines + 1 if not self.lastcmd else 0
 +
 +    @contextmanager
 +    def prepare_loop(self):
 +        readline = None
 +        if self.tty and self.completekey:
 +            try:
 +                import readline
 +            except ImportError:
 +                if is_win:
 +                    print "WARNING: pyreadline dependency missing.  Install to enable tab completion."
 +                pass
 +            else:
 +                old_completer = readline.get_completer()
 +                readline.set_completer(self.complete)
 +                if readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +                    readline.parse_and_bind("bind -e")
 +                    readline.parse_and_bind("bind '" + self.completekey + "' rl_complete")
 +                    readline.parse_and_bind("bind ^R em-inc-search-prev")
 +                else:
 +                    readline.parse_and_bind(self.completekey + ": complete")
 +        try:
 +            yield
 +        finally:
 +            if readline is not None:
 +                readline.set_completer(old_completer)
 +
 +    def get_input_line(self, prompt=''):
 +        if self.tty:
 +            try:
 +                self.lastcmd = raw_input(prompt).decode(self.encoding)
 +            except UnicodeDecodeError:
 +                self.lastcmd = ''
 +                traceback.print_exc()
 +                self.check_windows_encoding()
 +            line = self.lastcmd + '\n'
 +        else:
 +            self.lastcmd = self.stdin.readline()
 +            line = self.lastcmd
 +            if not len(line):
 +                raise EOFError
 +        self.lineno += 1
 +        return line
 +
 +    def use_stdin_reader(self, until='', prompt=''):
 +        until += '\n'
 +        while True:
 +            try:
 +                newline = self.get_input_line(prompt=prompt)
 +            except EOFError:
 +                return
 +            if newline == until:
 +                return
 +            yield newline
 +
 +    def cmdloop(self):
 +        """
 +        Adapted from cmd.Cmd's version, because there is literally no way with
 +        cmd.Cmd.cmdloop() to tell the difference between "EOF" showing up in
 +        input and an actual EOF.
 +        """
 +        with self.prepare_loop():
 +            while not self.stop:
 +                try:
 +                    if self.single_statement:
 +                        line = self.single_statement
 +                        self.stop = True
 +                    else:
 +                        line = self.get_input_line(self.prompt)
 +                    self.statement.write(line)
 +                    if self.onecmd(self.statement.getvalue()):
 +                        self.reset_statement()
 +                except EOFError:
 +                    self.handle_eof()
 +                except CQL_ERRORS, cqlerr:
 +                    self.printerr(cqlerr.message.decode(encoding='utf-8'))
 +                except KeyboardInterrupt:
 +                    self.reset_statement()
 +                    print
 +
 +    def onecmd(self, statementtext):
 +        """
 +        Returns true if the statement is complete and was handled (meaning it
 +        can be reset).
 +        """
 +
 +        try:
 +            statements, endtoken_escaped = cqlruleset.cql_split_statements(statementtext)
 +        except pylexotron.LexingError, e:
 +            if self.show_line_nums:
 +                self.printerr('Invalid syntax at char %d' % (e.charnum,))
 +            else:
 +                self.printerr('Invalid syntax at line %d, char %d'
 +                              % (e.linenum, e.charnum))
 +            statementline = statementtext.split('\n')[e.linenum - 1]
 +            self.printerr('  %s' % statementline)
 +            self.printerr(' %s^' % (' ' * e.charnum))
 +            return True
 +
 +        while statements and not statements[-1]:
 +            statements = statements[:-1]
 +        if not statements:
 +            return True
 +        if endtoken_escaped or statements[-1][-1][0] != 'endtoken':
 +            self.set_continue_prompt()
 +            return
 +        for st in statements:
 +            try:
 +                self.handle_statement(st, statementtext)
 +            except Exception, e:
 +                if self.debug:
 +                    traceback.print_exc()
 +                else:
 +                    self.printerr(e)
 +        return True
 +
 +    def handle_eof(self):
 +        if self.tty:
 +            print
 +        statement = self.statement.getvalue()
 +        if statement.strip():
 +            if not self.onecmd(statement):
 +                self.printerr('Incomplete statement at end of file')
 +        self.do_exit()
 +
 +    def handle_statement(self, tokens, srcstr):
 +        # Concat multi-line statements and insert into history
 +        if readline is not None:
 +            nl_count = srcstr.count("\n")
 +
 +            new_hist = srcstr.replace("\n", " ").rstrip()
 +
 +            if nl_count > 1 and self.last_hist != new_hist:
 +                readline.add_history(new_hist.encode(self.encoding))
 +
 +            self.last_hist = new_hist
 +        cmdword = tokens[0][1]
 +        if cmdword == '?':
 +            cmdword = 'help'
 +        custom_handler = getattr(self, 'do_' + cmdword.lower(), None)
 +        if custom_handler:
 +            parsed = cqlruleset.cql_whole_parse_tokens(tokens, srcstr=srcstr,
 +                                                       startsymbol='cqlshCommand')
 +            if parsed and not parsed.remainder:
 +                # successful complete parse
 +                return custom_handler(parsed)
 +            else:
 +                return self.handle_parse_error(cmdword, tokens, parsed, srcstr)
 +        return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +
 +    def handle_parse_error(self, cmdword, tokens, parsed, srcstr):
 +        if cmdword.lower() in ('select', 'insert', 'update', 'delete', 'truncate',
 +                               'create', 'drop', 'alter', 'grant', 'revoke',
 +                               'batch', 'list'):
 +            # hey, maybe they know about some new syntax we don't. type
 +            # assumptions won't work, but maybe the query will.
 +            return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +        if parsed:
 +            self.printerr('Improper %s command (problem at %r).' % (cmdword, parsed.remainder[0]))
 +        else:
 +            self.printerr('Improper %s command.' % cmdword)
 +
 +    def do_use(self, parsed):
 +        ksname = parsed.get_binding('ksname')
 +        success, _ = self.perform_simple_statement(SimpleStatement(parsed.extract_orig()))
 +        if success:
 +            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):
 +        tracing_was_enabled = self.tracing_enabled
 +        ksname = parsed.get_binding('ksname')
 +        stop_tracing = ksname == 'system_traces' or (ksname is None and self.current_keyspace == 'system_traces')
 +        self.tracing_enabled = self.tracing_enabled and not stop_tracing
 +        statement = parsed.extract_orig()
 +        self.perform_statement(statement)
 +        self.tracing_enabled = tracing_was_enabled
 +
 +    def perform_statement(self, statement):
 +        stmt = SimpleStatement(statement, consistency_level=self.consistency_level, serial_consistency_level=self.serial_consistency_level, fetch_size=self.page_size if self.use_paging else None)
 +        success, future = self.perform_simple_statement(stmt)
 +
 +        if future:
 +            if future.warnings:
 +                self.print_warnings(future.warnings)
 +
 +            if self.tracing_enabled:
 +                try:
 +                    for trace in future.get_all_query_traces(max_wait_per=self.max_trace_wait, query_cl=self.consistency_level):
 +                        print_trace(self, trace)
 +                except TraceUnavailable:
 +                    msg = "Statement trace did not complete within %d seconds; trace data may be incomplete." % (self.session.max_trace_wait,)
 +                    self.writeresult(msg, color=RED)
 +                    for trace_id in future.get_query_trace_ids():
 +                        self.show_session(trace_id, partial_session=True)
 +                except Exception, err:
 +                    self.printerr("Unable to fetch query trace: %s" % (str(err),))
 +
 +        return success
 +
 +    def parse_for_table_meta(self, query_string):
 +        try:
 +            parsed = cqlruleset.cql_parse(query_string)[1]
 +        except IndexError:
 +            return None
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        return self.get_table_meta(ks, cf)
 +
 +    def perform_simple_statement(self, statement):
 +        if not statement:
 +            return False, None
 +
 +        future = self.session.execute_async(statement, trace=self.tracing_enabled)
 +        result = None
 +        try:
 +            result = future.result()
 +        except CQL_ERRORS, err:
 +            self.printerr(unicode(err.__class__.__name__) + u": " + err.message.decode(encoding='utf-8'))
 +        except Exception:
 +            import traceback
 +            self.printerr(traceback.format_exc())
 +
 +        # Even if statement failed we try to refresh schema if not agreed (see CASSANDRA-9689)
 +        if not future.is_schema_agreed:
 +            try:
 +                self.conn.refresh_schema_metadata(5)  # will throw exception if there is a schema mismatch
 +            except Exception:
 +                self.printerr("Warning: schema version mismatch detected; check the schema versions of your "
 +                              "nodes in system.local and system.peers.")
 +                self.conn.refresh_schema_metadata(-1)
 +
 +        if result is None:
 +            return False, None
 +
 +        if statement.query_string[:6].lower() == 'select':
 +            self.print_result(result, self.parse_for_table_meta(statement.query_string))
 +        elif statement.query_string.lower().startswith("list users") or statement.query_string.lower().startswith("list roles"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'roles'))
 +        elif statement.query_string.lower().startswith("list"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'role_permissions'))
 +        elif result:
 +            # CAS INSERT/UPDATE
 +            self.writeresult("")
 +            self.print_static_result(result.column_names, list(result), self.parse_for_table_meta(statement.query_string))
 +        self.flush_output()
 +        return True, future
 +
 +    def print_result(self, result, table_meta):
 +        self.decoding_errors = []
 +
 +        self.writeresult("")
 +        if result.has_more_pages and self.tty:
 +            num_rows = 0
 +            while True:
 +                page = result.current_rows
 +                if page:
 +                    num_rows += len(page)
 +                    self.print_static_result(result.column_names, page, table_meta)
 +                if result.has_more_pages:
 +                    raw_input("---MORE---")
 +                    result.fetch_next_page()
 +                else:
 +                    break
 +        else:
 +            rows = list(result)
 +            num_rows = len(rows)
 +            self.print_static_result(result.column_names, rows, table_meta)
 +        self.writeresult("(%d rows)" % num_rows)
 +
 +        if self.decoding_errors:
 +            for err in self.decoding_errors[:2]:
 +                self.writeresult(err.message(), color=RED)
 +            if len(self.decoding_errors) > 2:
 +                self.writeresult('%d more decoding errors suppressed.'
 +                                 % (len(self.decoding_errors) - 2), color=RED)
 +
 +    def print_static_result(self, column_names, rows, table_meta):
 +        if not column_names and not table_meta:
 +            return
 +
 +        column_names = column_names or table_meta.columns.keys()
 +        formatted_names = [self.myformat_colname(name, table_meta) for name in column_names]
 +        if not rows:
 +            # print header only
 +            self.print_formatted_result(formatted_names, None)
 +            return
 +        formatted_values = [map(self.myformat_value, row.values()) for row in rows]
 +
 +        if self.expand_enabled:
 +            self.print_formatted_result_vertically(formatted_names, formatted_values)
 +        else:
 +            self.print_formatted_result(formatted_names, formatted_values)
 +
 +    def print_formatted_result(self, formatted_names, formatted_values):
 +        # determine column widths
 +        widths = [n.displaywidth for n in formatted_names]
 +        if formatted_values is not None:
 +            for fmtrow in formatted_values:
 +                for num, col in enumerate(fmtrow):
 +                    widths[num] = max(widths[num], col.displaywidth)
 +
 +        # print header
 +        header = ' | '.join(hdr.ljust(w, color=self.color) for (hdr, w) in zip(formatted_names, widths))
 +        self.writeresult(' ' + header.rstrip())
 +        self.writeresult('-%s-' % '-+-'.join('-' * w for w in widths))
 +
 +        # stop if there are no rows
 +        if formatted_values is None:
 +            self.writeresult("")
 +            return
 +
 +        # print row data
 +        for row in formatted_values:
 +            line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
 +            self.writeresult(' ' + line)
 +
 +        self.writeresult("")
 +
 +    def print_formatted_result_vertically(self, formatted_names, formatted_values):
 +        max_col_width = max([n.displaywidth for n in formatted_names])
 +        max_val_width = max([n.displaywidth for row in formatted_values for n in row])
 +
 +        # for each row returned, list all the column-value pairs
 +        for row_id, row in enumerate(formatted_values):
 +            self.writeresult("@ Row %d" % (row_id + 1))
 +            self.writeresult('-%s-' % '-+-'.join(['-' * max_col_width, '-' * max_val_width]))
 +            for field_id, field in enumerate(row):
 +                column = formatted_names[field_id].ljust(max_col_width, color=self.color)
 +                value = field.ljust(field.displaywidth, color=self.color)
 +                self.writeresult(' ' + " | ".join([column, value]))
 +            self.writeresult('')
 +
 +    def print_warnings(self, warnings):
 +        if warnings is None or len(warnings) == 0:
 +            return
 +
 +        self.writeresult('')
 +        self.writeresult('Warnings :')
 +        for warning in warnings:
 +            self.writeresult(warning)
 +            self.writeresult('')
 +
 +    def emptyline(self):
 +        pass
 +
 +    def parseline(self, line):
 +        # this shouldn't be needed
 +        raise NotImplementedError
 +
 +    def complete(self, text, state):
 +        if readline is None:
 +            return
 +        if state == 0:
 +            try:
 +                self.completion_matches = self.find_completions(text)
 +            except Exception:
 +                if debug_completion:
 +                    import traceback
 +                    traceback.print_exc()
 +                else:
 +                    raise
 +        try:
 +            return self.completion_matches[state]
 +        except IndexError:
 +            return None
 +
 +    def find_completions(self, text):
 +        curline = readline.get_line_buffer()
 +        prevlines = self.statement.getvalue()
 +        wholestmt = prevlines + curline
 +        begidx = readline.get_begidx() + len(prevlines)
 +        stuff_to_complete = wholestmt[:begidx]
 +        return cqlruleset.cql_complete(stuff_to_complete, text, cassandra_conn=self,
 +                                       debug=debug_completion, startsymbol='cqlshCommand')
 +
 +    def set_prompt(self, prompt, prepend_user=False):
 +        if prepend_user and self.username:
 +            self.prompt = "%s@%s" % (self.username, prompt)
 +            return
 +        self.prompt = prompt
 +
 +    def cql_unprotect_name(self, namestr):
 +        if namestr is None:
 +            return
 +        return cqlruleset.dequote_name(namestr)
 +
 +    def cql_unprotect_value(self, valstr):
 +        if valstr is not None:
 +            return cqlruleset.dequote_value(valstr)
 +
 +    def print_recreate_keyspace(self, ksdef, out):
 +        out.write(ksdef.export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_columnfamily(self, ksname, cfname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given table.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_table_meta(ksname, cfname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_index(self, ksname, idxname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given index.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_index_meta(ksname, idxname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_object(self, ks, name, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given object (ks, table or index).
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_object_meta(ks, name).export_as_string())
 +        out.write("\n")
 +
 +    def describe_keyspaces(self):
 +        print
 +        cmd.Cmd.columnize(self, protect_names(self.get_keyspace_names()))
 +        print
 +
 +    def describe_keyspace(self, ksname):
 +        print
 +        self.print_recreate_keyspace(self.get_keyspace_meta(ksname), sys.stdout)
 +        print
 +
 +    def describe_columnfamily(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        self.print_recreate_columnfamily(ksname, cfname, sys.stdout)
 +        print
 +
 +    def describe_index(self, ksname, idxname):
 +        print
 +        self.print_recreate_index(ksname, idxname, sys.stdout)
 +        print
 +
 +    def describe_object(self, ks, name):
 +        print
 +        self.print_recreate_object(ks, name, sys.stdout)
 +        print
 +
 +    def describe_columnfamilies(self, ksname):
 +        print
 +        if ksname is None:
 +            for k in self.get_keyspaces():
 +                name = protect_name(k.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(k.name)))
 +                print
 +        else:
 +            cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(ksname)))
 +            print
 +
 +    def describe_functions(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.functions.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.functions.keys())
 +
 +    def describe_function(self, ksname, functionname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        functions = filter(lambda f: f.name == functionname, ksmeta.functions.values())
 +        if len(functions) == 0:
 +            raise FunctionNotFound("User defined function %r not found" % functionname)
 +        print "\n\n".join(func.as_cql_query(formatted=True) for func in functions)
 +        print
 +
 +    def describe_aggregates(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.aggregates.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.aggregates.keys())
 +
 +    def describe_aggregate(self, ksname, aggregatename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        aggregates = filter(lambda f: f.name == aggregatename, ksmeta.aggregates.values())
 +        if len(aggregates) == 0:
 +            raise FunctionNotFound("User defined aggregate %r not found" % aggregatename)
 +        print "\n\n".join(aggr.as_cql_query(formatted=True) for aggr in aggregates)
 +        print
 +
 +    def describe_usertypes(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +
 +    def describe_usertype(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        try:
 +            usertype = ksmeta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +        print usertype.as_cql_query(formatted=True)
 +        print
 +
 +    def _columnize_unicode(self, name_list, quote=False):
 +        """
 +        Used when columnizing identifiers that may contain unicode
 +        """
 +        names = [n.encode('utf-8') for n in name_list]
 +        if quote:
 +            names = protect_names(names)
 +        cmd.Cmd.columnize(self, names)
 +        print
 +
 +    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\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(self.current_keyspace)
 +            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):
 +        print
 +        for k in self.get_keyspaces():
 +            if include_system or k.name not in cql3handling.SYSTEM_KEYSPACES:
 +                self.print_recreate_keyspace(k, sys.stdout)
 +                print
 +
 +    def do_describe(self, parsed):
 +        """
 +        DESCRIBE [cqlsh only]
 +
 +        (DESC may be used as a shorthand.)
 +
 +          Outputs information about the connected Cassandra cluster, or about
 +          the data objects stored in the cluster. Use in one of the following ways:
 +
 +        DESCRIBE KEYSPACES
 +
 +          Output the names of all keyspaces.
 +
 +        DESCRIBE KEYSPACE [<keyspacename>]
 +
 +          Output CQL commands that could be used to recreate the given keyspace,
 +          and the objects in it (such as tables, types, functions, etc.).
 +          In some cases, as the CQL interface matures, there will be some metadata
 +          about a keyspace that is not representable with CQL. That metadata will not be shown.
 +
 +          The '<keyspacename>' argument may be omitted, in which case the current
 +          keyspace will be described.
 +
 +        DESCRIBE TABLES
 +
 +          Output the names of all tables in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TABLE [<keyspace>.]<tablename>
 +
 +          Output CQL commands that could be used to recreate the given table.
 +          In some cases, as above, there may be table metadata which is not
 +          representable and which will not be shown.
 +
 +        DESCRIBE INDEX <indexname>
 +
 +          Output the CQL command that could be used to recreate the given index.
 +          In some cases, there may be index metadata which is not representable
 +          and which will not be shown.
 +
 +        DESCRIBE CLUSTER
 +
 +          Output information about the connected Cassandra cluster, such as the
 +          cluster name, and the partitioner and snitch in use. When you are
 +          connected to a non-system keyspace, also shows endpoint-range
 +          ownership information for the Cassandra ring.
 +
 +        DESCRIBE [FULL] SCHEMA
 +
 +          Output CQL commands that could be used to recreate the entire (non-system) schema.
 +          Works as though "DESCRIBE KEYSPACE k" was invoked for each non-system keyspace
 +          k. Use DESCRIBE FULL SCHEMA to include the system keyspaces.
 +
 +        DESCRIBE TYPES
 +
 +          Output the names of all user-defined-types in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TYPE [<keyspace>.]<type>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-type.
 +
 +        DESCRIBE FUNCTIONS
 +
 +          Output the names of all user-defined-functions in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE FUNCTION [<keyspace>.]<function>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-function.
 +
 +        DESCRIBE AGGREGATES
 +
 +          Output the names of all user-defined-aggregates in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE AGGREGATE [<keyspace>.]<aggregate>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-aggregate.
 +
 +        DESCRIBE <objname>
 +
 +          Output CQL commands that could be used to recreate the entire object schema,
 +          where object can be either a keyspace or a table or an index (in this order).
 +  """
 +        what = parsed.matched[1][1].lower()
 +        if what == 'functions':
 +            self.describe_functions(self.current_keyspace)
 +        elif what == 'function':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            functionname = self.cql_unprotect_name(parsed.get_binding('udfname'))
 +            self.describe_function(ksname, functionname)
 +        elif what == 'aggregates':
 +            self.describe_aggregates(self.current_keyspace)
 +        elif what == 'aggregate':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            aggregatename = self.cql_unprotect_name(parsed.get_binding('udaname'))
 +            self.describe_aggregate(ksname, aggregatename)
 +        elif what == 'keyspaces':
 +            self.describe_keyspaces()
 +        elif what == 'keyspace':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', ''))
 +            if not ksname:
 +                ksname = self.current_keyspace
 +                if ksname is None:
 +                    self.printerr('Not in any keyspace.')
 +                    return
 +            self.describe_keyspace(ksname)
 +        elif what in ('columnfamily', 'table'):
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            self.describe_columnfamily(ks, cf)
 +        elif what == 'index':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            idx = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_index(ks, idx)
 +        elif what in ('columnfamilies', 'tables'):
 +            self.describe_columnfamilies(self.current_keyspace)
 +        elif what == 'types':
 +            self.describe_usertypes(self.current_keyspace)
 +        elif what == 'type':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            ut = self.cql_unprotect_name(parsed.get_binding('utname'))
 +            self.describe_usertype(ks, ut)
 +        elif what == 'cluster':
 +            self.describe_cluster()
 +        elif what == 'schema':
 +            self.describe_schema(False)
 +        elif what == 'full' and parsed.matched[2][1].lower() == 'schema':
 +            self.describe_schema(True)
 +        elif what:
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            name = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            if not name:
 +                name = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_object(ks, name)
 +    do_desc = do_describe
 +
 +    def do_copy(self, parsed):
 +        r"""
 +        COPY [cqlsh only]
 +
 +          COPY x FROM: Imports CSV data into a Cassandra table
 +          COPY x TO: Exports data from a Cassandra table in CSV format.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             FROM ( '<file_pattern_1, file_pattern_2, ... file_pattern_n>' | STDIN )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        File patterns are either file names or valid python glob expressions, e.g. *.csv or folder/*.csv.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             TO ( '<filename>' | STDOUT )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        Available common COPY options and defaults:
 +
 +          DELIMITER=','           - character that appears between records
 +          QUOTE='"'               - quoting character to be used to quote fields
 +          ESCAPE='\'              - character to appear before the QUOTE char when quoted
 +          HEADER=false            - whether to ignore the first line
 +          NULL=''                 - string that represents a null value
 +          DATETIMEFORMAT=         - timestamp strftime format
 +            '%Y-%m-%d %H:%M:%S%z'   defaults to time_format value in cqlshrc
 +          MAXATTEMPTS=5           - the maximum number of attempts per batch or range
 +          REPORTFREQUENCY=0.25    - the frequency with which we display status updates in seconds
 +          DECIMALSEP='.'          - the separator for decimal values
 +          THOUSANDSSEP=''         - the separator for thousands digit groups
 +          BOOLSTYLE='True,False'  - the representation for booleans, case insensitive, specify true followed by false,
 +                                    for example yes,no or 1,0
 +          NUMPROCESSES=n          - the number of worker processes, by default the number of cores minus one
 +                                    capped at 16
 +          CONFIGFILE=''           - a configuration file with the same format as .cqlshrc (see the Python ConfigParser
 +                                    documentation) where you can specify WITH options under the following optional
 +                                    sections: [copy], [copy-to], [copy-from], [copy:ks.table], [copy-to:ks.table],
 +                                    [copy-from:ks.table], where <ks> is your keyspace name and <table> is your table
 +                                    name. Options are read from these sections, in the order specified
 +                                    above, and command line options always override options in configuration files.
 +                                    Depending on the COPY direction, only the relevant copy-from or copy-to sections
 +                                    are used. If no configfile is specified then .cqlshrc is searched instead.
 +          RATEFILE=''             - an optional file where to print the output statistics
 +
 +        Available COPY FROM options and defaults:
 +
 +          CHUNKSIZE=5000          - the size of chunks passed to worker processes
 +          INGESTRATE=100000       - an approximate ingest rate in rows per second
 +          MINBATCHSIZE=10         - the minimum size of an import batch
 +          MAXBATCHSIZE=20         - the maximum size of an import batch
 +          MAXROWS=-1              - the maximum number of rows, -1 means no maximum
 +          SKIPROWS=0              - the number of rows to skip
 +          SKIPCOLS=''             - a comma separated list of column names to skip
 +          MAXPARSEERRORS=-1       - the maximum global number of parsing errors, -1 means no maximum
 +          MAXINSERTERRORS=-1      - the maximum global number of insert errors, -1 means no maximum
 +          ERRFILE=''              - a file where to store all rows that could not be imported, by default this is
 +                                    import_ks_table.err where <ks> is your keyspace and <table> is your table name.
 +          PREPAREDSTATEMENTS=True - whether to use prepared statements when importing, by default True. Set this to
 +                                    False if you don't mind shifting data parsing to the cluster. The cluster will also
 +                                    have to compile every batch statement. For large and oversized clusters
 +                                    this will result in a faster import but for smaller clusters it may generate
 +                                    timeouts.
 +
 +        Available COPY TO options and defaults:
 +
 +          ENCODING='utf8'          - encoding for CSV output
 +          PAGESIZE='1000'          - the page size for fetching results
 +          PAGETIMEOUT=10           - the page timeout in seconds for fetching results
 +          BEGINTOKEN=''            - the minimum token string to consider when exporting data
 +          ENDTOKEN=''              - the maximum token string to consider when exporting data
 +          MAXREQUESTS=6            - the maximum number of requests each worker process can work on in parallel
 +          MAXOUTPUTSIZE='-1'       - the maximum size of the output file measured in number of lines,
 +                                     beyond this maximum the output file will be split into segments,
 +                                     -1 means unlimited.
 +
 +        When entering CSV data on STDIN, you can use the sequence "\."
 +        on a line by itself to end the data input.
 +        """
 +
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        if ks is None:
 +            ks = self.current_keyspace
 +            if ks is None:
 +                raise NoKeyspaceError("Not in any keyspace.")
 +        table = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        columns = parsed.get_binding('colnames', None)
 +        if columns is not None:
 +            columns = map(self.cql_unprotect_name, columns)
 +        else:
 +            # default to all known columns
 +            columns = self.get_column_names(ks, table)
 +
 +        fname = parsed.get_binding('fname', None)
 +        if fname is not None:
 +            fname = self.cql_unprotect_value(fname)
 +
 +        copyoptnames = map(str.lower, parsed.get_binding('optnames', ()))
 +        copyoptvals = map(self.cql_unprotect_value, parsed.get_binding('optvals', ()))
 +        opts = dict(zip(copyoptnames, copyoptvals))
 +
 +        direction = parsed.get_binding('dir').upper()
 +        if direction == 'FROM':
 +            task = ImportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        elif direction == 'TO':
 +            task = ExportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        else:
 +            raise SyntaxError("Unknown direction %s" % direction)
 +
 +        task.run()
 +
 +    def do_show(self, parsed):
 +        """
 +        SHOW [cqlsh only]
 +
 +          Displays information about the current cqlsh session. Can be called in
 +          the following ways:
 +
 +        SHOW VERSION
 +
 +          Shows the version and build of the connected Cassandra instance, as
 +          well as the versions of the CQL spec and the Thrift protocol that
 +          the connected Cassandra instance understands.
 +
 +        SHOW HOST
 +
 +          Shows where cqlsh is currently connected.
 +
 +        SHOW SESSION <sessionid>
 +
 +          Pretty-prints the requested tracing session.
 +        """
 +        showwhat = parsed.get_binding('what').lower()
 +        if showwhat == 'version':
 +            self.get_connection_versions()
 +            self.show_version()
 +        elif showwhat == 'host':
 +            self.show_host()
 +        elif showwhat.startswith('session'):
 +            session_id = parsed.get_binding('sessionid').lower()
 +            self.show_session(UUID(session_id))
 +        else:
 +            self.printerr('Wait, how do I show %r?' % (showwhat,))
 +
 +    def do_source(self, parsed):
 +        """
 +        SOURCE [cqlsh only]
 +
 +        Executes a file containing CQL statements. Gives the output for each
 +        statement in turn, if any, or any errors that occur along the way.
 +
 +        Errors do NOT abort execution of the CQL source file.
 +
 +        Usage:
 +
 +          SOURCE '<file>';
 +
 +        That is, the path to the file to be executed must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        See also the --file option to cqlsh.
 +        """
 +        fname = parsed.get_binding('fname')
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            encoding, bom_size = get_file_encoding_bomsize(fname)
 +            f = codecs.open(fname, 'r', encoding)
 +            f.seek(bom_size)
 +        except IOError, e:
 +            self.printerr('Could not open %r: %s' % (fname, e))
 +            return
 +        username = self.auth_provider.username if self.auth_provider else None
 +        password = self.auth_provider.password if self.auth_provider else None
 +        subshell = Shell(self.hostname, self.port, color=self.color,
 +                         username=username, password=password,
 +                         encoding=self.encoding, stdin=f, tty=False, use_conn=self.conn,
 +                         cqlver=self.cql_version, keyspace=self.current_keyspace,
 +                         tracing_enabled=self.tracing_enabled,
 +                         display_nanotime_format=self.display_nanotime_format,
 +                         display_timestamp_format=self.display_timestamp_format,
 +                         display_date_format=self.display_date_format,
 +                         display_float_precision=self.display_float_precision,
 +                         display_timezone=self.display_timezone,
 +                         max_trace_wait=self.max_trace_wait, ssl=self.ssl,
 +                         request_timeout=self.session.default_timeout,
 +                         connect_timeout=self.conn.connect_timeout)
 +        subshell.cmdloop()
 +        f.close()
 +
 +    def do_capture(self, parsed):
 +        """
 +        CAPTURE [cqlsh only]
 +
 +        Begins capturing command output and appending it to a specified file.
 +        Output will not be shown at the console while it is captured.
 +
 +        Usage:
 +
 +          CAPTURE '<file>';
 +          CAPTURE OFF;
 +          CAPTURE;
 +
 +        That is, the path to the file to be appended to must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        Only query result output is captured. Errors and output from cqlsh-only
 +        commands will still be shown in the cqlsh session.
 +
 +        To stop capturing output and show it in the cqlsh session again, use
 +        CAPTURE OFF.
 +
 +        To inspect the current capture configuration, use CAPTURE with no
 +        arguments.
 +        """
 +        fname = parsed.get_binding('fname')
 +        if fname is None:
 +            if self.shunted_query_out is not None:
 +                print "Currently capturing query output to %r." % (self.query_out.name,)
 +            else:
 +                print "Currently not capturing query output."
 +            return
 +
 +        if fname.upper() == 'OFF':
 +            if self.shunted_query_out is None:
 +                self.printerr('Not currently capturing output.')
 +                return
 +            self.query_out.close()
 +            self.query_out = self.shunted_query_out
 +            self.color = self.shunted_color
 +            self.shunted_query_out = None
 +            del self.shunted_color
 +            return
 +
 +        if self.shunted_query_out is not None:
 +            self.printerr('Already capturing output to %s. Use CAPTURE OFF'
 +                          ' to disable.' % (self.query_out.name,))
 +            return
 +
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            f = open(fname, 'a')
 +        except IOError, e:
 +            self.printerr('Could not open %r for append: %s' % (fname, e))
 +            return
 +        self.shunted_query_out = self.query_out
 +        self.shunted_color = self.color
 +        self.query_out = f
 +        self.color = False
 +        print 'Now capturing query output to %r.' % (fname,)
 +
 +    def do_tracing(self, parsed):
 +        """
 +        TRACING [cqlsh]
 +
 +          Enables or disables request tracing.
 +
 +        TRACING ON
 +
 +          Enables tracing for all further requests.
 +
 +        TRACING OFF
 +
 +          Disables tracing.
 +
 +        TRACING
 +
 +          TRACING with no arguments shows the current tracing status.
 +        """
 +        self.tracing_enabled = SwitchCommand("TRACING", "Tracing").execute(self.tracing_enabled, parsed, self.printerr)
 +
 +    def do_expand(self, parsed):
 +        """
 +        EXPAND [cqlsh]
 +
 +          Enables or disables expanded (vertical) output.
 +
 +        EXPAND ON
 +
 +          Enables expanded (vertical) output.
 +
 +        EXPAND OFF
 +
 +          Disables expanded (vertical) output.
 +
 +        EXPAND
 +
 +          EXPAND with no arguments shows the current value of expand setting.
 +        """
 +        self.expand_enabled = SwitchCommand("EXPAND", "Expanded output").execute(self.expand_enabled, parsed, self.printerr)
 +
 +    def do_consistency(self, parsed):
 +        """
 +        CONSISTENCY [cqlsh only]
 +
 +           Overrides default consistency level (default level is ONE).
 +
 +        CONSISTENCY <level>
 +
 +           Sets consistency level for future requests.
 +
 +           Valid consistency levels:
 +
 +           ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM, SERIAL and LOCAL_SERIAL.
 +
 +           SERIAL and LOCAL_SERIAL may be used only for SELECTs; will be rejected with updates.
 +
 +        CONSISTENCY
 +
 +           CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.consistency_level])
 +            return
 +
 +        self.consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Consistency level set to %s.' % (level.upper(),)
 +
 +    def do_serial(self, parsed):
 +        """
 +        SERIAL CONSISTENCY [cqlsh only]
 +
 +           Overrides serial consistency level (default level is SERIAL).
 +
 +        SERIAL CONSISTENCY <level>
 +
 +           Sets consistency level for future conditional updates.
 +
 +           Valid consistency levels:
 +
 +           SERIAL, LOCAL_SERIAL.
 +
 +        SERIAL CONSISTENCY
 +
 +           SERIAL CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current serial consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.serial_consistency_level])
 +            return
 +
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Serial consistency level set to %s.' % (level.upper(),)
 +
 +    def do_login(self, parsed):
 +        """
 +        LOGIN [cqlsh only]
 +
 +           Changes login information without requiring restart.
 +
 +        LOGIN <username> (<password>)
 +
 +           Login using the specified username. If password is specified, it will be used
 +           otherwise, you will be prompted to enter.
 +        """
 +        username = parsed.get_binding('username')
 +        password = parsed.get_binding('password')
 +        if password is None:
 +            password = getpass.getpass()
 +        else:
 +            password = password[1:-1]
 +
 +        auth_provider = PlainTextAuthProvider(username=username, password=password)
 +
 +        conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=self.conn.cql_version,
 +                       protocol_version=self.conn.protocol_version,
 +                       auth_provider=auth_provider,
 +                       ssl_options=self.conn.ssl_options,
 +                       load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                       control_connection_timeout=self.conn.connect_timeout,
 +                       connect_timeout=self.conn.connect_timeout)
 +
 +        if self.current_keyspace:
 +            session = conn.connect(self.current_keyspace)
 +        else:
 +            session = conn.connect()
 +
 +        # Copy session properties
 +        session.default_timeout = self.session.default_timeout
 +        session.row_factory = self.session.row_factory
 +        session.default_consistency_level = self.session.default_consistency_level
 +        session.max_trace_wait = self.session.max_trace_wait
 +
 +        # Update after we've connected in case we fail to authenticate
 +        self.conn = conn
 +        self.auth_provider = auth_provider
 +        self.username = username
 +        self.session = session
 +
 +    def do_exit(self, parsed=None):
 +        """
 +        EXIT/QUIT [cqlsh only]
 +
 +        Exits cqlsh.
 +        """
 +        self.stop = True
 +        if self.owns_connection:
 +            self.conn.shutdown()
 +    do_quit = do_exit
 +
 +    def do_clear(self, parsed):
 +        """
 +        CLEAR/CLS [cqlsh only]
 +
 +        Clears the console.
 +        """
 +        import subprocess
 +

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[19/23] cassandra git commit: Merge branch 'cassandra-2.2' into cassandra-3.0

Posted by ja...@apache.org.
Merge branch 'cassandra-2.2' into cassandra-3.0


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

Branch: refs/heads/cassandra-3.11
Commit: 685dde10e3a6b4a27936893840f536fa25ae9da5
Parents: 51bf518 503aec7
Author: Jason Brown <ja...@gmail.com>
Authored: Mon Jan 15 06:01:38 2018 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 06:03:22 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  3 ++-
 bin/cqlsh.py                   |  8 ++++++--
 pylib/cqlshlib/copyutil.py     |  8 ++++----
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 50 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/CHANGES.txt
----------------------------------------------------------------------
diff --cc CHANGES.txt
index 0453ddd,055a35d..8696653
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@@ -25,67 -2,11 +25,68 @@@ Merged from 2.2
   * Fix the inspectJvmOptions startup check (CASSANDRA-14112)
   * Fix race that prevents submitting compaction for a table when executor is full (CASSANDRA-13801)
   * Rely on the JVM to handle OutOfMemoryErrors (CASSANDRA-13006)
-- * Grab refs during scrub/index redistribution/cleanup (CASSANDRA-13873)
+ Merged from 2.1:
+  * More PEP8 compliance for cqlsh (CASSANDRA-14021)
  
 -2.2.11
 +
 +3.0.15
 + * Improve TRUNCATE performance (CASSANDRA-13909)
 + * Implement short read protection on partition boundaries (CASSANDRA-13595)
 + * Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)
 + * Filter header only commit logs before recovery (CASSANDRA-13918)
 + * AssertionError prepending to a list (CASSANDRA-13149)
 + * Fix support for SuperColumn tables (CASSANDRA-12373)
 + * Handle limit correctly on tables with strict liveness (CASSANDRA-13883)
 + * Fix missing original update in TriggerExecutor (CASSANDRA-13894)
 + * Remove non-rpc-ready nodes from counter leader candidates (CASSANDRA-13043)
 + * Improve short read protection performance (CASSANDRA-13794)
 + * Fix sstable reader to support range-tombstone-marker for multi-slices (CASSANDRA-13787)
 + * Fix short read protection for tables with no clustering columns (CASSANDRA-13880)
 + * Make isBuilt volatile in PartitionUpdate (CASSANDRA-13619)
 + * Prevent integer overflow of timestamps in CellTest and RowsTest (CASSANDRA-13866)
 + * Fix counter application order in short read protection (CASSANDRA-12872)
 + * Don't block RepairJob execution on validation futures (CASSANDRA-13797)
 + * Wait for all management tasks to complete before shutting down CLSM (CASSANDRA-13123)
 + * INSERT statement fails when Tuple type is used as clustering column with default DESC order (CASSANDRA-13717)
 + * Fix pending view mutations handling and cleanup batchlog when there are local and remote paired mutations (CASSANDRA-13069)
 + * Improve config validation and documentation on overflow and NPE (CASSANDRA-13622)
 + * Range deletes in a CAS batch are ignored (CASSANDRA-13655)
 + * Avoid assertion error when IndexSummary > 2G (CASSANDRA-12014)
 + * Change repair midpoint logging for tiny ranges (CASSANDRA-13603)
 + * Better handle corrupt final commitlog segment (CASSANDRA-11995)
 + * StreamingHistogram is not thread safe (CASSANDRA-13756)
 + * Fix MV timestamp issues (CASSANDRA-11500)
 + * Better tolerate improperly formatted bcrypt hashes (CASSANDRA-13626) 
 + * Fix race condition in read command serialization (CASSANDRA-13363)
 + * Enable segement creation before recovering commitlogs (CASSANDRA-13587)
 + * Fix AssertionError in short read protection (CASSANDRA-13747)
 + * Don't skip corrupted sstables on startup (CASSANDRA-13620)
 + * Fix the merging of cells with different user type versions (CASSANDRA-13776)
 + * Copy session properties on cqlsh.py do_login (CASSANDRA-13640)
 + * Potential AssertionError during ReadRepair of range tombstone and partition deletions (CASSANDRA-13719)
 + * Don't let stress write warmup data if n=0 (CASSANDRA-13773)
 + * Gossip thread slows down when using batch commit log (CASSANDRA-12966)
 + * Randomize batchlog endpoint selection with only 1 or 2 racks (CASSANDRA-12884)
 + * Fix digest calculation for counter cells (CASSANDRA-13750)
 + * Fix ColumnDefinition.cellValueType() for non-frozen collection and change SSTabledump to use type.toJSONString() (CASSANDRA-13573)
 + * Skip materialized view addition if the base table doesn't exist (CASSANDRA-13737)
 + * Drop table should remove corresponding entries in dropped_columns table (CASSANDRA-13730)
 + * Log warn message until legacy auth tables have been migrated (CASSANDRA-13371)
 + * Fix incorrect [2.1 <- 3.0] serialization of counter cells created in 2.0 (CASSANDRA-13691)
 + * Fix invalid writetime for null cells (CASSANDRA-13711)
 + * Fix ALTER TABLE statement to atomically propagate changes to the table and its MVs (CASSANDRA-12952)
 + * Fixed ambiguous output of nodetool tablestats command (CASSANDRA-13722)
 + * JMXEnabledThreadPoolExecutor with corePoolSize equal to maxPoolSize (Backport CASSANDRA-13329)
 + * Fix Digest mismatch Exception if hints file has UnknownColumnFamily (CASSANDRA-13696)
 + * Purge tombstones created by expired cells (CASSANDRA-13643)
 + * Make concat work with iterators that have different subsets of columns (CASSANDRA-13482)
 + * Set test.runners based on cores and memory size (CASSANDRA-13078)
 + * Allow different NUMACTL_ARGS to be passed in (CASSANDRA-13557)
 + * Allow native function calls in CQLSSTableWriter (CASSANDRA-12606)
 + * Fix secondary index queries on COMPACT tables (CASSANDRA-13627)
 + * Nodetool listsnapshots output is missing a newline, if there are no snapshots (CASSANDRA-13568)
 + * sstabledump reports incorrect usage for argument order (CASSANDRA-13532)
 +Merged from 2.2:
   * Safely handle empty buffers when outputting to JSON (CASSANDRA-13868)
   * Copy session properties on cqlsh.py do_login (CASSANDRA-13847)
   * Fix load over calculated issue in IndexSummaryRedistribution (CASSANDRA-13738)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/bin/cqlsh.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 2a8b560,8224ad9..0f42e6e
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,8 -34,9 +34,9 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
 -NONALTERBALE_KEYSPACES = ('system')
 +SYSTEM_KEYSPACES = ('system', 'system_schema', 'system_traces', 'system_auth', 'system_distributed')
 +NONALTERBALE_KEYSPACES = ('system', 'system_schema')
  
  
  class Cql3ParsingRuleSet(CqlParsingRuleSet):
@@@ -579,8 -571,8 +582,9 @@@ def ks_name_completer(ctxt, cass)
  def cf_ks_name_completer(ctxt, cass):
      return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
  
+ 
  completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 +completer_for('materializedViewName', 'ksname')(cf_ks_name_completer)
  
  
  def cf_ks_dot_completer(ctxt, cass):
@@@ -589,8 -581,8 +593,9 @@@
          return ['.']
      return []
  
+ 
  completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 +completer_for('materializedViewName', 'dot')(cf_ks_dot_completer)
  
  
  @completer_for('columnFamilyName', 'cfname')
@@@ -607,19 -599,6 +612,20 @@@ def cf_name_completer(ctxt, cass)
      return map(maybe_escape_name, cfnames)
  
  
 +@completer_for('materializedViewName', 'mvname')
 +def mv_name_completer(ctxt, cass):
 +    ks = ctxt.get_binding('ksname', None)
 +    if ks is not None:
 +        ks = dequote_name(ks)
 +    try:
 +        mvnames = cass.get_materialized_view_names(ks)
 +    except Exception:
 +        if ks is None:
 +            return ()
 +        raise
 +    return map(maybe_escape_name, mvnames)
 +
++
  completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
  
  completer_for('userTypeName', 'dot')(cf_ks_dot_completer)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/685dde10/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[10/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/bin/cqlsh.py
----------------------------------------------------------------------
diff --cc bin/cqlsh.py
index 1f63826,0000000..e242d42
mode 100644,000000..100644
--- a/bin/cqlsh.py
+++ b/bin/cqlsh.py
@@@ -1,2588 -1,0 +1,2592 @@@
 +#!/bin/sh
 +# -*- mode: Python -*-
 +
 +# 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.
 +
 +""":"
 +# bash code here; finds a suitable python interpreter and execs this file.
 +# prefer unqualified "python" if suitable:
 +python -c 'import sys; sys.exit(not (0x020700b0 < sys.hexversion < 0x03000000))' 2>/dev/null \
 +    && exec python "$0" "$@"
 +for pyver in 2.7; do
 +    which python$pyver > /dev/null 2>&1 && exec python$pyver "$0" "$@"
 +done
 +echo "No appropriate python interpreter found." >&2
 +exit 1
 +":"""
 +
 +from __future__ import with_statement
 +
 +import cmd
 +import codecs
 +import ConfigParser
 +import csv
 +import getpass
 +import optparse
 +import os
 +import platform
 +import sys
 +import traceback
 +import warnings
 +import webbrowser
 +from StringIO import StringIO
 +from contextlib import contextmanager
 +from glob import glob
 +from uuid import UUID
 +
 +if sys.version_info[0] != 2 or sys.version_info[1] != 7:
 +    sys.exit("\nCQL Shell supports only Python 2.7\n")
 +
 +UTF8 = 'utf-8'
 +CP65001 = 'cp65001'  # Win utf-8 variant
 +
 +description = "CQL Shell for Apache Cassandra"
 +version = "5.0.1"
 +
 +readline = None
 +try:
 +    # check if tty first, cause readline doesn't check, and only cares
 +    # about $TERM. we don't want the funky escape code stuff to be
 +    # output if not a tty.
 +    if sys.stdin.isatty():
 +        import readline
 +except ImportError:
 +    pass
 +
 +CQL_LIB_PREFIX = 'cassandra-driver-internal-only-'
 +
 +CASSANDRA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
 +CASSANDRA_CQL_HTML_FALLBACK = 'https://cassandra.apache.org/doc/cql3/CQL-2.2.html'
 +
 +if os.path.exists(CASSANDRA_PATH + '/doc/cql3/CQL.html'):
 +    # default location of local CQL.html
 +    CASSANDRA_CQL_HTML = 'file://' + CASSANDRA_PATH + '/doc/cql3/CQL.html'
 +elif os.path.exists('/usr/share/doc/cassandra/CQL.html'):
 +    # fallback to package file
 +    CASSANDRA_CQL_HTML = 'file:///usr/share/doc/cassandra/CQL.html'
 +else:
 +    # fallback to online version
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +
 +# On Linux, the Python webbrowser module uses the 'xdg-open' executable
 +# to open a file/URL. But that only works, if the current session has been
 +# opened from _within_ a desktop environment. I.e. 'xdg-open' will fail,
 +# if the session's been opened via ssh to a remote box.
 +#
 +# Use 'python' to get some information about the detected browsers.
 +# >>> import webbrowser
 +# >>> webbrowser._tryorder
 +# >>> webbrowser._browser
 +#
 +if len(webbrowser._tryorder) == 0:
 +    CASSANDRA_CQL_HTML = CASSANDRA_CQL_HTML_FALLBACK
 +elif webbrowser._tryorder[0] == 'xdg-open' and os.environ.get('XDG_DATA_DIRS', '') == '':
 +    # only on Linux (some OS with xdg-open)
 +    webbrowser._tryorder.remove('xdg-open')
 +    webbrowser._tryorder.append('xdg-open')
 +
 +# use bundled libs for python-cql and thrift, if available. if there
 +# is a ../lib dir, use bundled libs there preferentially.
 +ZIPLIB_DIRS = [os.path.join(CASSANDRA_PATH, 'lib')]
 +myplatform = platform.system()
 +is_win = myplatform == 'Windows'
 +
 +# Workaround for supporting CP65001 encoding on python < 3.3 (https://bugs.python.org/issue13216)
 +if is_win and sys.version_info < (3, 3):
 +    codecs.register(lambda name: codecs.lookup(UTF8) if name == CP65001 else None)
 +
 +if myplatform == 'Linux':
 +    ZIPLIB_DIRS.append('/usr/share/cassandra/lib')
 +
 +if os.environ.get('CQLSH_NO_BUNDLED', ''):
 +    ZIPLIB_DIRS = ()
 +
 +
 +def find_zip(libprefix):
 +    for ziplibdir in ZIPLIB_DIRS:
 +        zips = glob(os.path.join(ziplibdir, libprefix + '*.zip'))
 +        if zips:
 +            return max(zips)   # probably the highest version, if multiple
 +
++
 +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, 'cassandra-driver-' + ver))
 +
 +third_parties = ('futures-', 'six-')
 +
 +for lib in third_parties:
 +    lib_zip = find_zip(lib)
 +    if lib_zip:
 +        sys.path.insert(0, lib_zip)
 +
 +warnings.filterwarnings("ignore", r".*blist.*")
 +try:
 +    import cassandra
 +except ImportError, e:
 +    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))
 +
 +from cassandra.auth import PlainTextAuthProvider
 +from cassandra.cluster import Cluster
 +from cassandra.metadata import (ColumnMetadata, KeyspaceMetadata,
 +                                TableMetadata, protect_name, protect_names)
 +from cassandra.policies import WhiteListRoundRobinPolicy
 +from cassandra.query import SimpleStatement, ordered_dict_factory, TraceUnavailable
 +
 +# cqlsh should run correctly when run out of a Cassandra source tree,
 +# out of an unpacked Cassandra tarball, and after a proper package install.
 +cqlshlibdir = os.path.join(CASSANDRA_PATH, 'pylib')
 +if os.path.isdir(cqlshlibdir):
 +    sys.path.insert(0, cqlshlibdir)
 +
 +from cqlshlib import cql3handling, cqlhandling, pylexotron, sslhandling
 +from cqlshlib.copyutil import ExportTask, ImportTask
 +from cqlshlib.displaying import (ANSI_RESET, BLUE, COLUMN_NAME_COLORS, CYAN,
 +                                 RED, FormattedValue, colorme)
 +from cqlshlib.formatting import (DEFAULT_DATE_FORMAT, DEFAULT_NANOTIME_FORMAT,
 +                                 DEFAULT_TIMESTAMP_FORMAT, DateTimeFormat,
 +                                 format_by_type, format_value_utype,
 +                                 formatter_for)
 +from cqlshlib.tracing import print_trace, print_trace_session
 +from cqlshlib.util import get_file_encoding_bomsize, trim_if_present
 +
 +DEFAULT_HOST = '127.0.0.1'
 +DEFAULT_PORT = 9042
 +DEFAULT_CQLVER = '3.3.1'
 +DEFAULT_PROTOCOL_VERSION = 4
 +DEFAULT_CONNECT_TIMEOUT_SECONDS = 5
 +DEFAULT_REQUEST_TIMEOUT_SECONDS = 10
 +
 +DEFAULT_FLOAT_PRECISION = 5
 +DEFAULT_MAX_TRACE_WAIT = 10
 +
 +if readline is not None and readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +    DEFAULT_COMPLETEKEY = '\t'
 +else:
 +    DEFAULT_COMPLETEKEY = 'tab'
 +
 +cqldocs = None
 +cqlruleset = None
 +
 +epilog = """Connects to %(DEFAULT_HOST)s:%(DEFAULT_PORT)d by default. These
 +defaults can be changed by setting $CQLSH_HOST and/or $CQLSH_PORT. When a
 +host (and optional port number) are given on the command line, they take
 +precedence over any defaults.""" % globals()
 +
 +parser = optparse.OptionParser(description=description, epilog=epilog,
 +                               usage="Usage: %prog [options] [host [port]]",
 +                               version='cqlsh ' + version)
 +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("--browser", dest='browser', help="""The browser to use to display CQL help, where BROWSER can be:
 +                                                    - one of the supported browsers in https://docs.python.org/2/library/webbrowser.html.
 +                                                    - browser path followed by %s, example: /usr/bin/google-chrome-stable %s""")
 +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('--debug', action='store_true',
 +                  help='Show additional debugging information')
 +parser.add_option("--encoding", help="Specify a non-default encoding for output." +
 +                  " (Default: %s)" % (UTF8,))
 +parser.add_option("--cqlshrc", help="Specify an alternative cqlshrc file location.")
 +parser.add_option('--cqlversion', default=DEFAULT_CQLVER,
 +                  help='Specify a particular CQL version (default: %default).'
 +                       ' Examples: "3.0.3", "3.1.0"')
 +parser.add_option("-e", "--execute", help='Execute the statement and quit.')
 +parser.add_option("--connect-timeout", default=DEFAULT_CONNECT_TIMEOUT_SECONDS, dest='connect_timeout',
 +                  help='Specify the connection timeout in seconds (default: %default seconds).')
 +parser.add_option("--request-timeout", default=DEFAULT_REQUEST_TIMEOUT_SECONDS, dest='request_timeout',
 +                  help='Specify the default request timeout in seconds (default: %default seconds).')
 +parser.add_option("-t", "--tty", action='store_true', dest='tty',
 +                  help='Force tty mode (command prompt).')
 +
 +optvalues = optparse.Values()
 +(options, arguments) = parser.parse_args(sys.argv[1:], values=optvalues)
 +
 +# BEGIN history/config definition
 +HISTORY_DIR = os.path.expanduser(os.path.join('~', '.cassandra'))
 +
 +if hasattr(options, 'cqlshrc'):
 +    CONFIG_FILE = options.cqlshrc
 +    if not os.path.exists(CONFIG_FILE):
 +        print '\nWarning: Specified cqlshrc location `%s` does not exist.  Using `%s` instead.\n' % (CONFIG_FILE, HISTORY_DIR)
 +        CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +else:
 +    CONFIG_FILE = os.path.join(HISTORY_DIR, 'cqlshrc')
 +
 +HISTORY = os.path.join(HISTORY_DIR, 'cqlsh_history')
 +if not os.path.exists(HISTORY_DIR):
 +    try:
 +        os.mkdir(HISTORY_DIR)
 +    except OSError:
 +        print '\nWarning: Cannot create directory at `%s`. Command history will not be saved.\n' % HISTORY_DIR
 +
 +OLD_CONFIG_FILE = os.path.expanduser(os.path.join('~', '.cqlshrc'))
 +if os.path.exists(OLD_CONFIG_FILE):
 +    if os.path.exists(CONFIG_FILE):
 +        print '\nWarning: cqlshrc config files were found at both the old location (%s) and \
 +                the new location (%s), the old config file will not be migrated to the new \
 +                location, and the new location will be used for now.  You should manually \
 +                consolidate the config files at the new location and remove the old file.' \
 +                % (OLD_CONFIG_FILE, CONFIG_FILE)
 +    else:
 +        os.rename(OLD_CONFIG_FILE, CONFIG_FILE)
 +OLD_HISTORY = os.path.expanduser(os.path.join('~', '.cqlsh_history'))
 +if os.path.exists(OLD_HISTORY):
 +    os.rename(OLD_HISTORY, HISTORY)
 +# END history/config definition
 +
 +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.protocol.ErrorMessage, cassandra.protocol.InternalError, cassandra.query.TraceUnavailable
 +)
 +
 +debug_completion = bool(os.environ.get('CQLSH_DEBUG_COMPLETION', '') == 'YES')
 +
 +# we want the cql parser to understand our cqlsh-specific commands too
 +my_commands_ending_with_newline = (
 +    'help',
 +    '?',
 +    'consistency',
 +    'serial',
 +    'describe',
 +    'desc',
 +    'show',
 +    'source',
 +    'capture',
 +    'login',
 +    'debug',
 +    'tracing',
 +    'expand',
 +    'paging',
 +    'exit',
 +    'quit',
 +    'clear',
 +    'cls'
 +)
 +
 +
 +cqlsh_syntax_completers = []
 +
 +
 +def cqlsh_syntax_completer(rulename, termname):
 +    def registrator(f):
 +        cqlsh_syntax_completers.append((rulename, termname, f))
 +        return f
 +    return registrator
 +
 +
 +cqlsh_extra_syntax_rules = r'''
 +<cqlshCommand> ::= <CQL_Statement>
 +                 | <specialCommand> ( ";" | "\n" )
 +                 ;
 +
 +<specialCommand> ::= <describeCommand>
 +                   | <consistencyCommand>
 +                   | <serialConsistencyCommand>
 +                   | <showCommand>
 +                   | <sourceCommand>
 +                   | <captureCommand>
 +                   | <copyCommand>
 +                   | <loginCommand>
 +                   | <debugCommand>
 +                   | <helpCommand>
 +                   | <tracingCommand>
 +                   | <expandCommand>
 +                   | <exitCommand>
 +                   | <pagingCommand>
 +                   | <clearCommand>
 +                   ;
 +
 +<describeCommand> ::= ( "DESCRIBE" | "DESC" )
 +                                  ( "FUNCTIONS"
 +                                  | "FUNCTION" udf=<anyFunctionName>
 +                                  | "AGGREGATES"
 +                                  | "AGGREGATE" uda=<userAggregateName>
 +                                  | "KEYSPACES"
 +                                  | "KEYSPACE" ksname=<keyspaceName>?
 +                                  | ( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
 +                                  | "INDEX" idx=<indexName>
 +                                  | ( "COLUMNFAMILIES" | "TABLES" )
 +                                  | "FULL"? "SCHEMA"
 +                                  | "CLUSTER"
 +                                  | "TYPES"
 +                                  | "TYPE" ut=<userTypeName>
 +                                  | (ksname=<keyspaceName> | cf=<columnFamilyName> | idx=<indexName>))
 +                    ;
 +
 +<consistencyCommand> ::= "CONSISTENCY" ( level=<consistencyLevel> )?
 +                       ;
 +
 +<consistencyLevel> ::= "ANY"
 +                     | "ONE"
 +                     | "TWO"
 +                     | "THREE"
 +                     | "QUORUM"
 +                     | "ALL"
 +                     | "LOCAL_QUORUM"
 +                     | "EACH_QUORUM"
 +                     | "SERIAL"
 +                     | "LOCAL_SERIAL"
 +                     | "LOCAL_ONE"
 +                     ;
 +
 +<serialConsistencyCommand> ::= "SERIAL" "CONSISTENCY" ( level=<serialConsistencyLevel> )?
 +                             ;
 +
 +<serialConsistencyLevel> ::= "SERIAL"
 +                           | "LOCAL_SERIAL"
 +                           ;
 +
 +<showCommand> ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid=<uuid> )
 +                ;
 +
 +<sourceCommand> ::= "SOURCE" fname=<stringLiteral>
 +                  ;
 +
 +<captureCommand> ::= "CAPTURE" ( fname=( <stringLiteral> | "OFF" ) )?
 +                   ;
 +
 +<copyCommand> ::= "COPY" cf=<columnFamilyName>
 +                         ( "(" [colnames]=<colname> ( "," [colnames]=<colname> )* ")" )?
 +                         ( dir="FROM" ( fname=<stringLiteral> | "STDIN" )
 +                         | dir="TO"   ( fname=<stringLiteral> | "STDOUT" ) )
 +                         ( "WITH" <copyOption> ( "AND" <copyOption> )* )?
 +                ;
 +
 +<copyOption> ::= [optnames]=(<identifier>|<reserved_identifier>) "=" [optvals]=<copyOptionVal>
 +               ;
 +
 +<copyOptionVal> ::= <identifier>
 +                  | <reserved_identifier>
 +                  | <term>
 +                  ;
 +
 +# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal
 +<debugCommand> ::= "DEBUG" "THINGS"?
 +                 ;
 +
 +<helpCommand> ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )*
 +                ;
 +
 +<tracingCommand> ::= "TRACING" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<expandCommand> ::= "EXPAND" ( switch=( "ON" | "OFF" ) )?
 +                   ;
 +
 +<pagingCommand> ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )?
 +                  ;
 +
 +<loginCommand> ::= "LOGIN" username=<username> (password=<stringLiteral>)?
 +                 ;
 +
 +<exitCommand> ::= "exit" | "quit"
 +                ;
 +
 +<clearCommand> ::= "CLEAR" | "CLS"
 +                 ;
 +
 +<qmark> ::= "?" ;
 +'''
 +
 +
 +@cqlsh_syntax_completer('helpCommand', 'topic')
 +def complete_help(ctxt, cqlsh):
 +    return sorted([t.upper() for t in cqldocs.get_help_topics() + cqlsh.get_help_topics()])
 +
 +
 +def complete_source_quoted_filename(ctxt, cqlsh):
 +    partial_path = ctxt.get_binding('partial', '')
 +    head, tail = os.path.split(partial_path)
 +    exhead = os.path.expanduser(head)
 +    try:
 +        contents = os.listdir(exhead or '.')
 +    except OSError:
 +        return ()
 +    matches = filter(lambda f: f.startswith(tail), contents)
 +    annotated = []
 +    for f in matches:
 +        match = os.path.join(head, f)
 +        if os.path.isdir(os.path.join(exhead, f)):
 +            match += '/'
 +        annotated.append(match)
 +    return annotated
 +
 +
 +cqlsh_syntax_completer('sourceCommand', 'fname')(complete_source_quoted_filename)
 +cqlsh_syntax_completer('captureCommand', 'fname')(complete_source_quoted_filename)
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'fname')
 +def copy_fname_completer(ctxt, cqlsh):
 +    lasttype = ctxt.get_binding('*LASTTYPE*')
 +    if lasttype == 'unclosedString':
 +        return complete_source_quoted_filename(ctxt, cqlsh)
 +    partial_path = ctxt.get_binding('partial')
 +    if partial_path == '':
 +        return ["'"]
 +    return ()
 +
 +
 +@cqlsh_syntax_completer('copyCommand', 'colnames')
 +def complete_copy_column_names(ctxt, cqlsh):
 +    existcols = map(cqlsh.cql_unprotect_name, ctxt.get_binding('colnames', ()))
 +    ks = cqlsh.cql_unprotect_name(ctxt.get_binding('ksname', None))
 +    cf = cqlsh.cql_unprotect_name(ctxt.get_binding('cfname'))
 +    colnames = cqlsh.get_column_names(ks, cf)
 +    if len(existcols) == 0:
 +        return [colnames[0]]
 +    return set(colnames[1:]) - set(existcols)
 +
 +
 +COPY_COMMON_OPTIONS = ['DELIMITER', 'QUOTE', 'ESCAPE', 'HEADER', 'NULL', 'DATETIMEFORMAT',
 +                       'MAXATTEMPTS', 'REPORTFREQUENCY', 'DECIMALSEP', 'THOUSANDSSEP', 'BOOLSTYLE',
 +                       'NUMPROCESSES', 'CONFIGFILE', 'RATEFILE']
 +COPY_FROM_OPTIONS = ['CHUNKSIZE', 'INGESTRATE', 'MAXBATCHSIZE', 'MINBATCHSIZE', 'MAXROWS',
 +                     'SKIPROWS', 'SKIPCOLS', 'MAXPARSEERRORS', 'MAXINSERTERRORS', 'ERRFILE', 'PREPAREDSTATEMENTS']
 +COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS']
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optnames')
 +def complete_copy_options(ctxt, cqlsh):
 +    optnames = map(str.upper, ctxt.get_binding('optnames', ()))
 +    direction = ctxt.get_binding('dir').upper()
 +    if direction == 'FROM':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_FROM_OPTIONS) - set(optnames)
 +    elif direction == 'TO':
 +        opts = set(COPY_COMMON_OPTIONS + COPY_TO_OPTIONS) - set(optnames)
 +    return opts
 +
 +
 +@cqlsh_syntax_completer('copyOption', 'optvals')
 +def complete_copy_opt_values(ctxt, cqlsh):
 +    optnames = ctxt.get_binding('optnames', ())
 +    lastopt = optnames[-1].lower()
 +    if lastopt == 'header':
 +        return ['true', 'false']
 +    return [cqlhandling.Hint('<single_character_string>')]
 +
 +
 +class NoKeyspaceError(Exception):
 +    pass
 +
 +
 +class KeyspaceNotFound(Exception):
 +    pass
 +
 +
 +class ColumnFamilyNotFound(Exception):
 +    pass
 +
 +
 +class IndexNotFound(Exception):
 +    pass
 +
 +
 +class ObjectNotFound(Exception):
 +    pass
 +
 +
 +class VersionNotSupported(Exception):
 +    pass
 +
 +
 +class UserTypeNotFound(Exception):
 +    pass
 +
 +
 +class FunctionNotFound(Exception):
 +    pass
 +
 +
 +class AggregateNotFound(Exception):
 +    pass
 +
 +
 +class DecodeError(Exception):
 +    verb = 'decode'
 +
 +    def __init__(self, thebytes, err, colname=None):
 +        self.thebytes = thebytes
 +        self.err = err
 +        self.colname = colname
 +
 +    def __str__(self):
 +        return str(self.thebytes)
 +
 +    def message(self):
 +        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 : %s' \
 +               % (self.verb, what, self.err)
 +
 +    def __repr__(self):
 +        return '<%s %s>' % (self.__class__.__name__, self.message())
 +
 +
 +class FormatError(DecodeError):
 +    verb = 'format'
 +
 +
 +def full_cql_version(ver):
 +    while ver.count('.') < 2:
 +        ver += '.0'
 +    ver_parts = ver.split('-', 1) + ['']
 +    vertuple = tuple(map(int, ver_parts[0].split('.')) + [ver_parts[1]])
 +    return ver, vertuple
 +
 +
 +def format_value(val, output_encoding, addcolor=False, date_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))
 +    return format_by_type(type(val), val, output_encoding, colormap=colormap,
 +                          addcolor=addcolor, nullval=nullval, date_time_format=date_time_format,
 +                          float_precision=float_precision)
 +
 +
 +def show_warning_without_quoting_line(message, category, filename, lineno, file=None, line=None):
 +    if file is None:
 +        file = sys.stderr
 +    try:
 +        file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
 +    except IOError:
 +        pass
++
++
 +warnings.showwarning = show_warning_without_quoting_line
 +warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 +
 +
 +def insert_driver_hooks():
 +    extend_cql_deserialization()
 +    auto_format_udts()
 +
 +
 +def extend_cql_deserialization():
 +    """
 +    The python driver returns BLOBs as string, but we expect them as bytearrays; therefore we change
 +    the implementation of cassandra.cqltypes.BytesType.deserialize.
 +
 +    The deserializers package exists only when the driver has been compiled with cython extensions and
 +    cassandra.deserializers.DesBytesType replaces cassandra.cqltypes.BytesType.deserialize.
 +
 +    DesBytesTypeByteArray is a fast deserializer that converts blobs into bytearrays but it was
 +    only introduced recently (3.1.0). If it is available we use it, otherwise we remove
 +    cassandra.deserializers.DesBytesType so that we fall back onto cassandra.cqltypes.BytesType.deserialize
 +    just like in the case where no cython extensions are present.
 +    """
 +    if hasattr(cassandra, 'deserializers'):
 +        if hasattr(cassandra.deserializers, 'DesBytesTypeByteArray'):
 +            cassandra.deserializers.DesBytesType = cassandra.deserializers.DesBytesTypeByteArray
 +        else:
 +            del cassandra.deserializers.DesBytesType
 +
 +    cassandra.cqltypes.BytesType.deserialize = staticmethod(lambda byts, protocol_version: bytearray(byts))
 +    cassandra.cqltypes.CassandraType.support_empty_values = True
 +
 +
 +def auto_format_udts():
 +    # when we see a new user defined type, set up the shell formatting for it
 +    udt_apply_params = cassandra.cqltypes.UserType.apply_parameters
 +
 +    def new_apply_params(cls, *args, **kwargs):
 +        udt_class = udt_apply_params(*args, **kwargs)
 +        formatter_for(udt_class.typename)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.udt_apply_parameters = classmethod(new_apply_params)
 +
 +    make_udt_class = cassandra.cqltypes.UserType.make_udt_class
 +
 +    def new_make_udt_class(cls, *args, **kwargs):
 +        udt_class = make_udt_class(*args, **kwargs)
 +        formatter_for(udt_class.tuple_type.__name__)(format_value_utype)
 +        return udt_class
 +
 +    cassandra.cqltypes.UserType.make_udt_class = classmethod(new_make_udt_class)
 +
 +
 +class FrozenType(cassandra.cqltypes._ParameterizedType):
 +    """
 +    Needed until the bundled python driver adds FrozenType.
 +    """
 +    typename = "frozen"
 +    num_subtypes = 1
 +
 +    @classmethod
 +    def deserialize_safe(cls, byts, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.from_binary(byts)
 +
 +    @classmethod
 +    def serialize_safe(cls, val, protocol_version):
 +        subtype, = cls.subtypes
 +        return subtype.to_binary(val, protocol_version)
 +
 +
 +class Shell(cmd.Cmd):
 +    custom_prompt = os.getenv('CQLSH_PROMPT', '')
 +    if custom_prompt is not '':
 +        custom_prompt += "\n"
 +    default_prompt = custom_prompt + "cqlsh> "
 +    continue_prompt = "   ... "
 +    keyspace_prompt = custom_prompt + "cqlsh:%s> "
 +    keyspace_continue_prompt = "%s    ... "
 +    show_line_nums = False
 +    debug = False
 +    stop = False
 +    last_hist = None
 +    shunted_query_out = None
 +    use_paging = True
 +
 +    default_page_size = 100
 +
 +    def __init__(self, hostname, port, color=False,
 +                 username=None, password=None, encoding=None, stdin=None, tty=True,
 +                 completekey=DEFAULT_COMPLETEKEY, browser=None, use_conn=None,
 +                 cqlver=DEFAULT_CQLVER, keyspace=None,
 +                 tracing_enabled=False, expand_enabled=False,
 +                 display_nanotime_format=DEFAULT_NANOTIME_FORMAT,
 +                 display_timestamp_format=DEFAULT_TIMESTAMP_FORMAT,
 +                 display_date_format=DEFAULT_DATE_FORMAT,
 +                 display_float_precision=DEFAULT_FLOAT_PRECISION,
 +                 display_timezone=None,
 +                 max_trace_wait=DEFAULT_MAX_TRACE_WAIT,
 +                 ssl=False,
 +                 single_statement=None,
 +                 request_timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS,
 +                 protocol_version=DEFAULT_PROTOCOL_VERSION,
 +                 connect_timeout=DEFAULT_CONNECT_TIMEOUT_SECONDS):
 +        cmd.Cmd.__init__(self, completekey=completekey)
 +        self.hostname = hostname
 +        self.port = port
 +        self.auth_provider = None
 +        if username:
 +            if not password:
 +                password = getpass.getpass()
 +            self.auth_provider = PlainTextAuthProvider(username=username, password=password)
 +        self.username = username
 +        self.keyspace = keyspace
 +        self.ssl = ssl
 +        self.tracing_enabled = tracing_enabled
 +        self.page_size = self.default_page_size
 +        self.expand_enabled = expand_enabled
 +        if use_conn:
 +            self.conn = use_conn
 +        else:
 +            self.conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=cqlver,
 +                                protocol_version=protocol_version,
 +                                auth_provider=self.auth_provider,
 +                                ssl_options=sslhandling.ssl_settings(hostname, CONFIG_FILE) if ssl else None,
 +                                load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                                control_connection_timeout=connect_timeout,
 +                                connect_timeout=connect_timeout)
 +        self.owns_connection = not use_conn
 +        self.set_expanded_cql_version(cqlver)
 +
 +        if keyspace:
 +            self.session = self.conn.connect(keyspace)
 +        else:
 +            self.session = self.conn.connect()
 +
 +        if browser == "":
 +            browser = None
 +        self.browser = browser
 +        self.color = color
 +
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_date_format = display_date_format
 +
 +        self.display_float_precision = display_float_precision
 +
 +        self.display_timezone = display_timezone
 +
 +        self.session.default_timeout = request_timeout
 +        self.session.row_factory = ordered_dict_factory
 +        self.session.default_consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.get_connection_versions()
 +
 +        self.current_keyspace = keyspace
 +
 +        self.display_timestamp_format = display_timestamp_format
 +        self.display_nanotime_format = display_nanotime_format
 +        self.display_date_format = display_date_format
 +
 +        self.max_trace_wait = max_trace_wait
 +        self.session.max_trace_wait = max_trace_wait
 +
 +        self.tty = tty
 +        self.encoding = encoding
 +        self.check_windows_encoding()
 +
 +        self.output_codec = codecs.lookup(encoding)
 +
 +        self.statement = StringIO()
 +        self.lineno = 1
 +        self.in_comment = False
 +
 +        self.prompt = ''
 +        if stdin is None:
 +            stdin = sys.stdin
 +
 +        if tty:
 +            self.reset_prompt()
 +            self.report_connection()
 +            print 'Use HELP for help.'
 +        else:
 +            self.show_line_nums = True
 +        self.stdin = stdin
 +        self.query_out = sys.stdout
 +        self.consistency_level = cassandra.ConsistencyLevel.ONE
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.SERIAL
 +
 +        self.empty_lines = 0
 +        self.statement_error = False
 +        self.single_statement = single_statement
 +
 +    @property
 +    def is_using_utf8(self):
 +        # utf8 encodings from https://docs.python.org/{2,3}/library/codecs.html
 +        return self.encoding.replace('-', '_').lower() in ['utf', 'utf_8', 'u8', 'utf8', CP65001]
 +
 +    def check_windows_encoding(self):
 +        if is_win and os.name == 'nt' and self.tty and \
 +           self.is_using_utf8 and sys.stdout.encoding != CP65001:
 +            self.printerr("\nWARNING: console codepage must be set to cp65001 "
 +                          "to support {} encoding on Windows platforms.\n"
 +                          "If you experience encoding problems, change your console"
 +                          " codepage with 'chcp 65001' before starting cqlsh.\n".format(self.encoding))
 +
 +    def set_expanded_cql_version(self, ver):
 +        ver, vertuple = full_cql_version(ver)
 +        self.cql_version = ver
 +        self.cql_ver_tuple = vertuple
 +
 +    def cqlver_atleast(self, major, minor=0, patch=0):
 +        return self.cql_ver_tuple[:3] >= (major, minor, patch)
 +
 +    def myformat_value(self, val, **kwargs):
 +        if isinstance(val, DecodeError):
 +            self.decoding_errors.append(val)
 +        try:
 +            dtformats = DateTimeFormat(timestamp_format=self.display_timestamp_format,
 +                                       date_format=self.display_date_format, nanotime_format=self.display_nanotime_format,
 +                                       timezone=self.display_timezone)
 +            return format_value(val, self.output_codec.name,
 +                                addcolor=self.color, date_time_format=dtformats,
 +                                float_precision=self.display_float_precision, **kwargs)
 +        except Exception, e:
 +            err = FormatError(val, e)
 +            self.decoding_errors.append(err)
 +            return format_value(err, self.output_codec.name, addcolor=self.color)
 +
 +    def myformat_colname(self, name, table_meta=None):
 +        column_colors = COLUMN_NAME_COLORS.copy()
 +        # check column role and color appropriately
 +        if table_meta:
 +            if name in [col.name for col in table_meta.partition_key]:
 +                column_colors.default_factory = lambda: RED
 +            elif name in [col.name for col in table_meta.clustering_key]:
 +                column_colors.default_factory = lambda: CYAN
 +        return self.myformat_value(name, colormap=column_colors)
 +
 +    def report_connection(self):
 +        self.show_host()
 +        self.show_version()
 +
 +    def show_host(self):
 +        print "Connected to %s at %s:%d." % \
 +            (self.applycolor(self.get_cluster_name(), BLUE),
 +              self.hostname,
 +              self.port)
 +
 +    def show_version(self):
 +        vers = self.connection_versions.copy()
 +        vers['shver'] = version
 +        # 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 | Native protocol v%(protocol)s]" % vers
 +
 +    def show_session(self, sessionid, partial_session=False):
 +        print_trace_session(self, self.session, sessionid, partial_session)
 +
 +    def get_connection_versions(self):
 +        result, = self.session.execute("select * from system.local where key = 'local'")
 +        vers = {
 +            'build': result['release_version'],
 +            'protocol': result['native_protocol_version'],
 +            'cql': result['cql_version'],
 +        }
 +        self.connection_versions = vers
 +
 +    def get_keyspace_names(self):
 +        return map(str, self.conn.metadata.keyspaces.keys())
 +
 +    def get_columnfamily_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).tables.keys())
 +
 +    def get_index_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(str, self.get_keyspace_meta(ksname).indexes.keys())
 +
 +    def get_column_names(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        layout = self.get_table_meta(ksname, cfname)
 +        return [unicode(col) for col in layout.columns]
 +
 +    def get_usertype_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return self.get_keyspace_meta(ksname).user_types.keys()
 +
 +    def get_usertype_layout(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        ks_meta = self.get_keyspace_meta(ksname)
 +
 +        try:
 +            user_type = ks_meta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +
 +        return [(field_name, field_type.cql_parameterized_type())
 +                for field_name, field_type in zip(user_type.field_names, user_type.field_types)]
 +
 +    def get_userfunction_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).functions.values())
 +
 +    def get_useraggregate_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return map(lambda f: f.name, self.get_keyspace_meta(ksname).aggregates.values())
 +
 +    def get_cluster_name(self):
 +        return self.conn.metadata.cluster_name
 +
 +    def get_partitioner(self):
 +        return self.conn.metadata.partitioner
 +
 +    def get_keyspace_meta(self, ksname):
 +        if ksname not in self.conn.metadata.keyspaces:
 +            raise KeyspaceNotFound('Keyspace %r not found.' % ksname)
 +        return self.conn.metadata.keyspaces[ksname]
 +
 +    def get_keyspaces(self):
 +        return self.conn.metadata.keyspaces.values()
 +
 +    def get_ring(self, ks):
 +        self.conn.metadata.token_map.rebuild_keyspace(ks, build_if_absent=True)
 +        return self.conn.metadata.token_map.tokens_to_hosts_by_ks[ks]
 +
 +    def get_table_meta(self, ksname, tablename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if tablename not in ksmeta.tables:
 +            if ksname == 'system_auth' and tablename in ['roles', 'role_permissions']:
 +                self.get_fake_auth_table_meta(ksname, tablename)
 +            else:
 +                raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +        else:
 +            return ksmeta.tables[tablename]
 +
 +    def get_fake_auth_table_meta(self, ksname, tablename):
 +        # may be using external auth implementation so internal tables
 +        # aren't actually defined in schema. In this case, we'll fake
 +        # them up
 +        if tablename == 'roles':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'roles')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['is_superuser'] = ColumnMetadata(table_meta, 'is_superuser', cassandra.cqltypes.BooleanType)
 +            table_meta.columns['can_login'] = ColumnMetadata(table_meta, 'can_login', cassandra.cqltypes.BooleanType)
 +        elif tablename == 'role_permissions':
 +            ks_meta = KeyspaceMetadata(ksname, True, None, None)
 +            table_meta = TableMetadata(ks_meta, 'role_permissions')
 +            table_meta.columns['role'] = ColumnMetadata(table_meta, 'role', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['resource'] = ColumnMetadata(table_meta, 'resource', cassandra.cqltypes.UTF8Type)
 +            table_meta.columns['permission'] = ColumnMetadata(table_meta, 'permission', cassandra.cqltypes.UTF8Type)
 +        else:
 +            raise ColumnFamilyNotFound("Column family %r not found" % tablename)
 +
 +    def get_index_meta(self, ksname, idxname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        ksmeta = self.get_keyspace_meta(ksname)
 +
 +        if idxname not in ksmeta.indexes:
 +            raise IndexNotFound("Index %r not found" % idxname)
 +
 +        return ksmeta.indexes[idxname]
 +
 +    def get_object_meta(self, ks, name):
 +        if name is None:
 +            if ks and ks in self.conn.metadata.keyspaces:
 +                return self.conn.metadata.keyspaces[ks]
 +            elif self.current_keyspace is None:
 +                raise ObjectNotFound("%r not found in keyspaces" % (ks))
 +            else:
 +                name = ks
 +                ks = self.current_keyspace
 +
 +        if ks is None:
 +            ks = self.current_keyspace
 +
 +        ksmeta = self.get_keyspace_meta(ks)
 +
 +        if name in ksmeta.tables:
 +            return ksmeta.tables[name]
 +        elif name in ksmeta.indexes:
 +            return ksmeta.indexes[name]
 +
 +        raise ObjectNotFound("%r not found in keyspace %r" % (name, ks))
 +
 +    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)
 +
 +    def get_trigger_names(self, ksname=None):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +
 +        return [trigger.name
 +                for table in self.get_keyspace_meta(ksname).tables.values()
 +                for trigger in table.triggers.values()]
 +
 +    def reset_statement(self):
 +        self.reset_prompt()
 +        self.statement.truncate(0)
 +        self.empty_lines = 0
 +
 +    def reset_prompt(self):
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.default_prompt, True)
 +        else:
 +            self.set_prompt(self.keyspace_prompt % self.current_keyspace, True)
 +
 +    def set_continue_prompt(self):
 +        if self.empty_lines >= 3:
 +            self.set_prompt("Statements are terminated with a ';'.  You can press CTRL-C to cancel an incomplete statement.")
 +            self.empty_lines = 0
 +            return
 +        if self.current_keyspace is None:
 +            self.set_prompt(self.continue_prompt)
 +        else:
 +            spaces = ' ' * len(str(self.current_keyspace))
 +            self.set_prompt(self.keyspace_continue_prompt % spaces)
 +        self.empty_lines = self.empty_lines + 1 if not self.lastcmd else 0
 +
 +    @contextmanager
 +    def prepare_loop(self):
 +        readline = None
 +        if self.tty and self.completekey:
 +            try:
 +                import readline
 +            except ImportError:
 +                if is_win:
 +                    print "WARNING: pyreadline dependency missing.  Install to enable tab completion."
 +                pass
 +            else:
 +                old_completer = readline.get_completer()
 +                readline.set_completer(self.complete)
 +                if readline.__doc__ is not None and 'libedit' in readline.__doc__:
 +                    readline.parse_and_bind("bind -e")
 +                    readline.parse_and_bind("bind '" + self.completekey + "' rl_complete")
 +                    readline.parse_and_bind("bind ^R em-inc-search-prev")
 +                else:
 +                    readline.parse_and_bind(self.completekey + ": complete")
 +        try:
 +            yield
 +        finally:
 +            if readline is not None:
 +                readline.set_completer(old_completer)
 +
 +    def get_input_line(self, prompt=''):
 +        if self.tty:
 +            try:
 +                self.lastcmd = raw_input(prompt).decode(self.encoding)
 +            except UnicodeDecodeError:
 +                self.lastcmd = ''
 +                traceback.print_exc()
 +                self.check_windows_encoding()
 +            line = self.lastcmd + '\n'
 +        else:
 +            self.lastcmd = self.stdin.readline()
 +            line = self.lastcmd
 +            if not len(line):
 +                raise EOFError
 +        self.lineno += 1
 +        return line
 +
 +    def use_stdin_reader(self, until='', prompt=''):
 +        until += '\n'
 +        while True:
 +            try:
 +                newline = self.get_input_line(prompt=prompt)
 +            except EOFError:
 +                return
 +            if newline == until:
 +                return
 +            yield newline
 +
 +    def cmdloop(self):
 +        """
 +        Adapted from cmd.Cmd's version, because there is literally no way with
 +        cmd.Cmd.cmdloop() to tell the difference between "EOF" showing up in
 +        input and an actual EOF.
 +        """
 +        with self.prepare_loop():
 +            while not self.stop:
 +                try:
 +                    if self.single_statement:
 +                        line = self.single_statement
 +                        self.stop = True
 +                    else:
 +                        line = self.get_input_line(self.prompt)
 +                    self.statement.write(line)
 +                    if self.onecmd(self.statement.getvalue()):
 +                        self.reset_statement()
 +                except EOFError:
 +                    self.handle_eof()
 +                except CQL_ERRORS, cqlerr:
 +                    self.printerr(cqlerr.message.decode(encoding='utf-8'))
 +                except KeyboardInterrupt:
 +                    self.reset_statement()
 +                    print
 +
 +    def onecmd(self, statementtext):
 +        """
 +        Returns true if the statement is complete and was handled (meaning it
 +        can be reset).
 +        """
 +
 +        try:
 +            statements, endtoken_escaped = cqlruleset.cql_split_statements(statementtext)
 +        except pylexotron.LexingError, e:
 +            if self.show_line_nums:
 +                self.printerr('Invalid syntax at char %d' % (e.charnum,))
 +            else:
 +                self.printerr('Invalid syntax at line %d, char %d'
 +                              % (e.linenum, e.charnum))
 +            statementline = statementtext.split('\n')[e.linenum - 1]
 +            self.printerr('  %s' % statementline)
 +            self.printerr(' %s^' % (' ' * e.charnum))
 +            return True
 +
 +        while statements and not statements[-1]:
 +            statements = statements[:-1]
 +        if not statements:
 +            return True
 +        if endtoken_escaped or statements[-1][-1][0] != 'endtoken':
 +            self.set_continue_prompt()
 +            return
 +        for st in statements:
 +            try:
 +                self.handle_statement(st, statementtext)
 +            except Exception, e:
 +                if self.debug:
 +                    traceback.print_exc()
 +                else:
 +                    self.printerr(e)
 +        return True
 +
 +    def handle_eof(self):
 +        if self.tty:
 +            print
 +        statement = self.statement.getvalue()
 +        if statement.strip():
 +            if not self.onecmd(statement):
 +                self.printerr('Incomplete statement at end of file')
 +        self.do_exit()
 +
 +    def handle_statement(self, tokens, srcstr):
 +        # Concat multi-line statements and insert into history
 +        if readline is not None:
 +            nl_count = srcstr.count("\n")
 +
 +            new_hist = srcstr.replace("\n", " ").rstrip()
 +
 +            if nl_count > 1 and self.last_hist != new_hist:
 +                readline.add_history(new_hist.encode(self.encoding))
 +
 +            self.last_hist = new_hist
 +        cmdword = tokens[0][1]
 +        if cmdword == '?':
 +            cmdword = 'help'
 +        custom_handler = getattr(self, 'do_' + cmdword.lower(), None)
 +        if custom_handler:
 +            parsed = cqlruleset.cql_whole_parse_tokens(tokens, srcstr=srcstr,
 +                                                       startsymbol='cqlshCommand')
 +            if parsed and not parsed.remainder:
 +                # successful complete parse
 +                return custom_handler(parsed)
 +            else:
 +                return self.handle_parse_error(cmdword, tokens, parsed, srcstr)
 +        return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +
 +    def handle_parse_error(self, cmdword, tokens, parsed, srcstr):
 +        if cmdword.lower() in ('select', 'insert', 'update', 'delete', 'truncate',
 +                               'create', 'drop', 'alter', 'grant', 'revoke',
 +                               'batch', 'list'):
 +            # hey, maybe they know about some new syntax we don't. type
 +            # assumptions won't work, but maybe the query will.
 +            return self.perform_statement(cqlruleset.cql_extract_orig(tokens, srcstr))
 +        if parsed:
 +            self.printerr('Improper %s command (problem at %r).' % (cmdword, parsed.remainder[0]))
 +        else:
 +            self.printerr('Improper %s command.' % cmdword)
 +
 +    def do_use(self, parsed):
 +        ksname = parsed.get_binding('ksname')
 +        success, _ = self.perform_simple_statement(SimpleStatement(parsed.extract_orig()))
 +        if success:
 +            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):
 +        tracing_was_enabled = self.tracing_enabled
 +        ksname = parsed.get_binding('ksname')
 +        stop_tracing = ksname == 'system_traces' or (ksname is None and self.current_keyspace == 'system_traces')
 +        self.tracing_enabled = self.tracing_enabled and not stop_tracing
 +        statement = parsed.extract_orig()
 +        self.perform_statement(statement)
 +        self.tracing_enabled = tracing_was_enabled
 +
 +    def perform_statement(self, statement):
 +        stmt = SimpleStatement(statement, consistency_level=self.consistency_level, serial_consistency_level=self.serial_consistency_level, fetch_size=self.page_size if self.use_paging else None)
 +        success, future = self.perform_simple_statement(stmt)
 +
 +        if future:
 +            if future.warnings:
 +                self.print_warnings(future.warnings)
 +
 +            if self.tracing_enabled:
 +                try:
 +                    for trace in future.get_all_query_traces(max_wait_per=self.max_trace_wait, query_cl=self.consistency_level):
 +                        print_trace(self, trace)
 +                except TraceUnavailable:
 +                    msg = "Statement trace did not complete within %d seconds; trace data may be incomplete." % (self.session.max_trace_wait,)
 +                    self.writeresult(msg, color=RED)
 +                    for trace_id in future.get_query_trace_ids():
 +                        self.show_session(trace_id, partial_session=True)
 +                except Exception, err:
 +                    self.printerr("Unable to fetch query trace: %s" % (str(err),))
 +
 +        return success
 +
 +    def parse_for_table_meta(self, query_string):
 +        try:
 +            parsed = cqlruleset.cql_parse(query_string)[1]
 +        except IndexError:
 +            return None
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        return self.get_table_meta(ks, cf)
 +
 +    def perform_simple_statement(self, statement):
 +        if not statement:
 +            return False, None
 +
 +        future = self.session.execute_async(statement, trace=self.tracing_enabled)
 +        result = None
 +        try:
 +            result = future.result()
 +        except CQL_ERRORS, err:
 +            self.printerr(unicode(err.__class__.__name__) + u": " + err.message.decode(encoding='utf-8'))
 +        except Exception:
 +            import traceback
 +            self.printerr(traceback.format_exc())
 +
 +        # Even if statement failed we try to refresh schema if not agreed (see CASSANDRA-9689)
 +        if not future.is_schema_agreed:
 +            try:
 +                self.conn.refresh_schema_metadata(5)  # will throw exception if there is a schema mismatch
 +            except Exception:
 +                self.printerr("Warning: schema version mismatch detected; check the schema versions of your "
 +                              "nodes in system.local and system.peers.")
 +                self.conn.refresh_schema_metadata(-1)
 +
 +        if result is None:
 +            return False, None
 +
 +        if statement.query_string[:6].lower() == 'select':
 +            self.print_result(result, self.parse_for_table_meta(statement.query_string))
 +        elif statement.query_string.lower().startswith("list users") or statement.query_string.lower().startswith("list roles"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'roles'))
 +        elif statement.query_string.lower().startswith("list"):
 +            self.print_result(result, self.get_table_meta('system_auth', 'role_permissions'))
 +        elif result:
 +            # CAS INSERT/UPDATE
 +            self.writeresult("")
 +            self.print_static_result(result.column_names, list(result), self.parse_for_table_meta(statement.query_string))
 +        self.flush_output()
 +        return True, future
 +
 +    def print_result(self, result, table_meta):
 +        self.decoding_errors = []
 +
 +        self.writeresult("")
 +        if result.has_more_pages and self.tty:
 +            num_rows = 0
 +            while True:
 +                page = result.current_rows
 +                if page:
 +                    num_rows += len(page)
 +                    self.print_static_result(result.column_names, page, table_meta)
 +                if result.has_more_pages:
 +                    raw_input("---MORE---")
 +                    result.fetch_next_page()
 +                else:
 +                    break
 +        else:
 +            rows = list(result)
 +            num_rows = len(rows)
 +            self.print_static_result(result.column_names, rows, table_meta)
 +        self.writeresult("(%d rows)" % num_rows)
 +
 +        if self.decoding_errors:
 +            for err in self.decoding_errors[:2]:
 +                self.writeresult(err.message(), color=RED)
 +            if len(self.decoding_errors) > 2:
 +                self.writeresult('%d more decoding errors suppressed.'
 +                                 % (len(self.decoding_errors) - 2), color=RED)
 +
 +    def print_static_result(self, column_names, rows, table_meta):
 +        if not column_names and not table_meta:
 +            return
 +
 +        column_names = column_names or table_meta.columns.keys()
 +        formatted_names = [self.myformat_colname(name, table_meta) for name in column_names]
 +        if not rows:
 +            # print header only
 +            self.print_formatted_result(formatted_names, None)
 +            return
 +        formatted_values = [map(self.myformat_value, row.values()) for row in rows]
 +
 +        if self.expand_enabled:
 +            self.print_formatted_result_vertically(formatted_names, formatted_values)
 +        else:
 +            self.print_formatted_result(formatted_names, formatted_values)
 +
 +    def print_formatted_result(self, formatted_names, formatted_values):
 +        # determine column widths
 +        widths = [n.displaywidth for n in formatted_names]
 +        if formatted_values is not None:
 +            for fmtrow in formatted_values:
 +                for num, col in enumerate(fmtrow):
 +                    widths[num] = max(widths[num], col.displaywidth)
 +
 +        # print header
 +        header = ' | '.join(hdr.ljust(w, color=self.color) for (hdr, w) in zip(formatted_names, widths))
 +        self.writeresult(' ' + header.rstrip())
 +        self.writeresult('-%s-' % '-+-'.join('-' * w for w in widths))
 +
 +        # stop if there are no rows
 +        if formatted_values is None:
 +            self.writeresult("")
 +            return
 +
 +        # print row data
 +        for row in formatted_values:
 +            line = ' | '.join(col.rjust(w, color=self.color) for (col, w) in zip(row, widths))
 +            self.writeresult(' ' + line)
 +
 +        self.writeresult("")
 +
 +    def print_formatted_result_vertically(self, formatted_names, formatted_values):
 +        max_col_width = max([n.displaywidth for n in formatted_names])
 +        max_val_width = max([n.displaywidth for row in formatted_values for n in row])
 +
 +        # for each row returned, list all the column-value pairs
 +        for row_id, row in enumerate(formatted_values):
 +            self.writeresult("@ Row %d" % (row_id + 1))
 +            self.writeresult('-%s-' % '-+-'.join(['-' * max_col_width, '-' * max_val_width]))
 +            for field_id, field in enumerate(row):
 +                column = formatted_names[field_id].ljust(max_col_width, color=self.color)
 +                value = field.ljust(field.displaywidth, color=self.color)
 +                self.writeresult(' ' + " | ".join([column, value]))
 +            self.writeresult('')
 +
 +    def print_warnings(self, warnings):
 +        if warnings is None or len(warnings) == 0:
 +            return
 +
 +        self.writeresult('')
 +        self.writeresult('Warnings :')
 +        for warning in warnings:
 +            self.writeresult(warning)
 +            self.writeresult('')
 +
 +    def emptyline(self):
 +        pass
 +
 +    def parseline(self, line):
 +        # this shouldn't be needed
 +        raise NotImplementedError
 +
 +    def complete(self, text, state):
 +        if readline is None:
 +            return
 +        if state == 0:
 +            try:
 +                self.completion_matches = self.find_completions(text)
 +            except Exception:
 +                if debug_completion:
 +                    import traceback
 +                    traceback.print_exc()
 +                else:
 +                    raise
 +        try:
 +            return self.completion_matches[state]
 +        except IndexError:
 +            return None
 +
 +    def find_completions(self, text):
 +        curline = readline.get_line_buffer()
 +        prevlines = self.statement.getvalue()
 +        wholestmt = prevlines + curline
 +        begidx = readline.get_begidx() + len(prevlines)
 +        stuff_to_complete = wholestmt[:begidx]
 +        return cqlruleset.cql_complete(stuff_to_complete, text, cassandra_conn=self,
 +                                       debug=debug_completion, startsymbol='cqlshCommand')
 +
 +    def set_prompt(self, prompt, prepend_user=False):
 +        if prepend_user and self.username:
 +            self.prompt = "%s@%s" % (self.username, prompt)
 +            return
 +        self.prompt = prompt
 +
 +    def cql_unprotect_name(self, namestr):
 +        if namestr is None:
 +            return
 +        return cqlruleset.dequote_name(namestr)
 +
 +    def cql_unprotect_value(self, valstr):
 +        if valstr is not None:
 +            return cqlruleset.dequote_value(valstr)
 +
 +    def print_recreate_keyspace(self, ksdef, out):
 +        out.write(ksdef.export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_columnfamily(self, ksname, cfname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given table.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_table_meta(ksname, cfname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_index(self, ksname, idxname, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given index.
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_index_meta(ksname, idxname).export_as_string())
 +        out.write("\n")
 +
 +    def print_recreate_object(self, ks, name, out):
 +        """
 +        Output CQL commands which should be pasteable back into a CQL session
 +        to recreate the given object (ks, table or index).
 +
 +        Writes output to the given out stream.
 +        """
 +        out.write(self.get_object_meta(ks, name).export_as_string())
 +        out.write("\n")
 +
 +    def describe_keyspaces(self):
 +        print
 +        cmd.Cmd.columnize(self, protect_names(self.get_keyspace_names()))
 +        print
 +
 +    def describe_keyspace(self, ksname):
 +        print
 +        self.print_recreate_keyspace(self.get_keyspace_meta(ksname), sys.stdout)
 +        print
 +
 +    def describe_columnfamily(self, ksname, cfname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        self.print_recreate_columnfamily(ksname, cfname, sys.stdout)
 +        print
 +
 +    def describe_index(self, ksname, idxname):
 +        print
 +        self.print_recreate_index(ksname, idxname, sys.stdout)
 +        print
 +
 +    def describe_object(self, ks, name):
 +        print
 +        self.print_recreate_object(ks, name, sys.stdout)
 +        print
 +
 +    def describe_columnfamilies(self, ksname):
 +        print
 +        if ksname is None:
 +            for k in self.get_keyspaces():
 +                name = protect_name(k.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(k.name)))
 +                print
 +        else:
 +            cmd.Cmd.columnize(self, protect_names(self.get_columnfamily_names(ksname)))
 +            print
 +
 +    def describe_functions(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.functions.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.functions.keys())
 +
 +    def describe_function(self, ksname, functionname):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        functions = filter(lambda f: f.name == functionname, ksmeta.functions.values())
 +        if len(functions) == 0:
 +            raise FunctionNotFound("User defined function %r not found" % functionname)
 +        print "\n\n".join(func.as_cql_query(formatted=True) for func in functions)
 +        print
 +
 +    def describe_aggregates(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.aggregates.keys())
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.aggregates.keys())
 +
 +    def describe_aggregate(self, ksname, aggregatename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        aggregates = filter(lambda f: f.name == aggregatename, ksmeta.aggregates.values())
 +        if len(aggregates) == 0:
 +            raise FunctionNotFound("User defined aggregate %r not found" % aggregatename)
 +        print "\n\n".join(aggr.as_cql_query(formatted=True) for aggr in aggregates)
 +        print
 +
 +    def describe_usertypes(self, ksname):
 +        print
 +        if ksname is None:
 +            for ksmeta in self.get_keyspaces():
 +                name = protect_name(ksmeta.name)
 +                print 'Keyspace %s' % (name,)
 +                print '---------%s' % ('-' * len(name))
 +                self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +        else:
 +            ksmeta = self.get_keyspace_meta(ksname)
 +            self._columnize_unicode(ksmeta.user_types.keys(), quote=True)
 +
 +    def describe_usertype(self, ksname, typename):
 +        if ksname is None:
 +            ksname = self.current_keyspace
 +        if ksname is None:
 +            raise NoKeyspaceError("No keyspace specified and no current keyspace")
 +        print
 +        ksmeta = self.get_keyspace_meta(ksname)
 +        try:
 +            usertype = ksmeta.user_types[typename]
 +        except KeyError:
 +            raise UserTypeNotFound("User type %r not found" % typename)
 +        print usertype.as_cql_query(formatted=True)
 +        print
 +
 +    def _columnize_unicode(self, name_list, quote=False):
 +        """
 +        Used when columnizing identifiers that may contain unicode
 +        """
 +        names = [n.encode('utf-8') for n in name_list]
 +        if quote:
 +            names = protect_names(names)
 +        cmd.Cmd.columnize(self, names)
 +        print
 +
 +    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\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(self.current_keyspace)
 +            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):
 +        print
 +        for k in self.get_keyspaces():
 +            if include_system or k.name not in cql3handling.SYSTEM_KEYSPACES:
 +                self.print_recreate_keyspace(k, sys.stdout)
 +                print
 +
 +    def do_describe(self, parsed):
 +        """
 +        DESCRIBE [cqlsh only]
 +
 +        (DESC may be used as a shorthand.)
 +
 +          Outputs information about the connected Cassandra cluster, or about
 +          the data objects stored in the cluster. Use in one of the following ways:
 +
 +        DESCRIBE KEYSPACES
 +
 +          Output the names of all keyspaces.
 +
 +        DESCRIBE KEYSPACE [<keyspacename>]
 +
 +          Output CQL commands that could be used to recreate the given keyspace,
 +          and the objects in it (such as tables, types, functions, etc.).
 +          In some cases, as the CQL interface matures, there will be some metadata
 +          about a keyspace that is not representable with CQL. That metadata will not be shown.
 +
 +          The '<keyspacename>' argument may be omitted, in which case the current
 +          keyspace will be described.
 +
 +        DESCRIBE TABLES
 +
 +          Output the names of all tables in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TABLE [<keyspace>.]<tablename>
 +
 +          Output CQL commands that could be used to recreate the given table.
 +          In some cases, as above, there may be table metadata which is not
 +          representable and which will not be shown.
 +
 +        DESCRIBE INDEX <indexname>
 +
 +          Output the CQL command that could be used to recreate the given index.
 +          In some cases, there may be index metadata which is not representable
 +          and which will not be shown.
 +
 +        DESCRIBE CLUSTER
 +
 +          Output information about the connected Cassandra cluster, such as the
 +          cluster name, and the partitioner and snitch in use. When you are
 +          connected to a non-system keyspace, also shows endpoint-range
 +          ownership information for the Cassandra ring.
 +
 +        DESCRIBE [FULL] SCHEMA
 +
 +          Output CQL commands that could be used to recreate the entire (non-system) schema.
 +          Works as though "DESCRIBE KEYSPACE k" was invoked for each non-system keyspace
 +          k. Use DESCRIBE FULL SCHEMA to include the system keyspaces.
 +
 +        DESCRIBE TYPES
 +
 +          Output the names of all user-defined-types in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE TYPE [<keyspace>.]<type>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-type.
 +
 +        DESCRIBE FUNCTIONS
 +
 +          Output the names of all user-defined-functions in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE FUNCTION [<keyspace>.]<function>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-function.
 +
 +        DESCRIBE AGGREGATES
 +
 +          Output the names of all user-defined-aggregates in the current keyspace, or in all
 +          keyspaces if there is no current keyspace.
 +
 +        DESCRIBE AGGREGATE [<keyspace>.]<aggregate>
 +
 +          Output the CQL command that could be used to recreate the given user-defined-aggregate.
 +
 +        DESCRIBE <objname>
 +
 +          Output CQL commands that could be used to recreate the entire object schema,
 +          where object can be either a keyspace or a table or an index (in this order).
 +  """
 +        what = parsed.matched[1][1].lower()
 +        if what == 'functions':
 +            self.describe_functions(self.current_keyspace)
 +        elif what == 'function':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            functionname = self.cql_unprotect_name(parsed.get_binding('udfname'))
 +            self.describe_function(ksname, functionname)
 +        elif what == 'aggregates':
 +            self.describe_aggregates(self.current_keyspace)
 +        elif what == 'aggregate':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            aggregatename = self.cql_unprotect_name(parsed.get_binding('udaname'))
 +            self.describe_aggregate(ksname, aggregatename)
 +        elif what == 'keyspaces':
 +            self.describe_keyspaces()
 +        elif what == 'keyspace':
 +            ksname = self.cql_unprotect_name(parsed.get_binding('ksname', ''))
 +            if not ksname:
 +                ksname = self.current_keyspace
 +                if ksname is None:
 +                    self.printerr('Not in any keyspace.')
 +                    return
 +            self.describe_keyspace(ksname)
 +        elif what in ('columnfamily', 'table'):
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            cf = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            self.describe_columnfamily(ks, cf)
 +        elif what == 'index':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            idx = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_index(ks, idx)
 +        elif what in ('columnfamilies', 'tables'):
 +            self.describe_columnfamilies(self.current_keyspace)
 +        elif what == 'types':
 +            self.describe_usertypes(self.current_keyspace)
 +        elif what == 'type':
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            ut = self.cql_unprotect_name(parsed.get_binding('utname'))
 +            self.describe_usertype(ks, ut)
 +        elif what == 'cluster':
 +            self.describe_cluster()
 +        elif what == 'schema':
 +            self.describe_schema(False)
 +        elif what == 'full' and parsed.matched[2][1].lower() == 'schema':
 +            self.describe_schema(True)
 +        elif what:
 +            ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +            name = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +            if not name:
 +                name = self.cql_unprotect_name(parsed.get_binding('idxname', None))
 +            self.describe_object(ks, name)
 +    do_desc = do_describe
 +
 +    def do_copy(self, parsed):
 +        r"""
 +        COPY [cqlsh only]
 +
 +          COPY x FROM: Imports CSV data into a Cassandra table
 +          COPY x TO: Exports data from a Cassandra table in CSV format.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             FROM ( '<file_pattern_1, file_pattern_2, ... file_pattern_n>' | STDIN )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        File patterns are either file names or valid python glob expressions, e.g. *.csv or folder/*.csv.
 +
 +        COPY <table_name> [ ( column [, ...] ) ]
 +             TO ( '<filename>' | STDOUT )
 +             [ WITH <option>='value' [AND ...] ];
 +
 +        Available common COPY options and defaults:
 +
 +          DELIMITER=','           - character that appears between records
 +          QUOTE='"'               - quoting character to be used to quote fields
 +          ESCAPE='\'              - character to appear before the QUOTE char when quoted
 +          HEADER=false            - whether to ignore the first line
 +          NULL=''                 - string that represents a null value
 +          DATETIMEFORMAT=         - timestamp strftime format
 +            '%Y-%m-%d %H:%M:%S%z'   defaults to time_format value in cqlshrc
 +          MAXATTEMPTS=5           - the maximum number of attempts per batch or range
 +          REPORTFREQUENCY=0.25    - the frequency with which we display status updates in seconds
 +          DECIMALSEP='.'          - the separator for decimal values
 +          THOUSANDSSEP=''         - the separator for thousands digit groups
 +          BOOLSTYLE='True,False'  - the representation for booleans, case insensitive, specify true followed by false,
 +                                    for example yes,no or 1,0
 +          NUMPROCESSES=n          - the number of worker processes, by default the number of cores minus one
 +                                    capped at 16
 +          CONFIGFILE=''           - a configuration file with the same format as .cqlshrc (see the Python ConfigParser
 +                                    documentation) where you can specify WITH options under the following optional
 +                                    sections: [copy], [copy-to], [copy-from], [copy:ks.table], [copy-to:ks.table],
 +                                    [copy-from:ks.table], where <ks> is your keyspace name and <table> is your table
 +                                    name. Options are read from these sections, in the order specified
 +                                    above, and command line options always override options in configuration files.
 +                                    Depending on the COPY direction, only the relevant copy-from or copy-to sections
 +                                    are used. If no configfile is specified then .cqlshrc is searched instead.
 +          RATEFILE=''             - an optional file where to print the output statistics
 +
 +        Available COPY FROM options and defaults:
 +
 +          CHUNKSIZE=5000          - the size of chunks passed to worker processes
 +          INGESTRATE=100000       - an approximate ingest rate in rows per second
 +          MINBATCHSIZE=10         - the minimum size of an import batch
 +          MAXBATCHSIZE=20         - the maximum size of an import batch
 +          MAXROWS=-1              - the maximum number of rows, -1 means no maximum
 +          SKIPROWS=0              - the number of rows to skip
 +          SKIPCOLS=''             - a comma separated list of column names to skip
 +          MAXPARSEERRORS=-1       - the maximum global number of parsing errors, -1 means no maximum
 +          MAXINSERTERRORS=-1      - the maximum global number of insert errors, -1 means no maximum
 +          ERRFILE=''              - a file where to store all rows that could not be imported, by default this is
 +                                    import_ks_table.err where <ks> is your keyspace and <table> is your table name.
 +          PREPAREDSTATEMENTS=True - whether to use prepared statements when importing, by default True. Set this to
 +                                    False if you don't mind shifting data parsing to the cluster. The cluster will also
 +                                    have to compile every batch statement. For large and oversized clusters
 +                                    this will result in a faster import but for smaller clusters it may generate
 +                                    timeouts.
 +
 +        Available COPY TO options and defaults:
 +
 +          ENCODING='utf8'          - encoding for CSV output
 +          PAGESIZE='1000'          - the page size for fetching results
 +          PAGETIMEOUT=10           - the page timeout in seconds for fetching results
 +          BEGINTOKEN=''            - the minimum token string to consider when exporting data
 +          ENDTOKEN=''              - the maximum token string to consider when exporting data
 +          MAXREQUESTS=6            - the maximum number of requests each worker process can work on in parallel
 +          MAXOUTPUTSIZE='-1'       - the maximum size of the output file measured in number of lines,
 +                                     beyond this maximum the output file will be split into segments,
 +                                     -1 means unlimited.
 +
 +        When entering CSV data on STDIN, you can use the sequence "\."
 +        on a line by itself to end the data input.
 +        """
 +
 +        ks = self.cql_unprotect_name(parsed.get_binding('ksname', None))
 +        if ks is None:
 +            ks = self.current_keyspace
 +            if ks is None:
 +                raise NoKeyspaceError("Not in any keyspace.")
 +        table = self.cql_unprotect_name(parsed.get_binding('cfname'))
 +        columns = parsed.get_binding('colnames', None)
 +        if columns is not None:
 +            columns = map(self.cql_unprotect_name, columns)
 +        else:
 +            # default to all known columns
 +            columns = self.get_column_names(ks, table)
 +
 +        fname = parsed.get_binding('fname', None)
 +        if fname is not None:
 +            fname = self.cql_unprotect_value(fname)
 +
 +        copyoptnames = map(str.lower, parsed.get_binding('optnames', ()))
 +        copyoptvals = map(self.cql_unprotect_value, parsed.get_binding('optvals', ()))
 +        opts = dict(zip(copyoptnames, copyoptvals))
 +
 +        direction = parsed.get_binding('dir').upper()
 +        if direction == 'FROM':
 +            task = ImportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        elif direction == 'TO':
 +            task = ExportTask(self, ks, table, columns, fname, opts, DEFAULT_PROTOCOL_VERSION, CONFIG_FILE)
 +        else:
 +            raise SyntaxError("Unknown direction %s" % direction)
 +
 +        task.run()
 +
 +    def do_show(self, parsed):
 +        """
 +        SHOW [cqlsh only]
 +
 +          Displays information about the current cqlsh session. Can be called in
 +          the following ways:
 +
 +        SHOW VERSION
 +
 +          Shows the version and build of the connected Cassandra instance, as
 +          well as the versions of the CQL spec and the Thrift protocol that
 +          the connected Cassandra instance understands.
 +
 +        SHOW HOST
 +
 +          Shows where cqlsh is currently connected.
 +
 +        SHOW SESSION <sessionid>
 +
 +          Pretty-prints the requested tracing session.
 +        """
 +        showwhat = parsed.get_binding('what').lower()
 +        if showwhat == 'version':
 +            self.get_connection_versions()
 +            self.show_version()
 +        elif showwhat == 'host':
 +            self.show_host()
 +        elif showwhat.startswith('session'):
 +            session_id = parsed.get_binding('sessionid').lower()
 +            self.show_session(UUID(session_id))
 +        else:
 +            self.printerr('Wait, how do I show %r?' % (showwhat,))
 +
 +    def do_source(self, parsed):
 +        """
 +        SOURCE [cqlsh only]
 +
 +        Executes a file containing CQL statements. Gives the output for each
 +        statement in turn, if any, or any errors that occur along the way.
 +
 +        Errors do NOT abort execution of the CQL source file.
 +
 +        Usage:
 +
 +          SOURCE '<file>';
 +
 +        That is, the path to the file to be executed must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        See also the --file option to cqlsh.
 +        """
 +        fname = parsed.get_binding('fname')
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            encoding, bom_size = get_file_encoding_bomsize(fname)
 +            f = codecs.open(fname, 'r', encoding)
 +            f.seek(bom_size)
 +        except IOError, e:
 +            self.printerr('Could not open %r: %s' % (fname, e))
 +            return
 +        username = self.auth_provider.username if self.auth_provider else None
 +        password = self.auth_provider.password if self.auth_provider else None
 +        subshell = Shell(self.hostname, self.port, color=self.color,
 +                         username=username, password=password,
 +                         encoding=self.encoding, stdin=f, tty=False, use_conn=self.conn,
 +                         cqlver=self.cql_version, keyspace=self.current_keyspace,
 +                         tracing_enabled=self.tracing_enabled,
 +                         display_nanotime_format=self.display_nanotime_format,
 +                         display_timestamp_format=self.display_timestamp_format,
 +                         display_date_format=self.display_date_format,
 +                         display_float_precision=self.display_float_precision,
 +                         display_timezone=self.display_timezone,
 +                         max_trace_wait=self.max_trace_wait, ssl=self.ssl,
 +                         request_timeout=self.session.default_timeout,
 +                         connect_timeout=self.conn.connect_timeout)
 +        subshell.cmdloop()
 +        f.close()
 +
 +    def do_capture(self, parsed):
 +        """
 +        CAPTURE [cqlsh only]
 +
 +        Begins capturing command output and appending it to a specified file.
 +        Output will not be shown at the console while it is captured.
 +
 +        Usage:
 +
 +          CAPTURE '<file>';
 +          CAPTURE OFF;
 +          CAPTURE;
 +
 +        That is, the path to the file to be appended to must be given inside a
 +        string literal. The path is interpreted relative to the current working
 +        directory. The tilde shorthand notation ('~/mydir') is supported for
 +        referring to $HOME.
 +
 +        Only query result output is captured. Errors and output from cqlsh-only
 +        commands will still be shown in the cqlsh session.
 +
 +        To stop capturing output and show it in the cqlsh session again, use
 +        CAPTURE OFF.
 +
 +        To inspect the current capture configuration, use CAPTURE with no
 +        arguments.
 +        """
 +        fname = parsed.get_binding('fname')
 +        if fname is None:
 +            if self.shunted_query_out is not None:
 +                print "Currently capturing query output to %r." % (self.query_out.name,)
 +            else:
 +                print "Currently not capturing query output."
 +            return
 +
 +        if fname.upper() == 'OFF':
 +            if self.shunted_query_out is None:
 +                self.printerr('Not currently capturing output.')
 +                return
 +            self.query_out.close()
 +            self.query_out = self.shunted_query_out
 +            self.color = self.shunted_color
 +            self.shunted_query_out = None
 +            del self.shunted_color
 +            return
 +
 +        if self.shunted_query_out is not None:
 +            self.printerr('Already capturing output to %s. Use CAPTURE OFF'
 +                          ' to disable.' % (self.query_out.name,))
 +            return
 +
 +        fname = os.path.expanduser(self.cql_unprotect_value(fname))
 +        try:
 +            f = open(fname, 'a')
 +        except IOError, e:
 +            self.printerr('Could not open %r for append: %s' % (fname, e))
 +            return
 +        self.shunted_query_out = self.query_out
 +        self.shunted_color = self.color
 +        self.query_out = f
 +        self.color = False
 +        print 'Now capturing query output to %r.' % (fname,)
 +
 +    def do_tracing(self, parsed):
 +        """
 +        TRACING [cqlsh]
 +
 +          Enables or disables request tracing.
 +
 +        TRACING ON
 +
 +          Enables tracing for all further requests.
 +
 +        TRACING OFF
 +
 +          Disables tracing.
 +
 +        TRACING
 +
 +          TRACING with no arguments shows the current tracing status.
 +        """
 +        self.tracing_enabled = SwitchCommand("TRACING", "Tracing").execute(self.tracing_enabled, parsed, self.printerr)
 +
 +    def do_expand(self, parsed):
 +        """
 +        EXPAND [cqlsh]
 +
 +          Enables or disables expanded (vertical) output.
 +
 +        EXPAND ON
 +
 +          Enables expanded (vertical) output.
 +
 +        EXPAND OFF
 +
 +          Disables expanded (vertical) output.
 +
 +        EXPAND
 +
 +          EXPAND with no arguments shows the current value of expand setting.
 +        """
 +        self.expand_enabled = SwitchCommand("EXPAND", "Expanded output").execute(self.expand_enabled, parsed, self.printerr)
 +
 +    def do_consistency(self, parsed):
 +        """
 +        CONSISTENCY [cqlsh only]
 +
 +           Overrides default consistency level (default level is ONE).
 +
 +        CONSISTENCY <level>
 +
 +           Sets consistency level for future requests.
 +
 +           Valid consistency levels:
 +
 +           ANY, ONE, TWO, THREE, QUORUM, ALL, LOCAL_ONE, LOCAL_QUORUM, EACH_QUORUM, SERIAL and LOCAL_SERIAL.
 +
 +           SERIAL and LOCAL_SERIAL may be used only for SELECTs; will be rejected with updates.
 +
 +        CONSISTENCY
 +
 +           CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.consistency_level])
 +            return
 +
 +        self.consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Consistency level set to %s.' % (level.upper(),)
 +
 +    def do_serial(self, parsed):
 +        """
 +        SERIAL CONSISTENCY [cqlsh only]
 +
 +           Overrides serial consistency level (default level is SERIAL).
 +
 +        SERIAL CONSISTENCY <level>
 +
 +           Sets consistency level for future conditional updates.
 +
 +           Valid consistency levels:
 +
 +           SERIAL, LOCAL_SERIAL.
 +
 +        SERIAL CONSISTENCY
 +
 +           SERIAL CONSISTENCY with no arguments shows the current consistency level.
 +        """
 +        level = parsed.get_binding('level')
 +        if level is None:
 +            print 'Current serial consistency level is %s.' % (cassandra.ConsistencyLevel.value_to_name[self.serial_consistency_level])
 +            return
 +
 +        self.serial_consistency_level = cassandra.ConsistencyLevel.name_to_value[level.upper()]
 +        print 'Serial consistency level set to %s.' % (level.upper(),)
 +
 +    def do_login(self, parsed):
 +        """
 +        LOGIN [cqlsh only]
 +
 +           Changes login information without requiring restart.
 +
 +        LOGIN <username> (<password>)
 +
 +           Login using the specified username. If password is specified, it will be used
 +           otherwise, you will be prompted to enter.
 +        """
 +        username = parsed.get_binding('username')
 +        password = parsed.get_binding('password')
 +        if password is None:
 +            password = getpass.getpass()
 +        else:
 +            password = password[1:-1]
 +
 +        auth_provider = PlainTextAuthProvider(username=username, password=password)
 +
 +        conn = Cluster(contact_points=(self.hostname,), port=self.port, cql_version=self.conn.cql_version,
 +                       protocol_version=self.conn.protocol_version,
 +                       auth_provider=auth_provider,
 +                       ssl_options=self.conn.ssl_options,
 +                       load_balancing_policy=WhiteListRoundRobinPolicy([self.hostname]),
 +                       control_connection_timeout=self.conn.connect_timeout,
 +                       connect_timeout=self.conn.connect_timeout)
 +
 +        if self.current_keyspace:
 +            session = conn.connect(self.current_keyspace)
 +        else:
 +            session = conn.connect()
 +
 +        # Copy session properties
 +        session.default_timeout = self.session.default_timeout
 +        session.row_factory = self.session.row_factory
 +        session.default_consistency_level = self.session.default_consistency_level
 +        session.max_trace_wait = self.session.max_trace_wait
 +
 +        # Update after we've connected in case we fail to authenticate
 +        self.conn = conn
 +        self.auth_provider = auth_provider
 +        self.username = username
 +        self.session = session
 +
 +    def do_exit(self, parsed=None):
 +        """
 +        EXIT/QUIT [cqlsh only]
 +
 +        Exits cqlsh.
 +        """
 +        self.stop = True
 +        if self.owns_connection:
 +            self.conn.shutdown()
 +    do_quit = do_exit
 +
 +    def do_clear(self, parsed):
 +        """
 +        CLEAR/CLS [cqlsh only]
 +
 +        Clears the console.
 +        """
 +        import subprocess
 +

<TRUNCATED>

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[12/23] cassandra git commit: Merge branch 'cassandra-2.1' into cassandra-2.2

Posted by ja...@apache.org.
http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/copyutil.py
index b72b517,85e2678..c9c5829
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@@ -150,37 -129,28 +150,37 @@@ class SendingChannel(object)
      def num_pending(self):
          return self.pending_messages.qsize() if self.pending_messages else 0
  
 -    def recv(self):
 -        with self.rlock:
 -            return self.reader.recv()
 +    def close(self):
 +        self.pipe.close()
 +
 +
 +class SendingChannels(object):
 +    """
 +    A group of one way channels for sending messages.
 +    """
 +    def __init__(self, num_channels):
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [SendingChannel(p) for p in self.pipes]
 +        self.num_channels = num_channels
  
      def close(self):
 -        self.reader.close()
 -        self.writer.close()
 +        for ch in self.channels:
 +            try:
 +                ch.close()
-             except:
++            except Exception:
 +                pass
  
  
 -class OneWayChannels(object):
 +class ReceivingChannels(object):
      """
 -    A group of one way channels.
 +    A group of one way channels for receiving messages.
      """
      def __init__(self, num_channels):
 -        self.channels = [OneWayChannel() for _ in xrange(num_channels)]
 -        self._readers = [ch.reader for ch in self.channels]
 -        self._rlocks = [ch.rlock for ch in self.channels]
 -        self._rlocks_by_readers = dict([(ch.reader, ch.rlock) for ch in self.channels])
 +        self.pipes = [OneWayPipe() for _ in xrange(num_channels)]
 +        self.channels = [ReceivingChannel(p) for p in self.pipes]
 +        self._readers = [p.reader for p in self.pipes]
 +        self._rlocks = [p.rlock for p in self.pipes]
 +        self._rlocks_by_readers = dict([(p.reader, p.rlock) for p in self.pipes])
          self.num_channels = num_channels
  
          self.recv = self.recv_select if IS_LINUX else self.recv_polling

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/cql3handling.py
index 897ee16,012e383..8224ad9
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@@ -34,7 -34,8 +34,8 @@@ class UnexpectedTableStructure(UserWarn
      def __str__(self):
          return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
  
+ 
 -SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 +SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth', 'system_distributed')
  NONALTERBALE_KEYSPACES = ('system')
  
  
@@@ -785,10 -691,17 +792,11 @@@ def select_relation_lhs_completer(ctxt
              filterable.add(layout.clustering_key[num].name)
          else:
              break
 -    for cd in layout.columns.values():
 -        if cd.index:
 -            filterable.add(cd.name)
 +    for idx in layout.indexes.itervalues():
 +        filterable.add(idx.index_options["target"])
      return map(maybe_escape_name, filterable)
  
+ 
 -@completer_for('selectClause', 'star')
 -def select_count_star_completer(ctxt, cass):
 -    return ['*']
 -
 -
  explain_completion('selector', 'colname')
  
  syntax_rules += r'''
@@@ -1178,12 -1076,11 +1193,13 @@@ explain_completion('createUserTypeState
  
  @completer_for('createIndexStatement', 'col')
  def create_index_col_completer(ctxt, cass):
 +    """ Return the columns for which an index doesn't exist yet. """
      layout = get_table_meta(ctxt, cass)
 -    colnames = [cd.name for cd in layout.columns.values() if not cd.index]
 +    idx_targets = [idx.index_options["target"] for idx in layout.indexes.itervalues()]
 +    colnames = [cd.name for cd in layout.columns.values() if cd.name not in idx_targets]
      return map(maybe_escape_name, colnames)
  
+ 
  syntax_rules += r'''
  <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                            ;
@@@ -1403,20 -1246,6 +1421,21 @@@ def username_name_completer(ctxt, cass)
      return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
  
  
 +@completer_for('rolename', 'role')
 +def rolename_completer(ctxt, cass):
 +    def maybe_quote(name):
 +        if CqlRuleSet.is_valid_cql3_name(name):
 +            return name
 +        return "'%s'" % name
 +
 +    # disable completion for CREATE ROLE.
 +    if ctxt.matched[0][1].upper() == 'CREATE':
 +        return [Hint('<rolename>')]
 +
 +    session = cass.session
 +    return [maybe_quote(row[0].replace("'", "''")) for row in session.execute("LIST ROLES")]
 +
++
  syntax_rules += r'''
  <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                 "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/cassandra/blob/503aec74/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --cc pylib/cqlshlib/formatting.py
index dcd08da,eac1810..f88fc5d
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@@ -53,7 -50,9 +54,8 @@@ def _make_turn_bits_red_f(color1, color
          return color1 + txt + color2
      return _turn_bits_red
  
+ 
  default_null_placeholder = 'null'
 -default_time_format = ''
  default_float_precision = 3
  default_colormap = DEFAULT_VALUE_COLORS
  empty_colormap = defaultdict(lambda: '')
@@@ -97,24 -96,7 +99,25 @@@ def color_text(bval, colormap, displayw
          displaywidth -= bval.count(r'\\')
      return FormattedValue(bval, coloredval, displaywidth)
  
+ 
 +DEFAULT_NANOTIME_FORMAT = '%H:%M:%S.%N'
 +DEFAULT_DATE_FORMAT = '%Y-%m-%d'
 +DEFAULT_TIMESTAMP_FORMAT = '%Y-%m-%d %H:%M:%S%z'
 +
 +if platform.system() == 'Windows':
 +    DEFAULT_TIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
 +
 +
 +class DateTimeFormat():
 +
 +    def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT,
 +                 nanotime_format=DEFAULT_NANOTIME_FORMAT, timezone=None):
 +        self.timestamp_format = timestamp_format
 +        self.date_format = date_format
 +        self.nanotime_format = nanotime_format
 +        self.timezone = timezone
 +
 +
  def format_value_default(val, colormap, **_):
      val = str(val)
      escapedval = val.replace('\\', '\\\\')
@@@ -146,8 -129,10 +150,10 @@@ def formatter_for(typname)
  
  @formatter_for('bytearray')
  def format_value_blob(val, colormap, **_):
 -    bval = '0x' + binascii.hexlify(str(val))
 +    bval = '0x' + binascii.hexlify(val)
      return colorme(bval, colormap, 'blob')
+ 
+ 
  formatter_for('buffer')(format_value_blob)
  
  
@@@ -311,14 -290,18 +320,16 @@@ def format_value_tuple(val, encoding, c
  
  
  @formatter_for('set')
 -def format_value_set(val, encoding, colormap, time_format, float_precision, nullval,
 +def format_value_set(val, encoding, colormap, date_time_format, float_precision, nullval,
                       decimal_sep, thousands_sep, boolean_styles, **_):
      return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
 -                                    time_format, float_precision, nullval,
 +                                    date_time_format, float_precision, nullval,
                                      decimal_sep, thousands_sep, boolean_styles)
+ 
+ 
  formatter_for('frozenset')(format_value_set)
 -# This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 -# and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
 -formatter_for('SortedSet')(format_value_set)
  formatter_for('sortedset')(format_value_set)
 +formatter_for('SortedSet')(format_value_set)
  
  
  @formatter_for('dict')


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org


[03/23] cassandra git commit: More PEP8 compliance for cqlsh

Posted by ja...@apache.org.
More PEP8 compliance for cqlsh

patch by Michael Kjellman; reviewed by Jay Zhuang for CASSANDRA-14021


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

Branch: refs/heads/trunk
Commit: f8d73a3acb00d807d09aa33e1612c89389b18480
Parents: d4fd82b
Author: Michael Kjellman <kj...@apple.com>
Authored: Tue Nov 14 20:51:37 2017 -0800
Committer: Jason Brown <ja...@gmail.com>
Committed: Mon Jan 15 05:56:44 2018 -0800

----------------------------------------------------------------------
 CHANGES.txt                    |  2 +-
 bin/cqlsh                      |  4 ++++
 pylib/cqlshlib/copyutil.py     |  6 +++---
 pylib/cqlshlib/cql3handling.py | 20 ++++++++++++++++++++
 pylib/cqlshlib/displaying.py   |  1 +
 pylib/cqlshlib/formatting.py   | 13 +++++++++++++
 pylib/cqlshlib/pylexotron.py   |  1 +
 pylib/cqlshlib/wcwidth.py      |  3 +++
 8 files changed, 46 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index b4e6f75..6e1ca85 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,5 @@
 2.1.20
- * 
+ * More PEP8 compliance for cqlsh (CASSANDRA-14021)
 
 2.1.19
  * Add storage port options to sstableloader (CASSANDRA-13844)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 6317ec9..30840db 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -83,6 +83,7 @@ def find_zip(libprefix):
         if zips:
             return max(zips)   # probably the highest version, if multiple
 
+
 cql_zip = find_zip(CQL_LIB_PREFIX)
 if cql_zip:
     ver = os.path.splitext(os.path.basename(cql_zip))[0][len(CQL_LIB_PREFIX):]
@@ -522,6 +523,8 @@ def show_warning_without_quoting_line(message, category, filename, lineno, file=
         file.write(warnings.formatwarning(message, category, filename, lineno, line=''))
     except IOError:
         pass
+
+
 warnings.showwarning = show_warning_without_quoting_line
 warnings.filterwarnings('always', category=cql3handling.UnexpectedTableStructure)
 
@@ -2213,6 +2216,7 @@ def main(options, hostname, port):
     if batch_mode and shell.statement_error:
         sys.exit(2)
 
+
 # always call this regardless of module name: when a sub-process is spawned
 # on Windows then the module name is not __main__, see CASSANDRA-9304
 insert_driver_hooks()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/copyutil.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/copyutil.py b/pylib/cqlshlib/copyutil.py
index 3a45353..85e2678 100644
--- a/pylib/cqlshlib/copyutil.py
+++ b/pylib/cqlshlib/copyutil.py
@@ -191,7 +191,7 @@ class OneWayChannels(object):
         for ch in self.channels:
             try:
                 ch.close()
-            except:
+            except Exception:
                 pass
 
 
@@ -1967,8 +1967,8 @@ class ImportConversion(object):
             pk_values = []
             for i in partition_key_indexes:
                 val = serialize(i, row[i])
-                l = len(val)
-                pk_values.append(struct.pack(">H%dsB" % l, l, val, 0))
+                length = len(val)
+                pk_values.append(struct.pack(">H%dsB" % length, length, val, 0))
             return b"".join(pk_values)
 
         if len(partition_key_indexes) == 1:

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/cql3handling.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/cql3handling.py b/pylib/cqlshlib/cql3handling.py
index 029e0c7..012e383 100644
--- a/pylib/cqlshlib/cql3handling.py
+++ b/pylib/cqlshlib/cql3handling.py
@@ -34,6 +34,7 @@ class UnexpectedTableStructure(UserWarning):
     def __str__(self):
         return 'Unexpected table structure; may not translate correctly to CQL. ' + self.msg
 
+
 SYSTEM_KEYSPACES = ('system', 'system_traces', 'system_auth')
 NONALTERBALE_KEYSPACES = ('system')
 
@@ -109,6 +110,7 @@ class Cql3ParsingRuleSet(CqlParsingRuleSet):
             cqlword = cqlword[1:-1].replace("''", "'")
         return cqlword
 
+
 CqlRuleSet = Cql3ParsingRuleSet()
 
 # convenience for remainder of module
@@ -306,6 +308,7 @@ def prop_equals_completer(ctxt, cass):
             return ()
     return ['=']
 
+
 completer_for('property', 'propeq')(prop_equals_completer)
 
 
@@ -529,6 +532,7 @@ def ks_name_completer(ctxt, cass):
 def cf_ks_name_completer(ctxt, cass):
     return [maybe_escape_name(ks) + '.' for ks in cass.get_keyspace_names()]
 
+
 completer_for('columnFamilyName', 'ksname')(cf_ks_name_completer)
 
 
@@ -538,6 +542,7 @@ def cf_ks_dot_completer(ctxt, cass):
         return ['.']
     return []
 
+
 completer_for('columnFamilyName', 'dot')(cf_ks_dot_completer)
 
 
@@ -554,6 +559,7 @@ def cf_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, cfnames)
 
+
 completer_for('userTypeName', 'ksname')(cf_ks_name_completer)
 
 completer_for('userTypeName', 'dot')(cf_ks_dot_completer)
@@ -606,6 +612,7 @@ def working_on_keyspace(ctxt):
         return True
     return False
 
+
 syntax_rules += r'''
 <useStatement> ::= "USE" <keyspaceName>
                  ;
@@ -694,6 +701,7 @@ def select_relation_lhs_completer(ctxt, cass):
 def select_count_star_completer(ctxt, cass):
     return ['*']
 
+
 explain_completion('selector', 'colname')
 
 syntax_rules += r'''
@@ -770,6 +778,7 @@ def insert_option_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <updateStatement> ::= "UPDATE" cf=<columnFamilyName>
                         ( "USING" [updateopt]=<usingOption>
@@ -863,6 +872,7 @@ def update_indexbracket_completer(ctxt, cass):
         return ['[']
     return []
 
+
 syntax_rules += r'''
 <deleteStatement> ::= "DELETE" ( <deleteSelector> ( "," <deleteSelector> )* )?
                         "FROM" cf=<columnFamilyName>
@@ -890,6 +900,7 @@ def delete_delcol_completer(ctxt, cass):
     layout = get_table_meta(ctxt, cass)
     return map(maybe_escape_name, regular_column_names(layout))
 
+
 syntax_rules += r'''
 <batchStatement> ::= "BEGIN" ( "UNLOGGED" | "COUNTER" )? "BATCH"
                         ( "USING" [batchopt]=<usingOption>
@@ -912,6 +923,7 @@ def batch_opt_completer(ctxt, cass):
         opts.discard(opt.split()[0])
     return opts
 
+
 syntax_rules += r'''
 <truncateStatement> ::= "TRUNCATE" ("COLUMNFAMILY" | "TABLE")? cf=<columnFamilyName>
                       ;
@@ -931,6 +943,7 @@ def create_ks_wat_completer(ctxt, cass):
         return ['KEYSPACE']
     return ['KEYSPACE', 'SCHEMA']
 
+
 syntax_rules += r'''
 <createColumnFamilyStatement> ::= "CREATE" wat=( "COLUMNFAMILY" | "TABLE" ) ("IF" "NOT" "EXISTS")?
                                     ( ks=<nonSystemKeyspaceName> dot="." )? cf=<cfOrKsName>
@@ -979,6 +992,7 @@ def create_cf_wat_completer(ctxt, cass):
         return ['TABLE']
     return ['TABLE', 'COLUMNFAMILY']
 
+
 explain_completion('createColumnFamilyStatement', 'cf', '<new_table_name>')
 explain_completion('compositeKeyCfSpec', 'newcolname', '<new_column_name>')
 
@@ -1033,6 +1047,7 @@ def create_cf_composite_primary_key_comma_completer(ctxt, cass):
         return ()
     return [',']
 
+
 syntax_rules += r'''
 
 <idxName> ::= <identifier>
@@ -1065,6 +1080,7 @@ def create_index_col_completer(ctxt, cass):
     colnames = [cd.name for cd in layout.columns.values() if not cd.index]
     return map(maybe_escape_name, colnames)
 
+
 syntax_rules += r'''
 <dropKeyspaceStatement> ::= "DROP" "KEYSPACE" ("IF" "EXISTS")? ksname=<nonSystemKeyspaceName>
                           ;
@@ -1113,6 +1129,7 @@ def idx_ks_idx_name_completer(ctxt, cass):
         raise
     return map(maybe_escape_name, idxnames)
 
+
 syntax_rules += r'''
 <alterTableStatement> ::= "ALTER" wat=( "COLUMNFAMILY" | "TABLE" ) cf=<columnFamilyName>
                                <alterInstructions>
@@ -1149,6 +1166,7 @@ def alter_type_field_completer(ctxt, cass):
     fields = [tuple[0] for tuple in layout]
     return map(maybe_escape_name, fields)
 
+
 explain_completion('alterInstructions', 'newcol', '<new_column_name>')
 explain_completion('alterTypeInstructions', 'newcol', '<new_field_name>')
 
@@ -1227,6 +1245,7 @@ def username_name_completer(ctxt, cass):
     session = cass.session
     return [maybe_quote(row.values()[0].replace("'", "''")) for row in session.execute("LIST USERS")]
 
+
 syntax_rules += r'''
 <createTriggerStatement> ::= "CREATE" "TRIGGER" ( "IF" "NOT" "EXISTS" )? <cident>
                                "ON" cf=<columnFamilyName> "USING" class=<stringLiteral>
@@ -1251,6 +1270,7 @@ def alter_type_field_completer(ctxt, cass):
     names = get_trigger_names(ctxt, cass)
     return map(maybe_escape_name, names)
 
+
 # END SYNTAX/COMPLETION RULE DEFINITIONS
 
 CqlRuleSet.append_rules(syntax_rules)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/displaying.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/displaying.py b/pylib/cqlshlib/displaying.py
index 7b260c2..09068ca 100644
--- a/pylib/cqlshlib/displaying.py
+++ b/pylib/cqlshlib/displaying.py
@@ -99,6 +99,7 @@ class FormattedValue:
         """
         return self.coloredval + self._pad(width, fill)
 
+
 DEFAULT_VALUE_COLORS = dict(
     default=YELLOW,
     text=YELLOW,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/formatting.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/formatting.py b/pylib/cqlshlib/formatting.py
index abb4896..eac1810 100644
--- a/pylib/cqlshlib/formatting.py
+++ b/pylib/cqlshlib/formatting.py
@@ -38,6 +38,7 @@ def _show_control_chars(match):
         txt = txt[1:-1]
     return txt
 
+
 bits_to_turn_red_re = re.compile(r'\\([^uUx]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2}|U[0-9a-fA-F]{8})')
 
 
@@ -49,6 +50,7 @@ def _make_turn_bits_red_f(color1, color2):
         return color1 + txt + color2
     return _turn_bits_red
 
+
 default_null_placeholder = 'null'
 default_time_format = ''
 default_float_precision = 3
@@ -101,6 +103,7 @@ def format_value_default(val, colormap, **_):
     bval = controlchars_re.sub(_show_control_chars, escapedval)
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap)
 
+
 # Mapping cql type base names ("int", "map", etc) to formatter functions,
 # making format_value a generic function
 _formatters = {}
@@ -128,6 +131,8 @@ def formatter_for(typname):
 def format_value_blob(val, colormap, **_):
     bval = '0x' + binascii.hexlify(str(val))
     return colorme(bval, colormap, 'blob')
+
+
 formatter_for('buffer')(format_value_blob)
 
 
@@ -188,6 +193,7 @@ def format_floating_point_type(val, colormap, float_precision, decimal_sep=None,
 
     return colorme(bval, colormap, 'float')
 
+
 formatter_for('float')(format_floating_point_type)
 
 
@@ -196,6 +202,7 @@ def format_integer_type(val, colormap, thousands_sep=None, **_):
     bval = format_integer_with_thousands_sep(val, thousands_sep) if thousands_sep else str(val)
     return colorme(bval, colormap, 'int')
 
+
 # We can get rid of this in cassandra-2.2
 if sys.version_info >= (2, 7):
     def format_integer_with_thousands_sep(val, thousands_sep=','):
@@ -221,6 +228,7 @@ def format_value_timestamp(val, colormap, time_format, quote=False, **_):
         bval = "'%s'" % bval
     return colorme(bval, colormap, 'timestamp')
 
+
 formatter_for('datetime')(format_value_timestamp)
 
 
@@ -241,6 +249,7 @@ def format_value_text(val, encoding, colormap, quote=False, **_):
 
     return bval if colormap is NO_COLOR_MAP else color_text(bval, colormap, wcwidth.wcswidth(bval.decode(encoding)))
 
+
 # name alias
 formatter_for('unicode')(format_value_text)
 
@@ -286,6 +295,8 @@ def format_value_set(val, encoding, colormap, time_format, float_precision, null
     return format_simple_collection(sorted(val), '{', '}', encoding, colormap,
                                     time_format, float_precision, nullval,
                                     decimal_sep, thousands_sep, boolean_styles)
+
+
 formatter_for('frozenset')(format_value_set)
 # This code is used by cqlsh (bundled driver version 2.7.2 using sortedset),
 # and the dtests, which use whichever driver on the machine, i.e. 3.0.0 (SortedSet)
@@ -314,6 +325,8 @@ def format_value_map(val, encoding, colormap, time_format, float_precision, null
         + 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)
 formatter_for('OrderedMap')(format_value_map)
 formatter_for('OrderedMapSerializedKey')(format_value_map)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/pylexotron.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/pylexotron.py b/pylib/cqlshlib/pylexotron.py
index 9cf0f4e..7b11eac 100644
--- a/pylib/cqlshlib/pylexotron.py
+++ b/pylib/cqlshlib/pylexotron.py
@@ -518,6 +518,7 @@ class ParsingRuleSet:
         pattern.match(ctxt, completions)
         return completions
 
+
 import sys
 
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/f8d73a3a/pylib/cqlshlib/wcwidth.py
----------------------------------------------------------------------
diff --git a/pylib/cqlshlib/wcwidth.py b/pylib/cqlshlib/wcwidth.py
index bc55c31..985fd41 100644
--- a/pylib/cqlshlib/wcwidth.py
+++ b/pylib/cqlshlib/wcwidth.py
@@ -94,6 +94,7 @@ def bisearch(ucs, table):
             return 1
     return 0
 
+
 # The following two functions define the column width of an ISO 10646
 # character as follows:
 #
@@ -178,6 +179,7 @@ combining = (
     (0xE0100, 0xE01EF)
 )
 
+
 # sorted list of non-overlapping intervals of East Asian Ambiguous
 # characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c"
 ambiguous = (
@@ -321,6 +323,7 @@ def wcwidth_cjk(c):
 def wcswidth_cjk(s):
     return mk_wcswidth_cjk(map(ord, s))
 
+
 if __name__ == "__main__":
     samples = (
         ('MUSIC SHARP SIGN', 1),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org