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
[6/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.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