vcli/packages/tabulate.py
def tabulate(tabular_data, headers=[], tablefmt="simple",
             floatfmt="g", numalign="decimal", stralign="left",
             missingval=""):
    """Format a fixed width table for pretty printing.

    >>> print(tabulate([[1, 2.34], [-56, "8.999"], ["2", "10001"]]))
    ---  ---------
      1      2.34
    -56      8.999
      2  10001
    ---  ---------

    The first required argument (`tabular_data`) can be a
    list-of-lists (or another iterable of iterables), a list of named
    tuples, a dictionary of iterables, an iterable of dictionaries,
    a two-dimensional NumPy array, NumPy record array, or a Pandas'
    dataframe.


    Table headers
    -------------

    To print nice column headers, supply the second argument (`headers`):

      - `headers` can be an explicit list of column headers
      - if `headers="firstrow"`, then the first row of data is used
      - if `headers="keys"`, then dictionary keys or column indices are used

    Otherwise a headerless table is produced.

    If the number of headers is less than the number of columns, they
    are supposed to be names of the last columns. This is consistent
    with the plain-text format of R and Pandas' dataframes.

    >>> print(tabulate([["sex","age"],["Alice","F",24],["Bob","M",19]],
    ...       headers="firstrow"))
           sex      age
    -----  -----  -----
    Alice  F         24
    Bob    M         19


    Column alignment
    ----------------

    `tabulate` tries to detect column types automatically, and aligns
    the values properly. By default it aligns decimal points of the
    numbers (or flushes integer numbers to the right), and flushes
    everything else to the left. Possible column alignments
    (`numalign`, `stralign`) are: "right", "center", "left", "decimal"
    (only for `numalign`), and None (to disable alignment).


    Table formats
    -------------

    `floatfmt` is a format specification used for columns which
    contain numeric data with a decimal point.

    `None` values are replaced with a `missingval` string:

    >>> print(tabulate([["spam", 1, None],
    ...                 ["eggs", 42, 3.14],
    ...                 ["other", None, 2.7]], missingval="?"))
    -----  --  ----
    spam    1  ?
    eggs   42  3.14
    other   ?  2.7
    -----  --  ----

    Various plain-text table formats (`tablefmt`) are supported:
    'plain', 'simple', 'grid', 'pipe', 'orgtbl', 'rst', 'mediawiki',
     'latex', and 'latex_booktabs'. Variable `tabulate_formats` contains the list of
    currently supported formats.

    "plain" format doesn't use any pseudographics to draw tables,
    it separates columns with a double space:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                 ["strings", "numbers"], "plain"))
    strings      numbers
    spam         41.9999
    eggs        451

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="plain"))
    spam   41.9999
    eggs  451

    "simple" format is like Pandoc simple_tables:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                 ["strings", "numbers"], "simple"))
    strings      numbers
    ---------  ---------
    spam         41.9999
    eggs        451

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="simple"))
    ----  --------
    spam   41.9999
    eggs  451
    ----  --------

    "grid" is similar to tables produced by Emacs table.el package or
    Pandoc grid_tables:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                ["strings", "numbers"], "grid"))
    +-----------+-----------+
    | strings   |   numbers |
    +===========+===========+
    | spam      |   41.9999 |
    +-----------+-----------+
    | eggs      |  451      |
    +-----------+-----------+

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="grid"))
    +------+----------+
    | spam |  41.9999 |
    +------+----------+
    | eggs | 451      |
    +------+----------+

    "fancy_grid" draws a grid using box-drawing characters:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                ["strings", "numbers"], "fancy_grid"))
    ╒═══════════╤═══════════╕
    │ strings   │   numbers │
    ╞═══════════╪═══════════╡
    │ spam      │   41.9999 │
    ├───────────┼───────────┤
    │ eggs      │  451      │
    ╘═══════════╧═══════════╛

    "pipe" is like tables in PHP Markdown Extra extension or Pandoc
    pipe_tables:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                ["strings", "numbers"], "pipe"))
    | strings   |   numbers |
    |:----------|----------:|
    | spam      |   41.9999 |
    | eggs      |  451      |

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="pipe"))
    |:-----|---------:|
    | spam |  41.9999 |
    | eggs | 451      |

    "orgtbl" is like tables in Emacs org-mode and orgtbl-mode. They
    are slightly different from "pipe" format by not using colons to
    define column alignment, and using a "+" sign to indicate line
    intersections:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                ["strings", "numbers"], "orgtbl"))
    | strings   |   numbers |
    |-----------+-----------|
    | spam      |   41.9999 |
    | eggs      |  451      |


    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="orgtbl"))
    | spam |  41.9999 |
    | eggs | 451      |

    "rst" is like a simple table format from reStructuredText; please
    note that reStructuredText accepts also "grid" tables:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]],
    ...                ["strings", "numbers"], "rst"))
    =========  =========
    strings      numbers
    =========  =========
    spam         41.9999
    eggs        451
    =========  =========

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="rst"))
    ====  ========
    spam   41.9999
    eggs  451
    ====  ========

    "mediawiki" produces a table markup used in Wikipedia and on other
    MediaWiki-based sites:

    >>> print(tabulate([["strings", "numbers"], ["spam", 41.9999], ["eggs", "451.0"]],
    ...                headers="firstrow", tablefmt="mediawiki"))
    {| class="wikitable" style="text-align: left;"
    |+ <!-- caption -->
    |-
    ! strings   !! align="right"|   numbers
    |-
    | spam      || align="right"|   41.9999
    |-
    | eggs      || align="right"|  451
    |}

    "html" produces HTML markup:

    >>> print(tabulate([["strings", "numbers"], ["spam", 41.9999], ["eggs", "451.0"]],
    ...                headers="firstrow", tablefmt="html"))
    <table>
    <tr><th>strings  </th><th style="text-align: right;">  numbers</th></tr>
    <tr><td>spam     </td><td style="text-align: right;">  41.9999</td></tr>
    <tr><td>eggs     </td><td style="text-align: right;"> 451     </td></tr>
    </table>

    "latex" produces a tabular environment of LaTeX document markup:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="latex"))
    \\begin{tabular}{lr}
    \\hline
     spam &  41.9999 \\\\
     eggs & 451      \\\\
    \\hline
    \\end{tabular}

    "latex_booktabs" produces a tabular environment of LaTeX document markup
    using the booktabs.sty package:

    >>> print(tabulate([["spam", 41.9999], ["eggs", "451.0"]], tablefmt="latex_booktabs"))
    \\begin{tabular}{lr}
    \\toprule
     spam &  41.9999 \\\\
     eggs & 451      \\\\
    \\bottomrule
    \end{tabular}
    """
    if tabular_data is None:
        tabular_data = []
    list_of_lists, headers = _normalize_tabular_data(tabular_data, headers)

    # optimization: look for ANSI control codes once,
    # enable smart width functions only if a control code is found
    plain_text = '\n'.join(['\t'.join(map(_text_type, headers))] + \
                            ['\t'.join(map(_text_type, row)) for row in list_of_lists])
    has_invisible = re.search(_invisible_codes, plain_text)
    if has_invisible:
        width_fn = _visible_width
    else:
        width_fn = wcswidth

    # format rows and columns, convert numeric values to strings
    cols = list(zip(*list_of_lists))
    coltypes = list(map(_column_type, cols))
    cols = [[_format(v, ct, floatfmt, missingval) for v in c]
             for c,ct in zip(cols, coltypes)]

    # align columns
    aligns = [numalign if ct in [int,float] else stralign for ct in coltypes]
    minwidths = [width_fn(h) + MIN_PADDING for h in headers] if headers else [0]*len(cols)
    cols = [_align_column(c, a, minw, has_invisible)
            for c, a, minw in zip(cols, aligns, minwidths)]

    if headers:
        # align headers and add headers
        t_cols = cols or [['']] * len(headers)
        t_aligns = aligns or [stralign] * len(headers)
        minwidths = [max(minw, width_fn(c[0])) for minw, c in zip(minwidths, t_cols)]
        headers = [_align_header(h, a, minw)
                   for h, a, minw in zip(headers, t_aligns, minwidths)]
        rows = list(zip(*cols))
    else:
        minwidths = [width_fn(c[0]) for c in cols]
        rows = list(zip(*cols))

    if not isinstance(tablefmt, TableFormat):
        tablefmt = _table_formats.get(tablefmt, _table_formats["simple"])

    return _format_table(tablefmt, headers, rows, minwidths, aligns)
vcli/key_bindings.py
def vcli_bindings(get_vi_mode_enabled, set_vi_mode_enabled):
    """
    Custom key bindings for vcli.
    """
    assert callable(get_vi_mode_enabled)
    assert callable(set_vi_mode_enabled)

    key_binding_manager = KeyBindingManager(
        enable_abort_and_exit_bindings=True,
        enable_open_in_editor=True,
        enable_search=True,
        enable_system_bindings=True,
        enable_vi_mode=Condition(lambda cli: get_vi_mode_enabled()))

    @key_binding_manager.registry.add_binding(Keys.F2)
    def _(event):
        """
        Enable/Disable SmartCompletion Mode.
        """
        _logger.debug('Detected F2 key.')
        buf = event.cli.current_buffer
        buf.completer.smart_completion = not buf.completer.smart_completion

    @key_binding_manager.registry.add_binding(Keys.F3)
    def _(event):
        """
        Enable/Disable Multiline Mode.
        """
        _logger.debug('Detected F3 key.')
        buf = event.cli.current_buffer
        buf.always_multiline = not buf.always_multiline

    @key_binding_manager.registry.add_binding(Keys.F4)
    def _(event):
        """
        Toggle between Vi and Emacs mode.
        """
        _logger.debug('Detected F4 key.')
        set_vi_mode_enabled(not get_vi_mode_enabled())

    @key_binding_manager.registry.add_binding(Keys.Tab)
    def _(event):
        """
        Force autocompletion at cursor.
        """
        _logger.debug('Detected <Tab> key.')
        b = event.cli.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            event.cli.start_completion(select_first=True)

    @key_binding_manager.registry.add_binding(Keys.ControlSpace)
    def _(event):
        """
        Initialize autocompletion at cursor.

        If the autocompletion menu is not showing, display it with the
        appropriate completions for the context.

        If the menu is showing, select the next completion.
        """
        _logger.debug('Detected <C-Space> key.')

        b = event.cli.current_buffer
        if b.complete_state:
            b.complete_next()
        else:
            event.cli.start_completion(select_first=False)

    return key_binding_manager
vcli/packages/vspecial/main.py
NO_QUERY = 0
vcli/packages/expanded.py
def expanded_table(rows, headers):
    header_len = max([len(x) for x in headers])
    max_row_len = 0
    results = []
    sep = u"-[ RECORD {0} ]-------------------------\n"

    padded_headers = [pad(x, header_len) + u" |" for x in headers]
    header_len += 2

    for row in rows:
        row_len = max([len(_text_type(x)) for x in row])
        row_result = []
        if row_len > max_row_len:
            max_row_len = row_len

        for header, value in zip(padded_headers, row):
            row_result.append(u"%s %s" % (header, value))

        results.append('\n'.join(row_result))

    output = []
    for i, result in enumerate(results):
        output.append(sep.format(i))
        output.append(result)
        output.append('\n')

    return ''.join(output)
vcli/packages/vspecial/main.py
class VSpecial(object):

    # Default static commands that don't rely on PGSpecial state are registered
    # via the special_command decorator and stored in default_commands
    default_commands = {}

    def __init__(self):
        self.timing_enabled = True

        self.commands = self.default_commands.copy()

        self.aligned = True
        self.show_header = True
        self.output = sys.stdout
        self.timing_enabled = False
        self.expanded_output = False

        self.register(self.toggle_align, '\\a', '\\a', 'Aligned or unaligned',
                      arg_type=NO_QUERY)
        self.register(self.toggle_header, '\\t', '\\t', 'Toggle header',
                      arg_type=NO_QUERY)
        self.register(self.redirect_output, '\\o', '\\o [FILE]',
                      'Output to file or stdout', arg_type=PARSED_QUERY)
        self.register(self.show_help, '\\?', '\\?', 'Show help',
                      arg_type=NO_QUERY)
        self.register(self.show_help, '\\h', '\\h', 'Show help',
                      arg_type=NO_QUERY)

        self.register(self.toggle_expanded_output, '\\x', '\\x',
                      'Toggle expanded output', arg_type=NO_QUERY)

        self.register(self.toggle_timing, '\\timing', '\\timing',
                      'Toggle timing of commands', arg_type=NO_QUERY)

    def register(self, *args, **kwargs):
        register_special_command(*args, command_dict=self.commands, **kwargs)

    def execute(self, cur, sql):
        commands = self.commands
        command, verbose, pattern = parse_special_command(sql)

        if (command not in commands) and (command.lower() not in commands):
            raise CommandNotFound

        try:
            special_cmd = commands[command]
        except KeyError:
            special_cmd = commands[command.lower()]
            if special_cmd.case_sensitive:
                raise CommandNotFound('Command not found: %s' % command)

        if special_cmd.arg_type == NO_QUERY:
            return special_cmd.handler()
        elif special_cmd.arg_type == PARSED_QUERY:
            return special_cmd.handler(cur=cur, pattern=pattern, verbose=verbose)
        elif special_cmd.arg_type == RAW_QUERY:
            return special_cmd.handler(cur=cur, query=sql)

    def toggle_align(self):
        self.aligned = not self.aligned
        message = 'Output format is '
        if self.aligned:
            message += 'aligned.'
        else:
            message += 'unaligned.'
        return [(None, None, None, message, True)]

    def toggle_header(self):
        self.show_header = not self.show_header
        if self.show_header:
            message = 'Showing '
        else:
            message = 'Hiding '
        message += 'header.'
        return [(None, None, None, message, True)]

    def redirect_output(self, cur=None, pattern=None, verbose=None):
        if os.path.isfile(self.output.name):
            # Close previous output file
            self.output.close()
        if pattern:
            filename = os.path.abspath(pattern)
            self.output = codecs.open(filename, 'w', encoding='utf-8')
            message = 'Redirecting output to file.'
        else:
            self.output = sys.stdout
            message = 'Redirecting output to stdout.'
        return [(None, None, None, message, True)]

    def show_help(self):
        headers = ['Command', 'Description']
        result = [
            ('\\q', 'Quit vcli')
        ]
        for _, value in self.commands.items():
            if not value.hidden:
                result.append((value.syntax, value.description))
        result = sorted(result)
        return [(None, result, headers, None, True)]

    def toggle_expanded_output(self):
        self.expanded_output = not self.expanded_output
        message = u"Expanded display is "
        message += u"on." if self.expanded_output else u"off."
        return [(None, None, None, message, True)]

    def toggle_timing(self):
        self.timing_enabled = not self.timing_enabled
        message = "Timing is "
        message += "on." if self.timing_enabled else "off."
        return [(None, None, None, message, True)]
vcli/config.py
def load_config(usr_cfg, def_cfg=None):
    cfg = ConfigObj()
    cfg.merge(ConfigObj(def_cfg, interpolation=False))
    cfg.merge(ConfigObj(expanduser(usr_cfg), interpolation=False))
    cfg.filename = expanduser(usr_cfg)

    return cfg
vcli/completion_refresher.py
class CompletionRefresher(object):

    refreshers = OrderedDict()

    def __init__(self):
        self._completer_thread = None
        self._restart_refresh = threading.Event()

    def refresh(self, executor, special, callbacks):
        """
        Creates a VCompleter object and populates it with the relevant
        completion suggestions in a background thread.

        executor - VExecute object, used to extract the credentials to connect
                   to the database.
        special - VSpecial object used for creating a new completion object.
        callbacks - A function or a list of functions to call after the thread
                    has completed the refresh. The newly created completion
                    object will be passed in as an argument to each callback.
        """
        if self.is_refreshing():
            self._restart_refresh.set()
            return [(None, None, None, 'Auto-completion refresh restarted.', True)]
        else:
            self._completer_thread = threading.Thread(target=self._bg_refresh,
                                                      args=(executor, special, callbacks),
                                                      name='completion_refresh')
            self._completer_thread.setDaemon(True)
            self._completer_thread.start()
            return [(None, None, None,
                     'Auto-completion refresh started in the background.', True)]

    def is_refreshing(self):
        return self._completer_thread and self._completer_thread.is_alive()

    def _bg_refresh(self, vexecute, special, callbacks):
        completer = VCompleter(smart_completion=True, vspecial=special)

        # Create a new vexecute method to popoulate the completions.
        e = vexecute
        executor = VExecute(e.dbname, e.user, e.password, e.host, e.port)

        # If callbacks is a single function then push it into a list.
        if callable(callbacks):
            callbacks = [callbacks]

        while 1:
            for refresher in self.refreshers.values():
                refresher(completer, executor)
                if self._restart_refresh.is_set():
                    self._restart_refresh.clear()
                    break
            else:
                # Break out of while loop if the for loop finishes natually
                # without hitting the break statement.
                break

            # Start over the refresh from the beginning if the for loop hit the
            # break statement.
            continue

        for callback in callbacks:
            callback(completer)
vcli/encodingutils.py
def utf8tounicode(arg):
    """
    Only in Python 2. Psycopg2 returns the error message as utf-8.
    In Python 3 the errors are returned as unicode.
    """

    if PY2 and isinstance(arg, str):
        return arg.decode('utf-8')
    return arg
vcli/config.py
def write_default_config(source, destination, overwrite=False):
    destination = expanduser(destination)
    if not overwrite and exists(destination):
        return

    shutil.copyfile(source, destination)
vcli/vstyle.py
def style_factory(name, cli_style):
    try:
        style = get_style_by_name(name)
    except ClassNotFound:
        style = get_style_by_name('native')

    class VStyle(Style):
        styles = {}

        styles.update(style.styles)
        styles.update(default_style_extensions)
        custom_styles = dict([(string_to_tokentype(x), y)
                                for x, y in cli_style.items()])
        styles.update(custom_styles)
    return PygmentsStyle(VStyle)
vcli/packages/vtablefmt.py

vcli/vexecute.py
class VExecute(object):

    # The boolean argument to the current_schemas function indicates whether
    # implicit schemas, e.g. pg_catalog
    search_path_query = '''
        SELECT current_schemas(true)'''

    schemata_query = '''
        SELECT  schema_name
        FROM    v_catalog.schemata
        ORDER BY 1'''

    tables_query = '''
        SELECT  table_schema, table_name
        FROM    v_catalog.tables
        ORDER BY 1, 2'''

    views_query = '''
        SELECT table_schema, table_name
        FROM v_catalog.views
        ORDER BY 1, 2'''

    table_columns_query = '''
        SELECT  table_schema, table_name, column_name
        FROM    v_catalog.columns
        ORDER BY 1, 2, 3'''

    view_columns_query = '''
        SELECT  table_schema, table_name, column_name
        FROM v_catalog.view_columns
        ORDER BY 1, 2, 3'''

    functions_query = '''
        SELECT schema_name, function_name
        FROM v_catalog.user_functions
        WHERE schema_name NOT IN ('v_catalog', 'v_monitor', 'v_internal')
        ORDER BY 1, 2'''

    databases_query = '''
        SELECT  database_name, owner_id, 'UTF8' AS encoding,
                'en_US.utf8' AS collate, 'en_US.utf8' AS ctype
        FROM    v_catalog.databases
        ORDER BY 1'''

    datatypes_query = '''
        SELECT schema_name, type_name
        FROM v_catalog.types, v_catalog.schemata
        WHERE schema_name NOT IN ('v_catalog', 'v_monitor', 'v_internal')
        ORDER BY 1, 2'''

    def __init__(self, database, user, password, host, port):
        self.dbname = database
        self.user = user
        self.password = password
        self.host = host
        self.port = port
        self.connect()

    def connect(self, database=None, user=None, password=None, host=None,
                port=None):

        db = (database or self.dbname)
        user = (user or self.user)
        password = (password or self.password)
        host = (host or self.host)
        port = (port or self.port)

        conn = vertica.connect(database=db, user=user, password=password,
                               host=host, port=int(port))

        # Print notice message for PROFILE (#42)
        def print_notice(message):
            print('%(Severity)s: %(Message)s' % message.values)
            hint = message.values.get('Hint')
            if hint:
                print('HINT: ' + hint)
        conn.notice_handler = print_notice

        # HACK: Modify vertica_python's connection socket to do keep alive
        # TODO: Keep alive for Windows and other platforms
        # http://stackoverflow.com/questions/12248132/how-to-change-tcp-keepalive-timer-using-python-script
        sock = conn._socket()
        if sys.platform == 'darwin':  # Mac OS X
            tcp_keepalive = 0x10
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            sock.setsockopt(socket.IPPROTO_TCP, tcp_keepalive, 60)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)
        elif sys.platform.startswith('linux'):
            sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 10)
            sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 5)

        if hasattr(self, 'conn'):
            self.conn.close()
        self.conn = conn
        # self.conn.autocommit = True
        self.dbname = db
        self.user = user
        self.password = password
        self.host = host
        self.port = port
        # register_json_typecasters(self.conn, self._json_typecaster)
        # register_hstore_typecaster(self.conn)

    def _json_typecaster(self, json_data):
        """Interpret incoming JSON data as a string.

        The raw data is decoded using the connection's encoding, which defaults
        to the database's encoding.

        See http://initd.org/psycopg/docs/connection.html#connection.encoding
        """

        if PY2:
            return json_data.decode(self.conn.encoding)
        else:
            return json_data

    def run(self, statement, vspecial=None):
        """Execute the sql in the database and return the results.

        :param statement: A string containing one or more sql statements
        :param vspecial: VSpecial object
        :return: List of tuples containing (title, rows, headers, status,
                                            force_stdout)
        """
        # Remove spaces and EOL
        statement = statement.strip()
        if not statement:  # Empty string
            yield (None, None, None, None, True)

        # Split the sql into separate queries and run each one.
        for sql in sqlparse.split(statement):
            # Remove spaces, eol and semi-colons.
            sql = sql.rstrip(';')

            if vspecial:
                # First try to run each query as special
                try:
                    _logger.debug('Trying a vspecial command. sql: %r', sql)
                    cur = self.conn.cursor()
                    for result in vspecial.execute(cur, sql):
                        yield result
                    return
                except special.CommandNotFound:
                    pass

            yield self.execute_normal_sql(sql)

    def execute_normal_sql(self, split_sql):
        _logger.debug('Regular sql statement. sql: %r', split_sql)
        cur = self.conn.cursor()

        try:
            tree = sqlparse.parse(split_sql)[0]
        except IndexError:
            return (None, None, None, None, True)

        if _is_copy_from_local(tree):
            _execute_copy_from_local_sql(tree, cur)
        else:
            cur.execute(split_sql)

        title = None
        statusmessage = None
        first_token = split_sql.split()[0].lower()
        if cur.description and first_token in ('select', 'update', 'delete', 'with',
                                               'insert', 'explain', 'profile'):
            headers = [x[0] for x in cur.description]
            return (title, cur, headers, statusmessage, False)
        else:
            _logger.debug('No rows in result.')
            return (title, None, None, statusmessage, True)

    def search_path(self):
        """Returns the current search path as a list of schema names"""
        with self.conn.cursor() as cur:
            _logger.debug('Search path query. sql: %r', self.search_path_query)
            cur.execute(self.search_path_query)
            names = cur.fetchone()[0]
            return names.split(b',')

    def schemata(self):
        """Returns a list of schema names in the database"""
        with self.conn.cursor() as cur:
            _logger.debug('Schemata Query. sql: %r', self.schemata_query)
            cur.execute(self.schemata_query)
            return (x[0] for x in cur.fetchall())

    def tables(self):
        """Yields (schema_name, table_name) tuples"""
        with self.conn.cursor() as cur:
            _logger.debug('Tables Query. sql: %r', self.tables_query)
            cur.execute(self.tables_query)
            for row in cur.iterate():
                yield tuple(row)

    def views(self):
        """Yields (schema_name, view_name) tuples.

            Includes both views and and materialized views
        """
        with self.conn.cursor() as cur:
            _logger.debug('Views Query. sql: %r', self.views_query)
            cur.execute(self.views_query)
            for row in cur.iterate():
                yield tuple(row)

    def table_columns(self):
        with self.conn.cursor() as cur:
            _logger.debug('Columns Query. sql: %r', self.table_columns_query)
            cur.execute(self.table_columns_query)
            for row in cur.iterate():
                yield tuple(row)

    def view_columns(self):
        with self.conn.cursor() as cur:
            _logger.debug('Columns Query. sql: %r', self.view_columns_query)
            cur.execute(self.view_columns_query)
            for row in cur.iterate():
                yield tuple(row)

    def databases(self):
        with self.conn.cursor() as cur:
            _logger.debug('Databases Query. sql: %r', self.databases_query)
            cur.execute(self.databases_query)
            return [x[0] for x in cur.fetchall()]

    def functions(self):
        """Yields tuples of (schema_name, function_name)"""
        with self.conn.cursor() as cur:
            _logger.debug('Functions Query. sql: %r', self.functions_query)
            cur.execute(self.functions_query)
            for row in cur.iterate():
                yield tuple(row)

    def datatypes(self):
        """Yields tuples of (schema_name, type_name)"""
        with self.conn.cursor() as cur:
            _logger.debug('Datatypes Query. sql: %r', self.datatypes_query)
            cur.execute(self.datatypes_query)
            for row in cur.iterate():
                yield tuple(row)
vcli/vbuffer.py
class VBuffer(Buffer):
    def __init__(self, always_multiline, *args, **kwargs):
        self.always_multiline = always_multiline

        @Condition
        def is_multiline():
            doc = self.document
            return self.always_multiline and not _multiline_exception(doc.text)

        super(self.__class__, self).__init__(*args, is_multiline=is_multiline,
                                             tempfile_suffix='.sql', **kwargs)
vcli/verror.py
def format_error(error):
    msg = str(error)
    if not hasattr(error, 'one_line_sql'):
        return msg

    result = ''

    match = RE_SQLSTATE.search(msg)
    if match:
        result += 'ERROR %s: ' % match.group(1)

    match = RE_MESSAGE.search(msg)
    if match:
        result += match.group(1)

    match = RE_POSITION.search(msg)
    if match:
        sql = error.one_line_sql()
        position = int(match.group(1))

        # Truncate the SQL query if its length > n (n must be odd)
        n = 75
        d = (n - 1) / 2
        length = len(sql)
        if length > n:
            left = position - d
            right = position + d
            position = d
            head = '...'
            tail = '...'

            if left < 0:
                right -= left
                position += left
                left = 0
                head = ''
            elif right >= length:
                offset = right - length + 1
                left -= offset
                position += offset
                right = length - 1
                tail = ''

            sql = head + sql[left:right + 1] + tail
            position += len(head)

        result += ('\n%s\n' % sql) + (' ' * (position - 1)) + '^'

    return result
vcli/vcompleter.py
class VCompleter(Completer):

    keywords = [
        'ACCESS', 'ADD', 'ALL', 'ALTER TABLE', 'AND', 'ANY', 'AS',
        'ASC', 'AUDIT', 'BETWEEN', 'BY', 'CASCADE', 'CASE', 'CHAR', 'CHECK',
        'CLUSTER', 'COLUMN', 'COMMENT', 'COMPRESS', 'CONNECT', 'COPY',
        'CREATE', 'CURRENT', 'DATABASE', 'DATE', 'DECIMAL', 'DEFAULT',
        'DELETE FROM', 'DELIMITER', 'DESC', 'DESCRIBE', 'DISTINCT', 'DROP',
        'ELSE', 'ENCODING', 'ESCAPE', 'EXCLUSIVE', 'EXISTS', 'EXTENSION',
        'FILE', 'FLOAT', 'FOR', 'FORMAT', 'FORCE_QUOTE', 'FORCE_NOT_NULL',
        'FREEZE', 'FROM', 'FULL', 'FUNCTION', 'GRANT', 'GROUP BY',
        'HAVING', 'HEADER', 'IDENTIFIED', 'ILIKE', 'IMMEDIATE', 'IN', 'INCREMENT',
        'INDEX', 'INITIAL', 'INSERT INTO', 'INTEGER', 'INTERSECT', 'INTO',
        'IS', 'JOIN', 'LEFT', 'LEVEL', 'LIKE', 'LIMIT', 'LOCK', 'LONG',
        'MAXEXTENTS', 'MINUS', 'MLSLABEL', 'MODE', 'MODIFY', 'NOAUDIT',
        'NOCOMPRESS', 'NOT', 'NOWAIT', 'NULL', 'NUMBER', 'OIDS', 'OF',
        'OFFLINE', 'ON', 'ONLINE', 'OPTION', 'OR', 'ORDER BY', 'OUTER',
        'OWNER', 'PCTFREE', 'PRIMARY', 'PRIOR', 'PRIVILEGES', 'QUOTE',
        'RAW', 'RENAME', 'RESOURCE', 'REVOKE', 'RIGHT', 'ROW', 'ROWID',
        'ROWNUM', 'ROWS', 'SCHEMA', 'SELECT', 'SESSION', 'SET', 'SHARE',
        'SIZE', 'SMALLINT', 'START', 'SUCCESSFUL', 'SYNONYM', 'SYSDATE',
        'TABLE', 'TEMPLATE', 'THEN', 'TO', 'TRIGGER', 'TRUNCATE', 'UID',
        'UNION', 'UNIQUE', 'UPDATE', 'USE', 'USER', 'USING', 'VALIDATE',
        'VALUES', 'VARCHAR', 'VARCHAR2', 'VIEW', 'WHEN', 'WHENEVER', 'WHERE',
        'WITH', 'EXPLAIN', 'PROFILE'
    ]

    functions = [
        'AVG', 'COUNT', 'DISTINCT', 'EXPORT_OBJECTS', 'FIRST', 'FORMAT',
        'LAST', 'LCASE', 'LEN', 'MAX', 'MIN', 'MID', 'NOW', 'ROUND', 'SUM',
        'TOP', 'UCASE'
    ]

    datatypes = [
        'BIGINT', 'BOOLEAN', 'CHAR', 'DATE', 'DOUBLE PRECISION', 'INT',
        'INTEGER', 'NUMERIC', 'REAL', 'TEXT', 'VARCHAR'
    ]

    def __init__(self, smart_completion=True, vspecial=None):
        super(VCompleter, self).__init__()
        self.smart_completion = smart_completion
        self.vspecial = vspecial

        self.reserved_words = set()
        for x in self.keywords:
            self.reserved_words.update(x.split())
        self.name_pattern = re.compile("^[_a-z][_a-z0-9\$]*$")

        self.databases = []
        self.dbmetadata = {'tables': {}, 'views': {}, 'functions': {},
                           'datatypes': {}}
        self.search_path = []

        self.all_completions = set(self.keywords + self.functions)

    def escape_name(self, name):
        name = name.decode('utf-8') if type(name) == bytes else name
        if name and ((not self.name_pattern.match(name))
                     or (name.upper() in self.reserved_words)
                     or (name.upper() in self.functions)):
            name = '"%s"' % name

        return name

    def unescape_name(self, name):
        """ Unquote a string."""
        if name and name[0] == '"' and name[-1] == '"':
            name = name[1:-1]

        return name

    def escaped_names(self, names):
        if names:
            return [self.escape_name(name) for name in names]
        return []

    def extend_database_names(self, databases):
        databases = self.escaped_names(databases)
        self.databases.extend(databases)

    def extend_keywords(self, additional_keywords):
        self.keywords.extend(additional_keywords)
        self.all_completions.update(additional_keywords)

    def extend_schemata(self, schemata):

        # schemata is a list of schema names
        schemata = self.escaped_names(schemata)
        metadata = self.dbmetadata['tables']
        for schema in schemata:
            metadata[schema] = {}

        # dbmetadata.values() are the 'tables' and 'functions' dicts
        for metadata in self.dbmetadata.values():
            for schema in schemata:
                metadata[schema] = {}

        self.all_completions.update(schemata)

    def extend_relations(self, data, kind):
        """ extend metadata for tables or views

        :param data: list of (schema_name, rel_name) tuples
        :param kind: either 'tables' or 'views'
        :return:
        """

        data = [self.escaped_names(d) for d in data]

        # dbmetadata['tables']['schema_name']['table_name'] should be a list of
        # column names. Default to an asterisk
        metadata = self.dbmetadata[kind]
        for schema, relname in data:
            try:
                metadata[schema][relname] = ['*']
            except KeyError:
                _logger.error('%r %r listed in unrecognized schema %r',
                              kind, relname, schema)
            self.all_completions.add(relname)

    def extend_columns(self, column_data, kind):
        """ extend column metadata

        :param column_data: list of (schema_name, rel_name, column_name) tuples
        :param kind: either 'tables' or 'views'
        :return:
        """

        column_data = [self.escaped_names(d) for d in column_data]
        metadata = self.dbmetadata[kind]
        for schema, relname, column in column_data:
            try:
                metadata[schema][relname].append(column)
            except KeyError:
                pass
            else:
                self.all_completions.add(column)

    def extend_functions(self, func_data):

        # func_data is an iterator of (schema_name, function_name)

        # dbmetadata['functions']['schema_name']['function_name'] should return
        # function metadata -- right now we're not storing any further metadata
        # so just default to None as a placeholder
        metadata = self.dbmetadata['functions']

        for f in func_data:
            schema, func = self.escaped_names(f)
            metadata[schema][func] = None
            self.all_completions.add(func)

    def extend_datatypes(self, type_data):

        # dbmetadata['datatypes'][schema_name][type_name] should store type
        # metadata, such as composite type field names. Currently, we're not
        # storing any metadata beyond typename, so just store None
        meta = self.dbmetadata['datatypes']

        if type_data:
            for t in type_data:
                schema, type_name = self.escaped_names(t)
                meta[schema][type_name] = None
                self.all_completions.add(type_name)

    def set_search_path(self, search_path):
        self.search_path = self.escaped_names(search_path)

    def reset_completions(self):
        self.databases = []
        self.special_commands = []
        self.search_path = []
        self.dbmetadata = {'tables': {}, 'views': {}, 'functions': {},
                           'datatypes': {}}
        self.all_completions = set(self.keywords + self.functions)

    def find_matches(self, text, collection, start_only=False, fuzzy=True,
                     meta=None, meta_collection=None):
        """Find completion matches for the given text.

        Given the user's input text and a collection of available
        completions, find completions matching the last word of the
        text.

        If `start_only` is True, the text will match an available
        completion only at the beginning. Otherwise, a completion is
        considered a match if the text appears anywhere within it.

        yields prompt_toolkit Completion instances for any matches found
        in the collection of available completions.

        """

        text = last_word(text, include='most_punctuations').lower()

        # Construct a `_match` function for either fuzzy or non-fuzzy matching
        # The match function returns a 2-tuple used for sorting the matches,
        # or None if the item doesn't match
        if fuzzy:
            regex = '.*?'.join(map(re.escape, text))
            pat = re.compile('(%s)' % regex)

            def _match(item):
                r = pat.search(self.unescape_name(item))
                if r:
                    return len(r.group()), r.start()
        else:
            match_end_limit = len(text) if start_only else None

            def _match(item):
                match_point = item.lower().find(text, 0, match_end_limit)
                if match_point >= 0:
                    return match_point, 0

        if meta_collection:
            # Each possible completion in the collection has a corresponding
            # meta-display string
            collection = zip(collection, meta_collection)
        else:
            # All completions have an identical meta
            collection = zip(collection, itertools.repeat(meta))

        completions = []
        for item, meta in collection:
            sort_key = _match(item)
            if sort_key:
                if meta and len(meta) > 50:
                    # Truncate meta-text to 50 characters, if necessary
                    meta = meta[:47] + u'...'

                completions.append((sort_key, item, meta))

        return [Completion(item, -len(text), display_meta=meta)
                for sort_key, item, meta in sorted(completions)]

    def get_completions(self, document, complete_event, smart_completion=None):
        word_before_cursor = document.get_word_before_cursor(WORD=True)
        if smart_completion is None:
            smart_completion = self.smart_completion

        # If smart_completion is off then match any word that starts with
        # 'word_before_cursor'.
        if not smart_completion:
            return self.find_matches(word_before_cursor, self.all_completions,
                                     start_only=True, fuzzy=False)

        completions = []
        suggestions = suggest_type(document.text, document.text_before_cursor)

        for suggestion in suggestions:

            _logger.debug('Suggestion type: %r', suggestion['type'])

            if suggestion['type'] == 'column':
                tables = suggestion['tables']
                _logger.debug("Completion column scope: %r", tables)
                scoped_cols = self.populate_scoped_cols(tables)

                if suggestion.get('drop_unique'):
                    # drop_unique is used for 'tb11 JOIN tbl2 USING (...' which
                    # should suggest only columns that appear in more than one
                    # table
                    scoped_cols = [col for (col, count)
                                   in Counter(scoped_cols).items()
                                   if count > 1 and col != '*']

                cols = self.find_matches(word_before_cursor, scoped_cols,
                                         meta='column')
                completions.extend(cols)

            elif suggestion['type'] == 'function':
                # suggest user-defined functions using substring matching
                funcs = self.populate_schema_objects(
                    suggestion['schema'], 'functions')
                user_funcs = self.find_matches(word_before_cursor, funcs,
                                               meta='function')
                completions.extend(user_funcs)

                if not suggestion['schema']:
                    # also suggest hardcoded functions using startswith
                    # matching
                    predefined_funcs = self.find_matches(word_before_cursor,
                                                         self.functions,
                                                         start_only=True,
                                                         fuzzy=False,
                                                         meta='function')
                    completions.extend(predefined_funcs)

            elif suggestion['type'] == 'schema':
                schema_names = self.dbmetadata['tables'].keys()

                # Unless we're sure the user really wants them, hide schema
                # names starting with pg_, which are mostly temporary schemas
                if not word_before_cursor.startswith('pg_'):
                    schema_names = [s for s in schema_names
                                    if not s.startswith('pg_')]

                schema_names = self.find_matches(word_before_cursor,
                                                 schema_names,
                                                 meta='schema')
                completions.extend(schema_names)

            elif suggestion['type'] == 'table':
                tables = self.populate_schema_objects(
                    suggestion['schema'], 'tables')

                # Unless we're sure the user really wants them, don't suggest
                # the pg_catalog tables that are implicitly on the search path
                if not suggestion['schema'] and (
                        not word_before_cursor.startswith('pg_')):
                    tables = [t for t in tables if not t.startswith('pg_')]

                tables = self.find_matches(word_before_cursor, tables,
                                           meta='table')
                completions.extend(tables)

            elif suggestion['type'] == 'view':
                views = self.populate_schema_objects(
                    suggestion['schema'], 'views')

                if not suggestion['schema'] and (
                        not word_before_cursor.startswith('pg_')):
                    views = [v for v in views if not v.startswith('pg_')]

                views = self.find_matches(word_before_cursor, views,
                                          meta='view')
                completions.extend(views)

            elif suggestion['type'] == 'alias':
                aliases = suggestion['aliases']
                aliases = self.find_matches(word_before_cursor, aliases,
                                            meta='table alias')
                completions.extend(aliases)

            elif suggestion['type'] == 'database':
                dbs = self.find_matches(word_before_cursor, self.databases,
                                        meta='database')
                completions.extend(dbs)

            elif suggestion['type'] == 'keyword':
                keywords = self.find_matches(word_before_cursor, self.keywords,
                                             start_only=True,
                                             fuzzy=False,
                                             meta='keyword')
                completions.extend(keywords)

            elif suggestion['type'] == 'special':
                if not self.vspecial:
                    continue

                commands = self.vspecial.commands
                cmd_names = commands.keys()
                desc = [commands[cmd].description for cmd in cmd_names]

                special = self.find_matches(word_before_cursor, cmd_names,
                                            start_only=True,
                                            fuzzy=False,
                                            meta_collection=desc)

                completions.extend(special)

            elif suggestion['type'] == 'datatype':
                # suggest custom datatypes
                types = self.populate_schema_objects(
                    suggestion['schema'], 'datatypes')
                types = self.find_matches(word_before_cursor, types,
                                          meta='datatype')
                completions.extend(types)

                if not suggestion['schema']:
                    # Also suggest hardcoded types
                    types = self.find_matches(word_before_cursor,
                                              self.datatypes, start_only=True,
                                              fuzzy=False, meta='datatype')
                    completions.extend(types)

            elif suggestion['type'] == 'namedquery':
                queries = self.find_matches(word_before_cursor, namedqueries.list(),
                                            start_only=False, fuzzy=True,
                                            meta='named query')
                completions.extend(queries)

        return completions

    def populate_scoped_cols(self, scoped_tbls):
        """ Find all columns in a set of scoped_tables
        :param scoped_tbls: list of (schema, table, alias) tuples
        :return: list of column names
        """

        columns = []
        meta = self.dbmetadata

        for tbl in scoped_tbls:
            if tbl[0]:
                # A fully qualified schema.relname reference
                schema = self.escape_name(tbl[0])
                relname = self.escape_name(tbl[1])

                # We don't know if schema.relname is a table or view. Since
                # tables and views cannot share the same name, we can check one
                # at a time
                try:
                    columns.extend(meta['tables'][schema][relname])

                    # Table exists, so don't bother checking for a view
                    continue
                except KeyError:
                    pass

                try:
                    columns.extend(meta['views'][schema][relname])
                except KeyError:
                    pass

            else:
                # Schema not specified, so traverse the search path looking for
                # a table or view that matches. Note that in order to get proper
                # shadowing behavior, we need to check both views and tables for
                # each schema before checking the next schema
                for schema in self.search_path:
                    relname = self.escape_name(tbl[1])

                    try:
                        columns.extend(meta['tables'][schema][relname])
                        break
                    except KeyError:
                        pass

                    try:
                        columns.extend(meta['views'][schema][relname])
                        break
                    except KeyError:
                        pass

        return columns

    def populate_schema_objects(self, schema, obj_type):
        """Returns list of tables or functions for a (optional) schema"""

        metadata = self.dbmetadata[obj_type]

        if schema:
            try:
                objects = metadata[schema].keys()
            except KeyError:
                # schema doesn't exist
                objects = []
        else:
            schemas = self.search_path
            objects = [obj for schema in schemas
                       for obj in metadata[schema].keys()]

        return objects
vcli/vtoolbar.py
def create_toolbar_tokens_func(get_vi_mode_enabled, get_is_refreshing):
    """
    Return a function that generates the toolbar tokens.
    """
    assert callable(get_vi_mode_enabled)

    token = Token.Toolbar

    def get_toolbar_tokens(cli):
        result = []
        result.append((token, ' '))

        if cli.buffers['DEFAULT_BUFFER'].completer.smart_completion:
            result.append((token.On, '[F2] Smart Completion: ON  '))
        else:
            result.append((token.Off, '[F2] Smart Completion: OFF  '))

        if cli.buffers['DEFAULT_BUFFER'].always_multiline:
            result.append((token.On, '[F3] Multiline: ON  '))
        else:
            result.append((token.Off, '[F3] Multiline: OFF  '))

        if cli.buffers['DEFAULT_BUFFER'].always_multiline:
            result.append((token,
                ' (Semi-colon [;] will end the line)'))

        if get_vi_mode_enabled():
            result.append((token.On, '[F4] Vi-mode'))
        else:
            result.append((token.On, '[F4] Emacs-mode'))

        if get_is_refreshing():
            result.append((token, '     Refreshing completions...'))

        return result
    return get_toolbar_tokens


Question: import getpass
import logging
import os
import re
import sys
import threading
import traceback
import click
    import setproctitle
import sqlparse
import vcli.packages.vspecial as special
from collections import namedtuple
from time import time
    from urlparse import urlparse
    from urllib.parse import urlparse
from prompt_toolkit import CommandLineInterface, Application, AbortAction
from prompt_toolkit.buffer import AcceptAction
from prompt_toolkit.document import Document
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.filters import Always, HasFocus, IsDone
from prompt_toolkit.history import FileHistory
from prompt_toolkit.layout.processors import (
    ConditionalProcessor, HighlightMatchingBracketProcessor)
from prompt_toolkit.shortcuts import create_prompt_layout, create_eventloop
from pygments.lexers.sql import PostgresLexer
from pygments.token import Token
from vertica_python import errors
from .__init__ import __version__
from .config import write_default_config, load_config
from .encodingutils import utf8tounicode
from .key_bindings import vcli_bindings
from .packages import vtablefmt
from .packages.expanded import expanded_table
from .packages.tabulate import tabulate
from .packages.vspecial.main import (VSpecial, NO_QUERY)
from .vbuffer import VBuffer
from .completion_refresher import CompletionRefresher
from .vcompleter import VCompleter
from .verror import format_error
from .vexecute import VExecute
from .vstyle import style_factory
from .vtoolbar import create_toolbar_tokens_func
        from vcli import __file__ as package_root
    def adjust_less_opts(self):
        less_opts = os.environ.get('LESS', '')
        self.logger.debug('Original value for LESS env var: %r', less_opts)
        os.environ['LESS'] = '-RXF'

        return less_opts

    def refresh_completions(self, reset=False):
        if reset:
            with self._completer_lock:
                self.completer.reset_completions()
        self.completion_refresher.refresh(self.vexecute, self.vspecial,
                                          self._on_completions_refreshed)
        return [(None, None, None,
                'Auto-completion refresh started in the background.', True)]

    def _on_completions_refreshed(self, new_completer):
        self._swap_completer_objects(new_completer)

        if self.cli:
            # After refreshing, redraw the CLI to clear the statusbar
            # "Refreshing completions..." indicator
            self.cli.request_redraw()

    def _swap_completer_objects(self, new_completer):
        """Swap the completer object in cli with the newly created completer.
        """
        with self._completer_lock:
            self.completer = new_completer
            # When pgcli is first launched we call refresh_completions before
            # instantiating the cli object. So it is necessary to check if cli
            # exists before trying the replace the completer object in cli.
            if self.cli:
                self.cli.current_buffer.completer = new_completer

    def get_completions(self, text, cursor_positition):
        with self._completer_lock:
            return self.completer.get_completions(
                Document(text=text, cursor_position=cursor_positition), None)


@click.command()
# Default host is '' so psycopg2 can default to either localhost or unix socket
@click.option('-h', '--host', default='localhost', show_default=True,
              help='Database server host address')
@click.option('-p', '--port', default=5433, show_default=True, type=int,
              help='Database server port')
@click.option('-U', '--user', default=getpass.getuser(), show_default=True,
              help='Database username')
@click.option('-W', '--prompt-password', 'prompt_passwd', is_flag=True,
              default=False, show_default=True, help='Prompt for password')
@click.option('-w', '--password', default='', show_default=True,
              help='Database password')
@click.option('-v', '--version', is_flag=True, help='Print version and exit')
@click.option('--vclirc', default='~/.vclirc', show_default=True,
              help='Location of .vclirc file')
@click.argument('database', nargs=1, default='')
def cli(database, host, port, user, prompt_passwd, password, version, vclirc):
    if version:
        click.echo('Version: %s' % __version__)
        sys.exit(0)

    if prompt_passwd and not password:
        password = click.prompt('Password', hide_input=True,
                                show_default=False, type=str)

    vcli = VCli(vclirc_file=vclirc)

    # Choose which ever one has a valid value
    database = database or os.getenv('VERTICA_URL', '')

    if '://' in database:
        vcli.connect_uri(database)
    else:
        vcli.connect(database, host, user, port, password)

    vcli.logger.debug('Launch Params: \n'
                      '\tdatabase: %r'
                      '\tuser: %r'
                      '\thost: %r'
                      '\tport: %r', database, user, host, port)
    if setproctitle:
        obfuscate_process_password()

    vcli.run_cli()


def obfuscate_process_password():
    process_title = setproctitle.getproctitle()
    if '://' in process_title:
        process_title = re.sub(r":(.*):(.*)@", r":\1:xxxx@", process_title)
    elif "=" in process_title:
        process_title = re.sub(r"password=(.+?)(\s|$)", r"password=xxxx\2", process_title)
    elif "-w" in process_title:
        process_title = re.sub(r"\-w\s+([^\s]+)(\s|$)", r"-w xxxx\2", process_title)

    setproctitle.setproctitle(process_title)


def format_output(title, cur, headers, status, table_format, expanded=False,
                  aligned=True, show_header=True):
    output = []
    if title:  # Only print the title if it's not None.
        output.append(title)
    if cur and headers:
        headers = [utf8tounicode(x) for x in headers]

        if hasattr(cur, 'iterate'):
            rows = cur.iterate()
        else:
            rows = cur

        if expanded:
            output.append(expanded_table(rows, headers))
        else:
            if aligned:
                numalign, stralign = 'decimal', 'left'
                tablefmt = table_format
            else:
                numalign, stralign = None, None

Answer:                 tablefmt = vtablefmt.vsv_unaligned