You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by br...@apache.org on 2012/03/27 21:31:19 UTC

[5/11] git commit: cqlsh: check for cql driver colname type support, overhaul column coloring Patch by paul cannon, reviewed by brandonwilliams for CASSANDRA-4003

cqlsh: check for cql driver colname type support, overhaul column coloring
Patch by paul cannon, reviewed by brandonwilliams for CASSANDRA-4003


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

Branch: refs/heads/cassandra-1.0
Commit: 270d0165daab39734ac35142b2e61ea7fa194bc2
Parents: 9fc1d5c
Author: Brandon Williams <br...@apache.org>
Authored: Tue Mar 27 14:29:10 2012 -0500
Committer: Brandon Williams <br...@apache.org>
Committed: Tue Mar 27 14:29:10 2012 -0500

----------------------------------------------------------------------
 bin/cqlsh |  107 +++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 75 insertions(+), 32 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/270d0165/bin/cqlsh
----------------------------------------------------------------------
diff --git a/bin/cqlsh b/bin/cqlsh
index 8a9d98c..7431bee 100755
--- a/bin/cqlsh
+++ b/bin/cqlsh
@@ -103,6 +103,7 @@ BLUE = '\033[0;1;34m'
 MAGENTA = '\033[0;1;35m'
 CYAN = '\033[0;1;36m'
 WHITE = '\033[0;1;37m'
+DARK_MAGENTA = '\033[0;35m'
 ANSI_RESET = '\033[0m'
 
 CQL_ERRORS = (cql.Error,)
@@ -298,55 +299,83 @@ def _show_control_chars(match):
 
 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})')
 
-def _turn_bits_red(match):
-    txt = match.group(0)
-    if txt == '\\\\':
-        return '\\'
-    return RED + txt + YELLOW
-
-def format_value(val, casstype, output_encoding, addcolor=False, time_format='', float_precision=3):
-    color = YELLOW
+def _make_turn_bits_red_f(color1, color2):
+    def _turn_bits_red(match):
+        txt = match.group(0)
+        if txt == '\\\\':
+            return '\\'
+        return color1 + txt + color2
+    return _turn_bits_red
+
+DEFAULT_VALUE_COLORS = dict(
+    default=YELLOW,
+    text=YELLOW,
+    error=RED,
+    hex=DARK_MAGENTA,
+    timestamp=GREEN,
+    int=GREEN,
+    float=GREEN,
+    decimal=GREEN,
+    boolean=GREEN,
+    uuid=GREEN,
+)
+
+COLUMN_NAME_COLORS = defaultdict(lambda: MAGENTA,
+    error=RED,
+    hex=DARK_MAGENTA,
+)
+
+def unix_time_from_uuid1(u):
+    return (u.get_time() - 0x01B21DD213814000) / 10000000.0
+
+def format_value(val, casstype, output_encoding, addcolor=False, time_format='',
+                 float_precision=3, colormap=DEFAULT_VALUE_COLORS):
+    color = colormap['default']
     coloredval = None
     displaywidth = None
 
     if val is None:
         bval = 'null'
-        color = RED
+        color = colormap['error']
     elif isinstance(val, DecodeError):
         casstype = 'BytesType'
         bval = repr(val.thebytes)
-        color = RED
+        color = colormap['hex']
     elif casstype == 'UTF8Type':
         escapedval = val.replace(u'\\', u'\\\\')
         escapedval = unicode_controlchars_re.sub(_show_control_chars, escapedval)
         bval = escapedval.encode(output_encoding, 'backslashreplace')
         displaywidth = wcwidth.wcswidth(bval.decode(output_encoding))
         if addcolor:
-            coloredval = YELLOW + bits_to_turn_red_re.sub(_turn_bits_red, bval) + ANSI_RESET
-    elif casstype == 'DateType':
+            tbr = _make_turn_bits_red_f(colormap['hex'], colormap['text'])
+            coloredval = colormap['text'] + bits_to_turn_red_re.sub(tbr, bval) + ANSI_RESET
+    elif casstype in ('DateType', 'TimeUUIDType'):
+        if casstype == 'TimeUUIDType':
+            val = unix_time_from_uuid1(val)
         timestamp = time.localtime(val)
         bval = time.strftime(time_format, timestamp)
-        color = GREEN
-    elif casstype in ('LongType', 'Int32Type', 'IntegerType'):
+        color = colormap['timestamp']
+    elif casstype in ('LongType', 'Int32Type', 'IntegerType', 'CounterColumnType'):
         # base-10 only for now; support others?
         bval = str(val)
-        color = GREEN
+        color = colormap['int']
     elif casstype in ('FloatType', 'DoubleType'):
         bval = '%.*g' % (float_precision, val)
-        color = GREEN
+        color = colormap['float']
     elif casstype in ('DecimalType', 'UUIDType', 'BooleanType'):
         # let python do these for us
         bval = str(val)
-        color = GREEN
+        color = colormap[cql_typename(casstype)]
     elif casstype == 'BytesType':
         bval = ''.join('%02x' % ord(c) for c in val)
-        color = RED
+        color = colormap['hex']
     else:
         # AsciiType is the only other one known right now, but handle others
         escapedval = val.replace('\\', '\\\\')
         bval = controlchars_re.sub(_show_control_chars, escapedval)
         if addcolor:
-            coloredval = YELLOW + bits_to_turn_red_re.sub(_turn_bits_red, bval) + ANSI_RESET
+            tbr = _make_turn_bits_red_f(colormap['hex'], colormap['text'])
+            coloredval = colormap['text'] + bits_to_turn_red_re.sub(tbr, bval) + ANSI_RESET
 
     if displaywidth is None:
         displaywidth = len(bval)
@@ -394,22 +423,15 @@ class Shell(cmd.Cmd):
         else:
             self.prompt = ""
 
-    def myformat_value(self, val, casstype):
+    def myformat_value(self, val, casstype, **kwargs):
         if isinstance(val, DecodeError):
             self.decoding_errors.append(val)
         return format_value(val, casstype, self.output_codec.name,
                             addcolor=self.color, time_format=self.display_time_format,
-                            float_precision=self.display_float_precision)
+                            float_precision=self.display_float_precision, **kwargs)
 
-    def myformat_colname(self, name):
-        if isinstance(name, DecodeError):
-            self.decoding_errors.append(name)
-            name = str(name)
-            color = RED
-        else:
-            color = MAGENTA
-        return FormattedValue(name, self.applycolor(name, color),
-                              wcwidth.wcswidth(name.decode(self.output_codec.name)))
+    def myformat_colname(self, name, nametype):
+        return self.myformat_value(name, nametype, colormap=COLUMN_NAME_COLORS)
 
     def report_connection(self):
         self.show_host()
@@ -701,6 +723,25 @@ class Shell(cmd.Cmd):
             decoder = partial(decoder, overrides=overrides)
         return decoder
 
+    def get_nametype(self, cursor, num):
+        """
+        Determine the Cassandra type of a column name from the current row of
+        query results on the given cursor. The column in question is given by
+        its zero-based ordinal number within the row.
+
+        This is necessary to differentiate some things like ascii vs. blob hex.
+        """
+
+        if getattr(cursor, 'supports_name_info', False):
+            return cursor.name_info[num][1]
+
+        # This is a pretty big hack, but necessary until we can rely on
+        # python-cql 1.0.10 being around.
+        row = cursor.result[cursor.rs_idx - 1]
+        col = row.columns[num]
+        schema = cursor.decoder.schema
+        return schema.name_types.get(col.name, schema.default_name_type)
+
     def print_count_result(self, cursor):
         if not cursor.result:
             return
@@ -738,7 +779,8 @@ class Shell(cmd.Cmd):
 
     def print_static_result(self, cursor):
         colnames, coltypes = zip(*cursor.description)[:2]
-        formatted_names = map(self.myformat_colname, colnames)
+        colnames_t = [(name, self.get_nametype(cursor, n)) for (n, name) in enumerate(colnames)]
+        formatted_names = [self.myformat_colname(name, nametype) for (name, nametype) in colnames_t]
         formatted_data = [map(self.myformat_value, row, coltypes) for row in cursor]
 
         # determine column widths
@@ -760,7 +802,8 @@ class Shell(cmd.Cmd):
     def print_dynamic_result(self, cursor):
         for row in cursor:
             colnames, coltypes = zip(*cursor.description)[:2]
-            colnames = [self.myformat_colname(name) for name in colnames]
+            colnames_t = [(name, self.get_nametype(cursor, n)) for (n, name) in enumerate(colnames)]
+            colnames = [self.myformat_colname(name, nametype) for (name, nametype) in colnames_t]
             colvals = [self.myformat_value(val, casstype) for (val, casstype) in zip(row, coltypes)]
             line = ' | '.join('%s,%s' % (n.coloredval, v.coloredval) for (n, v) in zip(colnames, colvals))
             print ' ' + line