Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 880AF200BCC for ; Mon, 14 Nov 2016 07:26:26 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 86B48160B06; Mon, 14 Nov 2016 06:26:26 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 5DA76160B0D for ; Mon, 14 Nov 2016 07:26:25 +0100 (CET) Received: (qmail 20318 invoked by uid 500); 14 Nov 2016 06:26:24 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 20241 invoked by uid 99); 14 Nov 2016 06:26:24 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 14 Nov 2016 06:26:24 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id DEA3EDFFAB; Mon, 14 Nov 2016 06:26:23 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: stefania@apache.org To: commits@cassandra.apache.org Date: Mon, 14 Nov 2016 06:26:24 -0000 Message-Id: <08892c11a23e4b6d95ab49faa0b295a4@git.apache.org> In-Reply-To: <3c4fc46b59a748eeabccd9e8439e1484@git.apache.org> References: <3c4fc46b59a748eeabccd9e8439e1484@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/3] cassandra git commit: Move cqlsh syntax rules into separate module and allow easier customization archived-at: Mon, 14 Nov 2016 06:26:26 -0000 Move cqlsh syntax rules into separate module and allow easier customization patch by Eduard Tudenhoefner; reviewed by Stefania Alborghetti for CASSANDRA-12897 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/57881554 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/57881554 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/57881554 Branch: refs/heads/trunk Commit: 578815541a54c7601a4f5b5d3ceff20fc2343b9f Parents: c31463a Author: Eduard Tudenhoefner Authored: Mon Nov 14 09:56:15 2016 +0800 Committer: Stefania Alborghetti Committed: Mon Nov 14 14:24:08 2016 +0800 ---------------------------------------------------------------------- CHANGES.txt | 1 + bin/cqlsh.py | 234 +------------------------- pylib/cqlshlib/cqlshhandling.py | 310 +++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 230 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/57881554/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 7b59c07..a8ef42c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.11 + * Move cqlsh syntax rules into separate module and allow easier customization (CASSANDRA-12897) Merged from 3.0: * Prevent reloading of logback.xml from UDF sandbox (CASSANDRA-12535) http://git-wip-us.apache.org/repos/asf/cassandra/blob/57881554/bin/cqlsh.py ---------------------------------------------------------------------- diff --git a/bin/cqlsh.py b/bin/cqlsh.py index 072ef08..0358c83 100644 --- a/bin/cqlsh.py +++ b/bin/cqlsh.py @@ -165,7 +165,7 @@ 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 import cql3handling, cqlhandling, pylexotron, sslhandling, cqlshhandling from cqlshlib.copyutil import ExportTask, ImportTask from cqlshlib.displaying import (ANSI_RESET, BLUE, COLUMN_NAME_COLORS, CYAN, RED, WHITE, FormattedValue, colorme) @@ -277,232 +277,6 @@ CQL_ERRORS = ( 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''' - ::= - | ( ";" | "\n" ) - ; - - ::= - | - | - | - | - | - | - | - | - | - | - | - | - | - | - ; - - ::= ( "DESCRIBE" | "DESC" ) - ( "FUNCTIONS" - | "FUNCTION" udf= - | "AGGREGATES" - | "AGGREGATE" uda= - | "KEYSPACES" - | "KEYSPACE" ksname=? - | ( "COLUMNFAMILY" | "TABLE" ) cf= - | "INDEX" idx= - | "MATERIALIZED" "VIEW" mv= - | ( "COLUMNFAMILIES" | "TABLES" ) - | "FULL"? "SCHEMA" - | "CLUSTER" - | "TYPES" - | "TYPE" ut= - | (ksname= | cf= | idx= | mv=)) - ; - - ::= "CONSISTENCY" ( level= )? - ; - - ::= "ANY" - | "ONE" - | "TWO" - | "THREE" - | "QUORUM" - | "ALL" - | "LOCAL_QUORUM" - | "EACH_QUORUM" - | "SERIAL" - | "LOCAL_SERIAL" - | "LOCAL_ONE" - ; - - ::= "SERIAL" "CONSISTENCY" ( level= )? - ; - - ::= "SERIAL" - | "LOCAL_SERIAL" - ; - - ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid= ) - ; - - ::= "SOURCE" fname= - ; - - ::= "CAPTURE" ( fname=( | "OFF" ) )? - ; - - ::= "COPY" cf= - ( "(" [colnames]= ( "," [colnames]= )* ")" )? - ( dir="FROM" ( fname= | "STDIN" ) - | dir="TO" ( fname= | "STDOUT" ) ) - ( "WITH" ( "AND" )* )? - ; - - ::= [optnames]=(|) "=" [optvals]= - ; - - ::= - | - | - ; - -# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal - ::= "DEBUG" "THINGS"? - ; - - ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )* - ; - - ::= "TRACING" ( switch=( "ON" | "OFF" ) )? - ; - - ::= "EXPAND" ( switch=( "ON" | "OFF" ) )? - ; - - ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )? - ; - - ::= "LOGIN" username= (password=)? - ; - - ::= "exit" | "quit" - ; - - ::= "CLEAR" | "CLS" - ; - - ::= "?" ; -''' - - -@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', 'TTL'] -COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS', - 'FLOATPRECISION', 'DOUBLEPRECISION'] - - -@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('')] - class NoKeyspaceError(Exception): pass @@ -2513,10 +2287,10 @@ def read_options(cmdlineargs, environment): def setup_cqlruleset(cqlmodule): global cqlruleset cqlruleset = cqlmodule.CqlRuleSet - cqlruleset.append_rules(cqlsh_extra_syntax_rules) - for rulename, termname, func in cqlsh_syntax_completers: + cqlruleset.append_rules(cqlshhandling.cqlsh_extra_syntax_rules) + for rulename, termname, func in cqlshhandling.cqlsh_syntax_completers: cqlruleset.completer_for(rulename, termname)(func) - cqlruleset.commands_end_with_newline.update(my_commands_ending_with_newline) + cqlruleset.commands_end_with_newline.update(cqlshhandling.my_commands_ending_with_newline) def setup_cqldocs(cqlmodule): http://git-wip-us.apache.org/repos/asf/cassandra/blob/57881554/pylib/cqlshlib/cqlshhandling.py ---------------------------------------------------------------------- diff --git a/pylib/cqlshlib/cqlshhandling.py b/pylib/cqlshlib/cqlshhandling.py new file mode 100644 index 0000000..9545876 --- /dev/null +++ b/pylib/cqlshlib/cqlshhandling.py @@ -0,0 +1,310 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import cqlhandling + +# 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_cmd_syntax_rules = r''' + ::= + | ( ";" | "\n" ) + ; +''' + +cqlsh_special_cmd_command_syntax_rules = r''' + ::= + | + | + | + | + | + | + | + | + | + | + | + | + | + | + ; +''' + +cqlsh_describe_cmd_syntax_rules = r''' + ::= ( "DESCRIBE" | "DESC" ) + ( "FUNCTIONS" + | "FUNCTION" udf= + | "AGGREGATES" + | "AGGREGATE" uda= + | "KEYSPACES" + | "KEYSPACE" ksname=? + | ( "COLUMNFAMILY" | "TABLE" ) cf= + | "INDEX" idx= + | "MATERIALIZED" "VIEW" mv= + | ( "COLUMNFAMILIES" | "TABLES" ) + | "FULL"? "SCHEMA" + | "CLUSTER" + | "TYPES" + | "TYPE" ut= + | (ksname= | cf= | idx= | mv=)) + ; +''' + +cqlsh_consistency_cmd_syntax_rules = r''' + ::= "CONSISTENCY" ( level= )? + ; +''' + +cqlsh_consistency_level_syntax_rules = r''' + ::= "ANY" + | "ONE" + | "TWO" + | "THREE" + | "QUORUM" + | "ALL" + | "LOCAL_QUORUM" + | "EACH_QUORUM" + | "SERIAL" + | "LOCAL_SERIAL" + | "LOCAL_ONE" + ; +''' + +cqlsh_serial_consistency_cmd_syntax_rules = r''' + ::= "SERIAL" "CONSISTENCY" ( level= )? + ; +''' + +cqlsh_serial_consistency_level_syntax_rules = r''' + ::= "SERIAL" + | "LOCAL_SERIAL" + ; +''' + +cqlsh_show_cmd_syntax_rules = r''' + ::= "SHOW" what=( "VERSION" | "HOST" | "SESSION" sessionid= ) + ; +''' + +cqlsh_source_cmd_syntax_rules = r''' + ::= "SOURCE" fname= + ; +''' + +cqlsh_capture_cmd_syntax_rules = r''' + ::= "CAPTURE" ( fname=( | "OFF" ) )? + ; +''' + +cqlsh_copy_cmd_syntax_rules = r''' + ::= "COPY" cf= + ( "(" [colnames]= ( "," [colnames]= )* ")" )? + ( dir="FROM" ( fname= | "STDIN" ) + | dir="TO" ( fname= | "STDOUT" ) ) + ( "WITH" ( "AND" )* )? + ; +''' + +cqlsh_copy_option_syntax_rules = r''' + ::= [optnames]=(|) "=" [optvals]= + ; +''' + +cqlsh_copy_option_val_syntax_rules = r''' + ::= + | + | + ; +''' + +cqlsh_debug_cmd_syntax_rules = r''' +# avoiding just "DEBUG" so that this rule doesn't get treated as a terminal + ::= "DEBUG" "THINGS"? + ; +''' + +cqlsh_help_cmd_syntax_rules = r''' + ::= ( "HELP" | "?" ) [topic]=( /[a-z_]*/ )* + ; +''' + +cqlsh_tracing_cmd_syntax_rules = r''' + ::= "TRACING" ( switch=( "ON" | "OFF" ) )? + ; +''' + +cqlsh_expand_cmd_syntax_rules = r''' + ::= "EXPAND" ( switch=( "ON" | "OFF" ) )? + ; +''' + +cqlsh_paging_cmd_syntax_rules = r''' + ::= "PAGING" ( switch=( "ON" | "OFF" | /[0-9]+/) )? + ; +''' + +cqlsh_login_cmd_syntax_rules = r''' + ::= "LOGIN" username= (password=)? + ; +''' + +cqlsh_exit_cmd_syntax_rules = r''' + ::= "exit" | "quit" + ; +''' + +cqlsh_clear_cmd_syntax_rules = r''' + ::= "CLEAR" | "CLS" + ; +''' + +cqlsh_question_mark = r''' + ::= "?" ; +''' + +cqlsh_extra_syntax_rules = cqlsh_cmd_syntax_rules + \ + cqlsh_special_cmd_command_syntax_rules + \ + cqlsh_describe_cmd_syntax_rules + \ + cqlsh_consistency_cmd_syntax_rules + \ + cqlsh_consistency_level_syntax_rules + \ + cqlsh_serial_consistency_cmd_syntax_rules + \ + cqlsh_serial_consistency_level_syntax_rules + \ + cqlsh_show_cmd_syntax_rules + \ + cqlsh_source_cmd_syntax_rules + \ + cqlsh_capture_cmd_syntax_rules + \ + cqlsh_copy_cmd_syntax_rules + \ + cqlsh_copy_option_syntax_rules + \ + cqlsh_copy_option_val_syntax_rules + \ + cqlsh_debug_cmd_syntax_rules + \ + cqlsh_help_cmd_syntax_rules + \ + cqlsh_tracing_cmd_syntax_rules + \ + cqlsh_expand_cmd_syntax_rules + \ + cqlsh_paging_cmd_syntax_rules + \ + cqlsh_login_cmd_syntax_rules + \ + cqlsh_exit_cmd_syntax_rules + \ + cqlsh_clear_cmd_syntax_rules + \ + cqlsh_question_mark + + +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', + 'TTL'] +COPY_TO_OPTIONS = ['ENCODING', 'PAGESIZE', 'PAGETIMEOUT', 'BEGINTOKEN', 'ENDTOKEN', 'MAXOUTPUTSIZE', 'MAXREQUESTS', + 'FLOATPRECISION', 'DOUBLEPRECISION'] + + +@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('')] + + +@cqlsh_syntax_completer('helpCommand', 'topic') +def complete_help(ctxt, cqlsh): + return sorted([t.upper() for t in cqlsh.cqldocs.get_help_topics() + cqlsh.get_help_topics()])