1
0
Fork 0
pgcli/pgcli/main.py

117 lines
4.7 KiB
Python
Raw Normal View History

2014-10-12 17:31:54 +00:00
#!/usr/bin/env python
from __future__ import unicode_literals
from __future__ import print_function
2014-10-12 22:07:34 +00:00
2014-11-27 23:02:54 +00:00
import os.path
2014-11-23 23:31:34 +00:00
2014-10-12 22:07:34 +00:00
import click
2014-10-12 17:31:54 +00:00
2014-10-12 17:45:35 +00:00
from prompt_toolkit import CommandLineInterface, AbortAction, Exit
2014-10-12 17:31:54 +00:00
from prompt_toolkit.layout import Layout
from prompt_toolkit.layout.prompt import DefaultPrompt
from prompt_toolkit.layout.menus import CompletionsMenu
2014-11-23 23:31:34 +00:00
from prompt_toolkit.history import FileHistory
from prompt_toolkit.key_bindings.emacs import emacs_bindings
2014-11-24 07:30:17 +00:00
from pygments.lexers.sql import SqlLexer
from .packages.tabulate import tabulate
from .packages.pgspecial import (CASE_SENSITIVE_COMMANDS,
NON_CASE_SENSITIVE_COMMANDS)
from .pgcompleter import PGCompleter
from .pgtoolbar import PGToolbar
from .pgstyle import PGStyle
from .pgexecute import PGExecute
from .pgline import PGLine
from .config import write_default_config, load_config
from .key_bindings import pgcli_bindings
2014-10-12 17:31:54 +00:00
2014-10-12 22:07:34 +00:00
@click.command()
2014-12-11 18:10:26 +00:00
@click.option('-h', '--host', default='localhost', help='Host address of the '
'postgres database.')
@click.option('-p', '--port', default=5432, help='Port number at which the '
'postgres instance is listening.')
@click.option('-U', '--user', prompt=True, envvar='USER', help='User name to '
'connect to the postgres database.')
2014-12-11 21:59:21 +00:00
@click.password_option('-W', '--password', default='',
confirmation_prompt=False)
@click.argument('database', envvar='USER')
def cli(database, user, password, host, port):
2014-11-27 23:02:54 +00:00
from pgcli import __file__ as package_root
package_root = os.path.dirname(package_root)
default_config = os.path.join(package_root, 'pgclirc')
# Write default config.
write_default_config(default_config, '~/.pgclirc')
# Load config.
config = load_config('~/.pgclirc')
smart_completion = config.getboolean('main', 'smart_completion')
2014-11-27 23:02:54 +00:00
# Connect to the database.
2014-11-23 08:09:00 +00:00
try:
pgexecute = PGExecute(database, user, password, host, port)
except Exception as e: # Connecting to a database could fail.
2014-11-23 08:09:00 +00:00
click.secho(e.message, err=True, fg='red')
exit(1)
layout = Layout(before_input=DefaultPrompt('%s> ' % pgexecute.dbname),
menus=[CompletionsMenu(max_height=10)],
lexer=SqlLexer,
bottom_toolbars=[
PGToolbar()])
completer = PGCompleter(smart_completion)
completer.extend_special_commands(CASE_SENSITIVE_COMMANDS.keys())
completer.extend_special_commands(NON_CASE_SENSITIVE_COMMANDS.keys())
tables = pgexecute.tables()
completer.extend_table_names(tables)
for table in tables:
completer.extend_column_names(table, pgexecute.columns(table))
completer.extend_database_names(pgexecute.databases())
2014-12-16 06:04:03 +00:00
line = PGLine(always_multiline=False, completer=completer,
2014-11-27 23:02:54 +00:00
history=FileHistory(os.path.expanduser('~/.pgcli-history')))
cli = CommandLineInterface(style=PGStyle, layout=layout, line=line,
key_binding_factories=[emacs_bindings, pgcli_bindings])
2014-10-12 17:31:54 +00:00
2014-10-12 17:45:35 +00:00
try:
while True:
cli.layout.before_input = DefaultPrompt('%s> ' % pgexecute.dbname)
2014-10-12 17:45:35 +00:00
document = cli.read_input(on_exit=AbortAction.RAISE_EXCEPTION)
2014-12-06 06:04:39 +00:00
# The reason we check here instead of inside the pgexecute is
# because we want to raise the Exit exception which will be caught
# by the try/except block that wraps the pgexecute.run() statement.
if (document.text.strip().lower() == 'exit'
or document.text.strip().lower() == 'quit'
2014-12-13 04:29:24 +00:00
or document.text.strip() == '\q'
or document.text.strip() == ':q'):
2014-12-06 06:04:39 +00:00
raise Exit
2014-11-23 08:09:00 +00:00
try:
res = pgexecute.run(document.text)
2014-12-20 04:57:36 +00:00
output = []
for rows, headers, status in res:
if rows:
2014-12-20 04:57:36 +00:00
output.append(tabulate(rows, headers, tablefmt='psql'))
if status: # Only print the status if it's not None.
2014-12-20 04:57:36 +00:00
output.append(status)
click.echo_via_pager('\n'.join(output))
2014-11-23 08:09:00 +00:00
except Exception as e:
click.secho(e.message, err=True, fg='red')
# Refresh the table names and column names if necessary.
if document.text and need_completion_refresh(document.text):
completer.reset_completions()
tables = pgexecute.tables()
completer.extend_table_names(tables)
for table in tables:
completer.extend_column_names(table,
pgexecute.columns(table))
2014-10-12 17:45:35 +00:00
except Exit:
print ('GoodBye!')
def need_completion_refresh(sql):
try:
first_token = sql.split()[0]
return first_token in ('alter', 'create', 'use', '\c', 'drop')
except Exception:
return False