Merge branch 'cassandra-2.2' into cassandra-3.0

This commit is contained in:
Joshua McKenzie 2016-02-17 19:23:10 -05:00
commit 5dbab32042
5 changed files with 68 additions and 6 deletions

View File

@ -32,6 +32,7 @@ Merged from 2.1:
* Gossiper#isEnabled is not thread safe (CASSANDRA-11116)
* Avoid major compaction mixing repaired and unrepaired sstables in DTCS (CASSANDRA-11113)
* Make it clear what DTCS timestamp_resolution is used for (CASSANDRA-11041)
* (cqlsh) Support timezone conversion using pytz (CASSANDRA-10397)
3.0.3

View File

@ -672,6 +672,7 @@ class Shell(cmd.Cmd):
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,
@ -721,6 +722,8 @@ class Shell(cmd.Cmd):
self.display_float_precision = display_float_precision
self.display_timezone = display_timezone
# If there is no schema metadata present (due to a schema mismatch), force schema refresh
if not self.conn.metadata.keyspaces:
self.refresh_schema_metadata_best_effort()
@ -807,7 +810,8 @@ class Shell(cmd.Cmd):
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)
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)
@ -2419,6 +2423,7 @@ def read_options(cmdlineargs, environment):
optvalues.field_size_limit = option_with_default(configs.getint, 'csv', 'field_size_limit', csv.field_size_limit())
optvalues.max_trace_wait = option_with_default(configs.getfloat, 'tracing', 'max_trace_wait',
DEFAULT_MAX_TRACE_WAIT)
optvalues.timezone = option_with_default(configs.get, 'ui', 'timezone', None)
optvalues.debug = False
optvalues.file = None
@ -2537,6 +2542,36 @@ def main(options, hostname, port):
sys.stderr.write("Using CQL driver: %s\n" % (cassandra,))
sys.stderr.write("Using connect timeout: %s seconds\n" % (options.connect_timeout,))
# create timezone based on settings, environment or auto-detection
timezone = None
if options.timezone or 'TZ' in os.environ:
try:
import pytz
if options.timezone:
try:
timezone = pytz.timezone(options.timezone)
except:
sys.stderr.write("Warning: could not recognize timezone '%s' specified in cqlshrc\n\n" % (options.timezone))
if 'TZ' in os.environ:
try:
timezone = pytz.timezone(os.environ['TZ'])
except:
sys.stderr.write("Warning: could not recognize timezone '%s' from environment value TZ\n\n" % (os.environ['TZ']))
except ImportError:
sys.stderr.write("Warning: Timezone defined and 'pytz' module for timezone conversion not installed. Timestamps will be displayed in UTC timezone.\n\n")
# try auto-detect timezone if tzlocal is installed
if not timezone:
try:
from tzlocal import get_localzone
timezone = get_localzone()
except ImportError:
# we silently ignore and fallback to UTC unless a custom timestamp format (which likely
# does contain a TZ part) was specified
if options.time_format != DEFAULT_TIMESTAMP_FORMAT:
sys.stderr.write("Warning: custom timestamp format specified in cqlshrc, but local timezone could not be detected.\n" +
"Either install Python 'tzlocal' module for auto-detection or specify client timezone in your cqlshrc.\n\n")
try:
shell = Shell(hostname,
port,
@ -2553,6 +2588,7 @@ def main(options, hostname, port):
display_nanotime_format=options.nanotime_format,
display_date_format=options.date_format,
display_float_precision=options.float_precision,
display_timezone=timezone,
max_trace_wait=options.max_trace_wait,
ssl=options.ssl,
single_statement=options.execute,

View File

@ -32,6 +32,9 @@
;; Used for displaying timestamps (and reading them with COPY)
; datetimeformat = %Y-%m-%d %H:%M:%S%z
;; Display timezone
;timezone = Etc/UTC
;; The number of digits displayed after the decimal point
;; (note that increasing this to large numbers can result in unusual values)
; float_precision = 5

View File

@ -107,10 +107,12 @@ if platform.system() == 'Windows':
class DateTimeFormat():
def __init__(self, timestamp_format=DEFAULT_TIMESTAMP_FORMAT, date_format=DEFAULT_DATE_FORMAT, nanotime_format=DEFAULT_NANOTIME_FORMAT):
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, **_):
@ -234,15 +236,17 @@ formatter_for('int')(format_integer_type)
@formatter_for('datetime')
def format_value_timestamp(val, colormap, date_time_format, quote=False, **_):
bval = strftime(date_time_format.timestamp_format, calendar.timegm(val.utctimetuple()))
bval = strftime(date_time_format.timestamp_format, calendar.timegm(val.utctimetuple()), timezone=date_time_format.timezone)
if quote:
bval = "'%s'" % bval
return colorme(bval, colormap, 'timestamp')
def strftime(time_format, seconds):
tzless_dt = datetime_from_timestamp(seconds)
return tzless_dt.replace(tzinfo=UTC()).strftime(time_format)
def strftime(time_format, seconds, timezone=None):
ret_dt = datetime_from_timestamp(seconds).replace(tzinfo=UTC())
if timezone:
ret_dt = ret_dt.astimezone(timezone)
return ret_dt.strftime(time_format)
@formatter_for('Date')

View File

@ -370,6 +370,24 @@ class TestCqlshOutput(BaseTestCase):
nnnnnnnn
"""),
), env={'TZ': 'Etc/UTC'})
try:
import pytz # test only if pytz is available on PYTHONPATH
self.assertQueriesGiveColoredOutput((
('''select timestampcol from has_all_types where num = 0;''', """
timestampcol
MMMMMMMMMMMM
--------------------------
2012-05-14 09:53:20-0300
GGGGGGGGGGGGGGGGGGGGGGGG
(1 rows)
nnnnnnnn
"""),
), env={'TZ': 'America/Sao_Paulo'})
except ImportError:
pass
def test_boolean_output(self):
self.assertCqlverQueriesGiveColoredOutput((