diff options
author | Dick Marinus <dick@mrns.nl> | 2017-05-22 20:45:55 +0200 |
---|---|---|
committer | Dick Marinus <dick@mrns.nl> | 2017-05-22 20:45:55 +0200 |
commit | c6ae43a39825f7f3fb96677bf44d9feed5358d8f (patch) | |
tree | a6fa9689029ff516242f699143081d58613fa725 | |
parent | bbb0866806917dd5a162587d1b95ed00c6fbceec (diff) | |
parent | bc6883a308055bd76f6ec82d5d2afdd3d911d528 (diff) |
Merge remote-tracking branch 'upstream/master' into feature/tox_behave
46 files changed, 2268 insertions, 1748 deletions
diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..b2713c79 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,3 @@ +[run] +parallel=True +source=pgcli diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..b5cdbece --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,9 @@ +## Description +<!--- Describe your problem as fully as you can. --> + +## Your environment +<!-- This gives us some more context to work with. --> + +- [ ] Please provide your OS and version information. +- [ ] Please provide your CLI version. +- [ ] What is the output of ``pip freeze`` command. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..8d498abc --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +## Description +<!--- Describe your changes in detail. --> + + + +## Checklist +<!--- We appreciate your help and want to give you credit. Please take a moment to put an `x` in the boxes below as you complete them. --> +- [ ] I've added this contribution to the `changelog.md`. +- [ ] I've added my name to the `AUTHORS` file (or it's already there). diff --git a/.travis.yml b/.travis.yml index 92e155a8..d4528e8b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,14 +7,23 @@ python: - "3.6" install: - - pip install . pytest mock codecov==1.5.1 behave pexpect==3.3 + - pip install . docutils pytest mock codecov==1.5.1 behave pexpect==3.3 + - pip install git+https://github.com/hayd/pep8radius.git script: + - set -e - coverage run --source pgcli -m py.test - cd tests - behave + - cd .. + # check for changelog ReST compliance + - rst2html.py --halt=warning changelog.rst >/dev/null + # check for pep8 errors, only looking at branch vs master. If there are errors, show diff and return an error code. + - pep8radius master --docformatter --error-status || ( pep8radius master --docformatter --diff; false ) + - set +e after_success: + - coverage combine - codecov notifications: @@ -12,10 +12,12 @@ Core Devs: * Joakim Koljonen * Daniel Rocco * Karl-Aksel Puulmann + * Dick Marinus Contributors: ------------- * Brett + * Étienne BERSAC (bersace) * Daniel Schwarz * inkn * Jonathan Slenders @@ -56,6 +58,12 @@ Contributors: * Manuel Barkhau * Sergii V * Emanuele Gaifas + * Owen Stephens + * Russell Davies + * AlexTes + * Hraban Luyat + * Jackson Popkin + * Gustavo Castro Creator: -------- diff --git a/DEVELOP.rst b/DEVELOP.rst index 0c4dedf3..0af5143f 100644 --- a/DEVELOP.rst +++ b/DEVELOP.rst @@ -66,24 +66,8 @@ Adding PostgreSQL Special (Meta) Commands ----------------------------------------- If you want to work on adding new meta-commands (such as `\dp`, `\ds`, `dy`), -you'll be changing the code of `packages/pgspecial.py`. Search for the -dictionary called `CASE_SENSITIVE_COMMANDS`. The special command us used as -the dictionary key, and the value is a tuple. - -The first item in the tuple is either a string (sql statement) or a function. -The second item in the tuple is a list of strings which is the documentation -for that special command. The list will have two items, the first item is the -command itself with possible options and the second item is the plain english -description of that command. - -For example, `\l` is a meta-command that lists all the databases. The way you -can see the SQL statement issued by PostgreSQL when this command is executed -is to launch `psql -E` and entering `\l`. - -That will print the results and also print the sql statement that was executed -to produce that result. In most cases it's a single sql statement, but sometimes -it's a series of sql statements that feed the results to each other to get to -the final result. +you need to contribute to `pgspecial <https://github.com/pgcli/pgspecial/>`_ +project. Building RPM and DEB packages ----------------------------- @@ -155,3 +139,18 @@ To see stdout/stderr, use the following command: $ behave --no-capture + +PEP8 checks +----------- + +When you submit a PR, the changeset is checked for pep8 compliance using +`pep8radius <https://github.com/hayd/pep8radius>`_. If you see a build failing because +of these checks, install pep8radius and apply style fixes: + +:: + + $ pip install pep8radius + $ pep8radius --docformatter --diff # view a diff of proposed fixes + $ pep8radius --docformatter --in-place # apply the fixes + +Then commit and push the fixes. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..8d48e7de --- /dev/null +++ b/Dockerfile @@ -0,0 +1,6 @@ +FROM python:2.7 + +COPY . /app +RUN cd /app && pip install -e . + +CMD pgcli @@ -63,7 +63,6 @@ The `pgcli` is written using prompt_toolkit_. - ``SELECT * FROM <tab>`` will only show table names. - ``SELECT * FROM users WHERE <tab>`` will only show column names. -* Config file is automatically created at ``~/.config/pgcli/config`` at first launch. * Primitive support for ``psql`` back-slash commands. * Pretty prints tabular data. Note: `pgcli` uses [tabulate](https://github.com/dbcli/pgcli/blob/master/pgcli/packages/tabulate.py) @@ -73,6 +72,11 @@ The `pgcli` is written using prompt_toolkit_. .. _prompt_toolkit: https://github.com/jonathanslenders/python-prompt-toolkit +Config +------ +A config file is automatically created at ``~/.config/pgcli/config`` at first launch. +See the file itself for a description of all available options. + Contributions: -------------- @@ -176,6 +180,39 @@ Then you can install pgcli: $ sudo pip install pgcli +Docker +====== + +Pgcli can be run from within Docker. This can be useful to try pgcli without +installing it, or any dependencies, system-wide. + +To build the image: + +:: + + $ docker build -t pgcli . + +To create a container from the image: + +:: + + $ docker run --rm -ti pgcli pgcli <ARGS> + +To access postgresql databases listening on localhost, make sure to run the +docker in "host net mode". E.g. to access a database called "foo" on the +postgresql server running on localhost:5432 (the standard port): + +:: + + $ docker run --rm -ti --net host pgcli pgcli -h localhost foo + +To connect to a locally running instance over a unix socket, bind the socket to +the docker container: + +:: + + $ docker run --rm -ti -v /var/run/postgres:/var/run/postgres pgcli pgcli foo + Thanks: ------- diff --git a/changelog.rst b/changelog.rst index 0d65d95f..49db98a4 100644 --- a/changelog.rst +++ b/changelog.rst @@ -1,8 +1,33 @@ Upcoming ======== +Features: +--------- +* Add time option for prompt (Thanks: `Gustavo Castro`_) +* Suggest objects from all schemas (not just those in search_path) (Thanks: `Joakim Koljonen`_) +* Casing for column headers (Thanks: `Joakim Koljonen`_) +* Allow configurable character to be used for multi-line query continuations. (Thanks: `Owen Stephens`_) +* Completions after ORDER BY and DISTINCT now take account of table aliases. (Thanks: `Owen Stephens`_) +* Narrow keyword candidates based on previous keyword. (Thanks: `Étienne Bersac`_) +* Opening an external editor will edit the last-run query. (Thanks: `Thomas Roten`_) + +Bug fixes: +---------- +* Fixed external editor bug (issue #668). (Thanks: `Irina Truong`_). +* Standardize command line option names. (Thanks: `Russell Davies`_) +* Improve handling of ``lock_not_available`` error (issue #700). (Thanks: `Jackson Popkin <https://github.com/jdpopkin>`_) +* Fixed user option precedence (issue #697). (Thanks: `Irina Truong`_). + Internal changes: ----------------- +* Run pep8 checks in travis (Thanks: `Irina Truong`_). +* Add pager wrapper for behave tests (Thanks: `Dick Marinus`_). +* Behave quit pgcli nicely (Thanks: `Dick Marinus`_). +* Behave test source command (Thanks: `Dick Marinus`_). +* Behave fix clean up. (Thanks: `Dick Marinus`_). +* Test using behave the tee command (Thanks: `Dick Marinus`_). +* Behave remove boiler plate code (Thanks: `Dick Marinus`_). +* Behave fix pgspecial update (Thanks: `Dick Marinus`_). * Add behave to tox (Thanks: `Dick Marinus`_). 1.5.1 @@ -236,12 +261,12 @@ Features: than the display window. * Don't hide functions from pg_catalog. (Thanks: `Darik Gamble`_). * Suggest set-returning functions as tables. (Thanks: `Darik Gamble`_). - Functions that return table like results will now be suggested in places of tables. + Functions that return table like results will now be suggested in places of tables. * Suggest fields from functions used as tables. (Thanks: `Darik Gamble`_). * Using ``pgspecial`` as a separate module. (Thanks: `Iryna Cherniavska`_). * Make "enter" key behave as "tab" key when the completion menu is displayed. (Thanks: `Matheus Rosa`_). * Support different error-handling options when running multiple queries. (Thanks: `Darik Gamble`_). - When ``on_error = STOP`` in the config file, pgcli will abort execution if one of the queries results in an error. + When ``on_error = STOP`` in the config file, pgcli will abort execution if one of the queries results in an error. * Hide the password displayed in the process name in ``ps``. (Thanks: `Stuart Quin`_) Bug Fixes: @@ -314,7 +339,7 @@ Features: * Completion menu now has metadata information such as schema, table, column, view, etc., next to the suggestions. (Thanks: `Darik Gamble`_) * Customizable history file location via config file. (Thanks: `Çağatay Yüksel`_) - Add this line to your config file (~/.pgclirc) to customize where to store the history file. + Add this line to your config file (~/.pgclirc) to customize where to store the history file. :: @@ -345,16 +370,16 @@ Internal Changes: Features: --------- -* Add fuzzy matching for the table names and column names. +* Add fuzzy matching for the table names and column names. Matching very long table/column names are now easier with fuzzy matching. The - fuzzy match works like the fuzzy open in SublimeText or Vim's Ctrl-P plugin. + fuzzy match works like the fuzzy open in SublimeText or Vim's Ctrl-P plugin. eg: Typing ``djmv`` will match `django_migration_views` since it is able to match parts of the input to the full table name. -* Change the timing information to seconds. - +* Change the timing information to seconds. + The ``Command Time`` and ``Format Time`` are now displayed in seconds instead of a unitless number displayed in scientific notation. @@ -363,7 +388,7 @@ Features: Frequently typed queries can now be saved and recalled using a name using newly added special commands (``\n[+]``, ``\ns``, ``\nd``). - eg: + eg: :: @@ -394,17 +419,17 @@ Bug Fixes: * Fix an error when running ``\d table_name`` when running on a table with rules. (Thanks: `Ali Kargın`_) * Fix a pgcli crash when entering non-ascii characters in Windows. (Thanks: `Darik Gamble`_, `Jonathan Slenders`_) -* Faster rendering of expanded mode output by making the horizontal separator a fixed length string. -* Completion suggestions for the ``\c`` command are not auto-escaped by default. +* Faster rendering of expanded mode output by making the horizontal separator a fixed length string. +* Completion suggestions for the ``\c`` command are not auto-escaped by default. Internal Changes: ----------------- -* Complete refactor of handling the back-slash commands. +* Complete refactor of handling the back-slash commands. * Upgrade prompt_toolkit to 0.42. (Thanks: `Jonathan Slenders`_) * Change the config file management to use ConfigObj.(Thanks: `Brett Atoms`_) * Add integration tests using ``behave``. (Thanks: `Iryna Cherniavska`_) - + 0.17.0 ====== @@ -417,16 +442,16 @@ Features: Previously completions only matched a table name if it started with the partially typed word. Now completions will match even if the partially typed word is in the middle of a suggestion. - eg: When you type 'mig', 'django_migrations' will be suggested. + eg: When you type 'mig', 'django_migrations' will be suggested. * Completion for built-in tables and temporary tables are suggested after entering a prefix of ``pg_``. (Thanks: `Darik Gamble`_) * Add place holder doc strings for special commands that are planned for implementation. (Thanks: `Iryna Cherniavska`_) * Updated version of prompt_toolkit, now matching braces are highlighted. (Thanks: `Jonathan Slenders`_) * Added support of ``\\e`` command. Queries can be edited in an external editor. (Thanks: `Iryna Cherniavska`_) eg: When you type ``SELECT * FROM \e`` it will be opened in an external editor. * Add special command ``\dT`` to show datatypes. (Thanks: `Darik Gamble`_) -* Add auto-completion support for datatypes in CREATE, SELECT etc. (Thanks: `Darik Gamble`_) +* Add auto-completion support for datatypes in CREATE, SELECT etc. (Thanks: `Darik Gamble`_) * Improve the auto-completion in WHERE clause with logical operators. (Thanks: `Darik Gamble`_) -* +* Bug Fixes: ---------- @@ -458,7 +483,7 @@ Bug Fixes: As a result the suggestions for tables vs functions are cleaner. (Thanks: `Darik Gamble`_) * Remove scientific notation when formatting large numbers. (Thanks: `Daniel Rocco`_) * Add the FUNCTION keyword to auto-completion. -* Display NULL values as <null> instead of empty strings. +* Display NULL values as <null> instead of empty strings. * Fix the completion refresh when ``\connect`` is executed. 0.16.1 @@ -474,10 +499,10 @@ Bug Fixes: Features: --------- -* Add \ds special command to show sequences. +* Add \ds special command to show sequences. * Add Vi mode for keybindings. This can be enabled by adding 'vi = True' in ~/.pgclirc. (Thanks: `Jay Zeng`_) * Add a -v/--version flag to pgcli. -* Add completion for TEMPLATE keyword and smart-completion for +* Add completion for TEMPLATE keyword and smart-completion for 'CREATE DATABASE blah WITH TEMPLATE <tab>'. (Thanks: `Daniel Rocco`_) * Add custom decoders to json/jsonb to emulate the behavior of psql. This removes the unicode prefix (eg: u'Éowyn') in the output. (Thanks: `Daniel Rocco`_) @@ -492,7 +517,7 @@ Bug Fixes: * Print BIGSERIAL type as Integer instead of Float. * Show completions for special commands at the beginning of a statement. (Thanks: `Daniel Rocco`_) * Allow special commands to work in a multi-statement case where multiple sql - statements are separated by semi-colon in the same line. + statements are separated by semi-colon in the same line. 0.15.4 ====== @@ -500,11 +525,11 @@ Bug Fixes: 0.15.3 ====== -* Override the LESS options completely instead of appending to it. +* Override the LESS options completely instead of appending to it. 0.15.2 ====== -* Revert back to using psycopg2 as the postgres adapter. psycopg2cffi fails for some tests in Python 3. +* Revert back to using psycopg2 as the postgres adapter. psycopg2cffi fails for some tests in Python 3. 0.15.0 ====== @@ -513,14 +538,14 @@ Features: --------- * Add syntax color styles to config. * Add auto-completion for COPY statements. -* Change Postgres adapter to psycopg2cffi, to make it PyPy compatible. +* Change Postgres adapter to psycopg2cffi, to make it PyPy compatible. Now pgcli can be run by PyPy. Bug Fixes: ---------- * Treat boolean values as strings instead of ints. * Make \di, \dv and \dt to be schema aware. (Thanks: `Darik Gamble`_) -* Make column name display unicode compatible. +* Make column name display unicode compatible. 0.14.0 ====== @@ -528,14 +553,14 @@ Bug Fixes: Features: --------- * Add alias completion support to ON keyword. (Thanks: `Iryna Cherniavska`_) -* Add LIMIT keyword to completion. +* Add LIMIT keyword to completion. * Auto-completion for Postgres schemas. (Thanks: `Darik Gamble`_) -* Better unicode handling for datatypes, dbname and roles. -* Add \timing command to time the sql commands. +* Better unicode handling for datatypes, dbname and roles. +* Add \timing command to time the sql commands. This can be set via config file (~/.pgclirc) using `timing = True`. -* Add different table styles for displaying output. +* Add different table styles for displaying output. This can be changed via config file (~/.pgclirc) using `table_format = fancy_grid`. -* Add confirmation before printing results that have more than 1000 rows. +* Add confirmation before printing results that have more than 1000 rows. Bug Fixes: ---------- @@ -552,7 +577,7 @@ Bug Fixes: Features: --------- -* Add -d/--dbname option to the commandline. +* Add -d/--dbname option to the commandline. eg: pgcli -d database * Add the username as an argument after the database. eg: pgcli dbname user @@ -569,12 +594,12 @@ Bug Fixes: Features: --------- -* Upgrade to prompt_toolkit version 0.26 (Thanks: https://github.com/macobo) +* Upgrade to prompt_toolkit version 0.26 (Thanks: https://github.com/macobo) * Adds Ctrl-left/right to move the cursor one word left/right respectively. * Internal API changes. * IPython integration through `ipython-sql`_ (Thanks: `Darik Gamble`_) - * Add an ipython magic extension to embed pgcli inside ipython. - * Results from a pgcli query are sent back to ipython. + * Add an ipython magic extension to embed pgcli inside ipython. + * Results from a pgcli query are sent back to ipython. * Multiple sql statments in the same line separated by semi-colon. (Thanks: https://github.com/macobo) .. _`ipython-sql`: https://github.com/catherinedevlin/ipython-sql @@ -613,15 +638,15 @@ Improvements: .. _`Amjith Ramanujam`: https://github.com/amjith .. _`Darik Gamble`: https://github.com/darikg .. _`Iryna Cherniavska`: https://github.com/j-bennet -.. _`Daniel Rocco`: https://github.com/drocco007 -.. _`Jay Zeng`: https://github.com/jayzeng +.. _`Daniel Rocco`: https://github.com/drocco007 +.. _`Jay Zeng`: https://github.com/jayzeng .. _`蔡佳男`: https://github.com/xalley .. _dp: https://github.com/ceocoder .. _`Jonathan Slenders`: https://github.com/jonathanslenders .. _`Dimitar Roustchev`: https://github.com/droustchev .. _`François Pietka`: https://github.com/fpietka .. _`Ali Kargın`: https://github.com/sancopanco -.. _`Brett Atoms`: https://github.com/brettatoms +.. _`Brett Atoms`: https://github.com/brettatoms .. _`Nathan Jhaveri`: https://github.com/nathanjhaveri .. _`Çağatay Yüksel`: https://github.com/cagatay .. _`Michael Kaminsky`: https://github.com/mikekaminsky @@ -656,6 +681,12 @@ Improvements: .. _`Janus Troelsen`: https://github.com/ysangkok .. _`Fabien Meghazi`: https://github.com/amigrave .. _`Manuel Barkhau`: https://github.com/mbarkhau -.. _`Sergii`: https://github.com/foxyterkel +.. _`Sergii`: https://github.com/foxyterkel .. _`Emanuele Gaifas`: https://github.com/lelit .. _`tk`: https://github.com/kanet77 +.. _`Owen Stephens`: https://github.com/owst +.. _`Russell Davies`: https://github.com/russelldavies +.. _`Dick Marinus`: https://github.com/meeuw +.. _`Étienne Bersac`: https://github.com/bersace +.. _`Thomas Roten`: https://github.com/tsroten +.. _`Gustavo Castro`: https://github.com/gustavo-castro diff --git a/pgcli/main.py b/pgcli/main.py index 1e533cc8..9f57aa52 100755 --- a/pgcli/main.py +++ b/pgcli/main.py @@ -11,6 +11,7 @@ import threading import shutil import functools import humanize +import datetime as dt from time import time, sleep from codecs import open @@ -75,6 +76,13 @@ MetaQuery = namedtuple( ]) MetaQuery.__new__.__defaults__ = ('', False, 0, False, False, False, False) +OutputSettings = namedtuple( + 'OutputSettings', + 'table_format dcmlfmt floatfmt missingval expanded max_width case_function' +) +OutputSettings.__new__.__defaults__ = ( + None, None, None, '<null>', False, None, lambda x: x +) # no-op logging handler class NullHandler(logging.Handler): @@ -133,6 +141,7 @@ class PGCli(object): self.row_limit = c['main'].as_int('row_limit') self.min_num_menu_lines = c['main'].as_int('min_num_menu_lines') + self.multiline_continuation_char = c['main']['multiline_continuation_char'] self.table_format = c['main']['table_format'] self.syntax_style = c['main']['syntax_style'] self.cli_style = c['colors'] @@ -144,6 +153,8 @@ class PGCli(object): self.decimal_format = c['data_formats']['decimal'] self.float_format = c['data_formats']['float'] + self.now = dt.datetime.today() + self.completion_refresher = CompletionRefresher() self.query_history = [] @@ -157,6 +168,8 @@ class PGCli(object): 'generate_aliases': c['main'].as_bool('generate_aliases'), 'asterisk_column_order': c['main']['asterisk_column_order'], 'qualify_columns': c['main']['qualify_columns'], + 'case_column_headers': c['main'].as_bool('case_column_headers'), + 'search_path_filter': c['main'].as_bool('search_path_filter'), 'single_connection': single_connection, 'less_chatty': less_chatty, 'keyword_casing': keyword_casing, @@ -350,16 +363,23 @@ class PGCli(object): :param document: Document :return: Document """ + # FIXME: using application.pre_run_callables like this here is not the best solution. + # It's internal api of prompt_toolkit that may change. This was added to fix #668. + # We may find a better way to do it in the future. + saved_callables = cli.application.pre_run_callables while special.editor_command(document.text): filename = special.get_filename(document.text) - sql, message = special.open_external_editor(filename, - sql=document.text) + query = (special.get_editor_query(document.text) or + self.get_last_query()) + sql, message = special.open_external_editor(filename, sql=query) if message: # Something went wrong. Raise an exception and bail. raise RuntimeError(message) cli.current_buffer.document = Document(sql, cursor_position=len(sql)) - document = cli.run(False) + cli.application.pre_run_callables = [] + document = cli.run() continue + cli.application.pre_run_callables = saved_callables return document def execute_command(self, text, query): @@ -442,7 +462,7 @@ class PGCli(object): try: while True: - document = self.cli.run(True) + document = self.cli.run() # The reason we check here instead of inside the pgexecute is # because we want to raise the Exit exception which will be @@ -474,6 +494,8 @@ class PGCli(object): else: query = self.execute_command(document.text, query) + self.now = dt.datetime.today() + # Allow PGCompleter to learn user's preferred keywords, etc. with self._completer_lock: self.completer.extend_query_history(document.text) @@ -501,7 +523,8 @@ class PGCli(object): return [(Token.Prompt, prompt)] def get_continuation_tokens(cli, width): - return [(Token.Continuation, '.' * (width - 1) + ' ')] + continuation=self.multiline_continuation_char * (width - 1) + ' ' + return [(Token.Continuation, continuation)] get_toolbar_tokens = create_toolbar_tokens_func( lambda: self.vi_mode, self.completion_refresher.is_refreshing, @@ -596,9 +619,19 @@ class PGCli(object): max_width = None expanded = self.pgspecial.expanded_output or self.expanded_output - formatted = format_output( - title, cur, headers, status, self.table_format, self.decimal_format, - self.float_format, self.null_string, expanded, max_width) + settings = OutputSettings( + table_format=self.table_format, + dcmlfmt=self.decimal_format, + floatfmt=self.float_format, + missingval=self.null_string, + expanded=expanded, + max_width=max_width, + case_function=( + self.completer.case if self.settings['case_column_headers'] + else lambda x: x + ) + ) + formatted = format_output(title, cur, headers, status, settings) output.extend(formatted) total = time() - start @@ -696,6 +729,7 @@ |