def initialize_logging(self): log_file = self.config["main"]["log_file"] if log_file == "default": log_file = config_location() + "log" ensure_dir_exists(log_file) log_level = self.config["main"]["log_level"] level_map = { "CRITICAL": logging.CRITICAL, "ERROR": logging.ERROR, "WARNING": logging.WARNING, "INFO": logging.INFO, "DEBUG": logging.DEBUG, } # Disable logging if value is NONE by switching to a no-op handler # Set log level to a high value so it doesn't even waste cycles getting called. if log_level.upper() == "NONE": handler = logging.NullHandler() log_level = "CRITICAL" elif dir_path_exists(log_file): handler = logging.FileHandler(log_file) else: self.echo( 'Error: Unable to open the log file "{}".'.format(log_file), err=True, fg="red", ) return formatter = logging.Formatter( "%(asctime)s (%(process)d/%(threadName)s) " "%(name)s %(levelname)s - %(message)s" ) handler.setFormatter(formatter) root_logger = logging.getLogger("litecli") root_logger.addHandler(handler) root_logger.setLevel(level_map[log_level.upper()]) logging.captureWarnings(True) root_logger.debug("Initializing litecli logging.") root_logger.debug("Log file %r.", log_file)
def run_cli(self): iterations = 0 sqlexecute = self.sqlexecute logger = self.logger self.configure_pager() self.refresh_completions() history_file = config_location() + "history" if dir_path_exists(history_file): history = FileHistory(history_file) else: history = None self.echo( 'Error: Unable to open the history file "{}". ' "Your query history will not be saved.".format(history_file), err=True, fg="red", ) key_bindings = cli_bindings(self) if 0 and not self.less_chatty: print("Version:", __version__) print( "Mail: https://groups.google.com/forum/#!forum/litecli-users") print("Github: https://github.com/dbcli/litecli") # print("Home: https://litecli.com") def get_message(): prompt = self.get_prompt(self.prompt_format) if (self.prompt_format == self.default_prompt and len(prompt) > self.max_len_prompt): prompt = self.get_prompt("\\d> ") #print(prompt) return [("class:prompt", '%s> ' % DBNAME)] def get_continuation(width, line_number, is_soft_wrap): continuation = " " * (width - 1) + " " return [("class:continuation", continuation)] def show_suggestion_tip(): return iterations < 2 def one_iteration(text=None): if text is None: try: text = self.prompt_app.prompt() except KeyboardInterrupt: return special.set_expanded_output(False) try: text = self.handle_editor_command(text) except RuntimeError as e: #logger.error("sql: %r, error: %r", text, e) #logger.error("traceback: %r", traceback.format_exc()) self.showerr(e) return if not text.strip(): return if self.destructive_warning: destroy = confirm_destructive_query(text) if destroy is None: pass # Query was not destructive. Nothing to do here. elif destroy is True: self.echo("Your call!") else: self.echo("Wise choice!") return # Keep track of whether or not the query is mutating. In case # of a multi-statement query, the overall query is considered # mutating if any one of the component statements is mutating mutating = False try: logger.debug("sql: %r", text) special.write_tee(self.get_prompt(self.prompt_format) + text) if self.logfile: self.logfile.write("\n# %s\n" % datetime.now()) self.logfile.write(text) self.logfile.write("\n") successful = False start = time() res = sqlexecute.run(text, DBNAME) self.formatter.query = text successful = True result_count = 0 for title, cur, headers, status in res: logger.debug("headers: %r", headers) logger.debug("rows: %r", cur) logger.debug("status: %r", status) threshold = 1000 if is_select(status) and cur and cur.rowcount > threshold: self.echo( "The result set has more than {} rows.".format( threshold), fg="red", ) if not confirm("Do you want to continue?"): self.echo("Aborted!", err=True, fg="red") break if self.auto_vertical_output: max_width = self.prompt_app.output.get_size().columns else: max_width = None formatted = self.format_output( title, cur, headers, special.is_expanded_output(), max_width) t = time() - start try: if result_count > 0: self.echo("") try: self.output(formatted, status) except KeyboardInterrupt: pass self.echo("Time: %0.03fs" % t) except KeyboardInterrupt: pass start = time() result_count += 1 mutating = mutating or is_mutating(status) special.unset_once_if_written() except EOFError as e: raise e except KeyboardInterrupt: # get last connection id connection_id_to_kill = sqlexecute.connection_id logger.debug("connection id to kill: %r", connection_id_to_kill) # Restart connection to the database sqlexecute.connect() try: for title, cur, headers, status in sqlexecute.run( "kill %s" % connection_id_to_kill): status_str = str(status).lower() if status_str.find("ok") > -1: logger.debug( "cancelled query, connection id: %r, sql: %r", connection_id_to_kill, text, ) self.echo("cancelled query", err=True, fg="red") except Exception as e: self.echo( "Encountered error while cancelling query: {}".format( e), err=True, fg="red", ) except NotImplementedError: self.echo("Not Yet Implemented.", fg="yellow") except OperationalError as e: logger.debug("Exception: %r", e) if e.args[0] in (2003, 2006, 2013): logger.debug("Attempting to reconnect.") self.echo("Reconnecting...", fg="yellow") try: sqlexecute.connect() logger.debug("Reconnected successfully.") one_iteration(text) return # OK to just return, cuz the recursion call runs to the end. except OperationalError as e: logger.debug("Reconnect failed. e: %r", e) self.echo(str(e), err=True, fg="red") # If reconnection failed, don't proceed further. return else: #logger.error("sql: %r, error: %r", text, e) #logger.error("traceback: %r", traceback.format_exc()) self.showerr(e) except Exception as e: #logger.error("sql: %r, error: %r", text, e) #logger.error("traceback: %r", traceback.format_exc()) self.showerr(e) else: if is_dropping_database(text, self.sqlexecute.dbname): self.sqlexecute.dbname = None self.sqlexecute.connect() # Refresh the table names and column names if necessary. if need_completion_refresh(text): self.refresh_completions(reset=need_completion_reset(text)) finally: if self.logfile is False: self.echo("Warning: This query was not logged.", err=True, fg="red") query = Query(text, successful, mutating) self.query_history.append(query) get_toolbar_tokens = create_toolbar_tokens_func( self, show_suggestion_tip) if self.wider_completion_menu: complete_style = CompleteStyle.MULTI_COLUMN else: complete_style = CompleteStyle.COLUMN with self._completer_lock: if self.key_bindings == "vi": editing_mode = EditingMode.VI else: editing_mode = EditingMode.EMACS self.prompt_app = PromptSession( lexer=PygmentsLexer(LiteCliLexer), reserve_space_for_menu=self.get_reserved_space(), message=get_message, prompt_continuation=get_continuation, bottom_toolbar=get_toolbar_tokens, complete_style=complete_style, input_processors=[ ConditionalProcessor( processor=HighlightMatchingBracketProcessor( chars="[](){}"), filter=HasFocus(DEFAULT_BUFFER) & ~IsDone(), ) ], tempfile_suffix=".sql", completer=DynamicCompleter(lambda: self.completer), history=history, auto_suggest=AutoSuggestFromHistory(), complete_while_typing=True, multiline=cli_is_multiline(self), style=style_factory(self.syntax_style, self.cli_style), include_default_pygments_style=False, key_bindings=key_bindings, enable_open_in_editor=True, enable_system_prompt=True, enable_suspend=True, editing_mode=editing_mode, search_ignore_case=True, ) try: while True: one_iteration() iterations += 1 except EOFError: special.close_tee() if not self.less_chatty: self.echo("Goodbye!")