mycli 2.2.0__tar.gz → 2.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mycli-2.2.0 → mycli-2.4.0}/AGENTS.md +4 -2
- {mycli-2.2.0/mycli.egg-info → mycli-2.4.0}/PKG-INFO +30 -13
- {mycli-2.2.0 → mycli-2.4.0}/README.md +29 -12
- {mycli-2.2.0 → mycli-2.4.0}/changelog.md +38 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/TIPS +9 -1
- {mycli-2.2.0 → mycli-2.4.0}/mycli/cli_runner.py +59 -19
- {mycli-2.2.0 → mycli-2.4.0}/mycli/clibuffer.py +1 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/client.py +18 -3
- {mycli-2.2.0 → mycli-2.4.0}/mycli/client_connection.py +52 -22
- {mycli-2.2.0 → mycli-2.4.0}/mycli/client_query.py +2 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/clitoolbar.py +13 -13
- {mycli-2.2.0 → mycli-2.4.0}/mycli/completion_refresher.py +56 -21
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main.py +0 -9
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main_modes/execute.py +3 -3
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main_modes/repl.py +26 -1
- {mycli-2.2.0 → mycli-2.4.0}/mycli/myclirc +44 -1
- {mycli-2.2.0 → mycli-2.4.0}/mycli/output.py +34 -5
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/__init__.py +4 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/iocommands.py +11 -1
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/main.py +9 -1
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/utils.py +21 -6
- mycli-2.4.0/mycli/password_sources.py +77 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/schema_prefetcher.py +27 -3
- {mycli-2.2.0 → mycli-2.4.0}/mycli/sqlexecute.py +6 -0
- {mycli-2.2.0 → mycli-2.4.0/mycli.egg-info}/PKG-INFO +30 -13
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/SOURCES.txt +2 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/scm_file_list.json +131 -129
- mycli-2.4.0/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/fixture_data/help_commands.txt +8 -7
- {mycli-2.2.0 → mycli-2.4.0}/test/myclirc +43 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_cli_runner.py +295 -9
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_client.py +42 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_client_connection.py +176 -49
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_clitoolbar.py +3 -3
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_completion_refresher.py +133 -1
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_main.py +33 -22
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_main_modes_repl.py +71 -1
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_output.py +102 -0
- mycli-2.4.0/test/pytests/test_password_sources.py +81 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_schema_prefetcher.py +140 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_iocommands.py +4 -2
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_utils.py +20 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_sqlexecute.py +12 -5
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_tabular_output.py +9 -1
- {mycli-2.2.0 → mycli-2.4.0}/test/utils.py +1 -0
- mycli-2.2.0/mycli.egg-info/scm_version.json +0 -8
- {mycli-2.2.0 → mycli-2.4.0}/.git-blame-ignore-revs +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/dependabot.yml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/workflows/ci.yml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/workflows/lint.yml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/workflows/publish.yml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.github/workflows/typecheck.yml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/.gitignore +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/AUTHORS.rst +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/CONTRIBUTING.md +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/LICENSE.txt +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/MANIFEST.in +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/SPONSORS.rst +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/doc/key_bindings.rst +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/doc/llm.md +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/doc/screenshots/main.gif +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/doc/screenshots/tables.png +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/AUTHORS +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/SPONSORS +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/app_state.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/client_commands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/clistyle.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/compat.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/config.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/constants.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/key_bindings.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/lexer.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main_modes/batch.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main_modes/checkup.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/main_modes/list_dsn.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/batch_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/cli_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/completion_engine.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/filepaths.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/hybrid_redirection.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/interactive_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/key_binding_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/ptoolkit/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/ptoolkit/fzf.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/ptoolkit/history.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/ptoolkit/utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/dbcommands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/delimitercommand.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/dsn_aliases.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/favoritequeries.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/special/llm.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/sql_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/sqlresult.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/string_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/tabular_output/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/sqlcompleter.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/ssh_tunnel.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/types.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli/vault.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/requires.txt +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/pyproject.toml +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/setup.cfg +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/auto_vertical.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/basic_commands.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/connection.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/crud_database.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/crud_table.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/db_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/environment.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/fixture_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/iocommands.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/named_queries.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/specials.feature +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/__init__.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/auto_vertical.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/basic_commands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/connection.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/crud_database.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/crud_table.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/iocommands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/named_queries.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/specials.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/steps/wrappers.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/features/wrappager.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/mylogin.cnf +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/conftest.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_app_state.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_batch_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_checkup.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_cli_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_clibuffer.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_client_commands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_client_query.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_clistyle.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_completer_use_switch.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_completion_engine.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_config.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_dsn_aliases.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_favoritequeries.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_filepaths.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_hybrid_redirection.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_key_bindings.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_lexer.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_main_modes_list_dsn.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_naive_completion.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_ptoolkit_fzf.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_ptoolkit_history.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_ptoolkit_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_smart_completion_public_schema_only.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_dbcommands.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_init.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_llm.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_special_main.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_sql_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_sqlcompleter.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_sqlresult.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_ssh_tunnel.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_string_utils.py +0 -0
- {mycli-2.2.0 → mycli-2.4.0}/test/pytests/test_vault.py +0 -0
|
@@ -31,7 +31,7 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
31
31
|
├── mycli/main_modes/checkup.py # `--checkup` mode
|
|
32
32
|
├── mycli/main_modes/execute.py # `--execute` mode
|
|
33
33
|
├── mycli/main_modes/list_dsn.py # `--list-dsn` mode
|
|
34
|
-
├── mycli/main_modes/repl.py # interactive REPL
|
|
34
|
+
├── mycli/main_modes/repl.py # interactive REPL mode
|
|
35
35
|
├── mycli/myclirc # project-level configuration file
|
|
36
36
|
├── mycli/output.py # `OutputMixin` mixin for feedback and output of query results
|
|
37
37
|
├── mycli/packages/ # application packages
|
|
@@ -48,16 +48,18 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
48
48
|
├── mycli/packages/sqlresult.py # the `SQLResult` dataclass for holding responses
|
|
49
49
|
├── mycli/packages/string_utils.py # generic string utilities
|
|
50
50
|
├── mycli/packages/tabular_output/ # extends cli_helper with additional output formats
|
|
51
|
+
├── mycli/password_sources.py # password sources and precedence
|
|
52
|
+
├── mycli/ssh_tunnel.py # connecting over a tunnel with `--ssh-jump`
|
|
51
53
|
├── mycli/schema_prefetcher.py # background prefetcher for multi-schema auto-completion
|
|
52
54
|
├── mycli/sqlcompleter.py # offers SQL completions
|
|
53
55
|
├── mycli/sqlexecute.py # runs SQL queries
|
|
54
56
|
├── mycli/types.py # shared types
|
|
55
57
|
├── mycli/vault.py # Vault integration
|
|
56
|
-
├── test/conftest.py # pytest configuration
|
|
57
58
|
├── test/features/ # behave tests
|
|
58
59
|
├── test/myclirc # mycli configuration used for tests
|
|
59
60
|
├── test/mylogin.cnf # `mylogin.cnf` example used for tests
|
|
60
61
|
├── test/pytests/ # pytest tests
|
|
62
|
+
├── test/pytests/conftest.py # pytest configuration
|
|
61
63
|
└── test/utils.py # shared utilities for tests
|
|
62
64
|
|
|
63
65
|
## Development
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: CLI for MySQL Database. With auto-completion and syntax highlighting.
|
|
5
5
|
Author: Mycli Core Team
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -89,13 +89,13 @@ You might need `sudo` on Linux.
|
|
|
89
89
|
pip install --upgrade 'mycli[all]'
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
or, only on macOS (`fzf` and `pygments` are optional):
|
|
92
|
+
or, only on macOS (`fzf` and `pygments` are optional but recommended):
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
95
|
brew update && brew install mycli fzf pygments
|
|
96
96
|
```
|
|
97
97
|
|
|
98
|
-
or, only on Debian or Ubuntu (`fzf` and `pygments` are optional):
|
|
98
|
+
or, only on Debian or Ubuntu (`fzf` and `pygments` are optional but recommended):
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
101
|
sudo apt-get install mycli fzf python3-pygments
|
|
@@ -115,6 +115,7 @@ Features
|
|
|
115
115
|
* Auto-completion as you type for SQL keywords as well as tables, views,
|
|
116
116
|
columns, enums, and more!
|
|
117
117
|
* Fuzzy history search using [fzf](https://github.com/junegunn/fzf).
|
|
118
|
+
* Output explorer using [fzf](https://github.com/junegunn/fzf) or other tools.
|
|
118
119
|
* Syntax highlighting using [Pygments](https://pygments.org/).
|
|
119
120
|
* Smart-completion (enabled by default) will suggest context-sensitive completion.
|
|
120
121
|
- `SELECT * FROM <tab>` will only show table names.
|
|
@@ -158,15 +159,15 @@ These are some alternative ways to install mycli that are not managed by our
|
|
|
158
159
|
team but provided by OS package maintainers. OS packages could be somewhat
|
|
159
160
|
out of date.
|
|
160
161
|
|
|
161
|
-
If present, the `fzf` package can be used for fuzzy history search, and
|
|
162
|
-
`pygemtize` can be used for
|
|
163
|
-
search. The `less` package is
|
|
164
|
-
installed.
|
|
162
|
+
If present, the `fzf` package can be used for fuzzy history search, and as an
|
|
163
|
+
output "explorer" with the `\x` special command. `pygemtize` can be used for
|
|
164
|
+
syntax highlighting within the fuzzy history search. The `less` package is
|
|
165
|
+
also expected, but almost always already installed.
|
|
165
166
|
|
|
166
167
|
### Arch, Manjaro
|
|
167
168
|
|
|
168
169
|
You can install the `mycli` package available in the AUR. `fzf` and
|
|
169
|
-
`python-pygments` are optional:
|
|
170
|
+
`python-pygments` are optional but recommended:
|
|
170
171
|
|
|
171
172
|
```bash
|
|
172
173
|
yay -S mycli fzf python-pygments
|
|
@@ -175,7 +176,8 @@ yay -S mycli fzf python-pygments
|
|
|
175
176
|
### Debian, Ubuntu
|
|
176
177
|
|
|
177
178
|
On Debian and Ubuntu distributions, you can easily install the mycli package
|
|
178
|
-
using apt. The `fzf` and `python3-pygments` packages are optional
|
|
179
|
+
using apt. The `fzf` and `python3-pygments` packages are optional but
|
|
180
|
+
recommended:
|
|
179
181
|
|
|
180
182
|
```bash
|
|
181
183
|
sudo apt-get install mycli fzf python3-pygments
|
|
@@ -184,7 +186,7 @@ sudo apt-get install mycli fzf python3-pygments
|
|
|
184
186
|
### Fedora
|
|
185
187
|
|
|
186
188
|
Fedora has a package available for mycli; install it using dnf. The `fzf` and
|
|
187
|
-
`python-pygments` packages are optional:
|
|
189
|
+
`python-pygments` packages are optional but recommended:
|
|
188
190
|
|
|
189
191
|
```bash
|
|
190
192
|
sudo dnf install mycli fzf python-pygments
|
|
@@ -196,7 +198,9 @@ sudo dnf install mycli fzf python-pygments
|
|
|
196
198
|
|
|
197
199
|
Install the `less` pager, for example by `scoop install less`.
|
|
198
200
|
|
|
199
|
-
|
|
201
|
+
Install the `fzf` fuzzy finder, for example by `scoop install fzf`.
|
|
202
|
+
|
|
203
|
+
Follow the instructions on this blog post: https://web.archive.org/web/20221006045208/https://www.codewall.co.uk/installing-using-mycli-on-windows/
|
|
200
204
|
|
|
201
205
|
The libraries used in mycli are Windows-compatible, but there are known
|
|
202
206
|
limitations according to the test suite. The basics work without any
|
|
@@ -209,11 +213,24 @@ PRs to address shortcomings on Windows would be welcome!
|
|
|
209
213
|
Mycli is more compatible with WSL than with native Windows, though still
|
|
210
214
|
not 100% perfect. This is a good option for using mycli on Windows.
|
|
211
215
|
|
|
216
|
+
With WSL, you are probably using an Ubuntu distribution, in which case
|
|
217
|
+
recommended dependencies can be installed by
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
sudo apt-get install fzf python3-pygments
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
and mycli can be installed by `apt-get` or by `pip` (recommended):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
pip install --upgrade 'mycli[all]'
|
|
227
|
+
```
|
|
228
|
+
|
|
212
229
|
PRs to complete WSL support would be welcome!
|
|
213
230
|
|
|
214
231
|
### Thanks
|
|
215
232
|
|
|
216
|
-
This project was funded through
|
|
233
|
+
This project was funded through Kickstarter. Our thanks to the [backers](https://mycli.net/sponsors) who supported the project.
|
|
217
234
|
|
|
218
235
|
A special thanks to [Jonathan Slenders](https://twitter.com/jonathan_s) for
|
|
219
236
|
creating [Python Prompt Toolkit](https://github.com/jonathanslenders/python-prompt-toolkit),
|
|
@@ -241,7 +258,7 @@ following in `~/.myclirc`:
|
|
|
241
258
|
default_character_set = utf8
|
|
242
259
|
```
|
|
243
260
|
|
|
244
|
-
or set `--charset=utf8` when invoking
|
|
261
|
+
or set `--charset=utf8` when invoking mycli
|
|
245
262
|
|
|
246
263
|
### Configuration and Usage
|
|
247
264
|
|
|
@@ -32,13 +32,13 @@ You might need `sudo` on Linux.
|
|
|
32
32
|
pip install --upgrade 'mycli[all]'
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
or, only on macOS (`fzf` and `pygments` are optional):
|
|
35
|
+
or, only on macOS (`fzf` and `pygments` are optional but recommended):
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
brew update && brew install mycli fzf pygments
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
or, only on Debian or Ubuntu (`fzf` and `pygments` are optional):
|
|
41
|
+
or, only on Debian or Ubuntu (`fzf` and `pygments` are optional but recommended):
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
44
|
sudo apt-get install mycli fzf python3-pygments
|
|
@@ -58,6 +58,7 @@ Features
|
|
|
58
58
|
* Auto-completion as you type for SQL keywords as well as tables, views,
|
|
59
59
|
columns, enums, and more!
|
|
60
60
|
* Fuzzy history search using [fzf](https://github.com/junegunn/fzf).
|
|
61
|
+
* Output explorer using [fzf](https://github.com/junegunn/fzf) or other tools.
|
|
61
62
|
* Syntax highlighting using [Pygments](https://pygments.org/).
|
|
62
63
|
* Smart-completion (enabled by default) will suggest context-sensitive completion.
|
|
63
64
|
- `SELECT * FROM <tab>` will only show table names.
|
|
@@ -101,15 +102,15 @@ These are some alternative ways to install mycli that are not managed by our
|
|
|
101
102
|
team but provided by OS package maintainers. OS packages could be somewhat
|
|
102
103
|
out of date.
|
|
103
104
|
|
|
104
|
-
If present, the `fzf` package can be used for fuzzy history search, and
|
|
105
|
-
`pygemtize` can be used for
|
|
106
|
-
search. The `less` package is
|
|
107
|
-
installed.
|
|
105
|
+
If present, the `fzf` package can be used for fuzzy history search, and as an
|
|
106
|
+
output "explorer" with the `\x` special command. `pygemtize` can be used for
|
|
107
|
+
syntax highlighting within the fuzzy history search. The `less` package is
|
|
108
|
+
also expected, but almost always already installed.
|
|
108
109
|
|
|
109
110
|
### Arch, Manjaro
|
|
110
111
|
|
|
111
112
|
You can install the `mycli` package available in the AUR. `fzf` and
|
|
112
|
-
`python-pygments` are optional:
|
|
113
|
+
`python-pygments` are optional but recommended:
|
|
113
114
|
|
|
114
115
|
```bash
|
|
115
116
|
yay -S mycli fzf python-pygments
|
|
@@ -118,7 +119,8 @@ yay -S mycli fzf python-pygments
|
|
|
118
119
|
### Debian, Ubuntu
|
|
119
120
|
|
|
120
121
|
On Debian and Ubuntu distributions, you can easily install the mycli package
|
|
121
|
-
using apt. The `fzf` and `python3-pygments` packages are optional
|
|
122
|
+
using apt. The `fzf` and `python3-pygments` packages are optional but
|
|
123
|
+
recommended:
|
|
122
124
|
|
|
123
125
|
```bash
|
|
124
126
|
sudo apt-get install mycli fzf python3-pygments
|
|
@@ -127,7 +129,7 @@ sudo apt-get install mycli fzf python3-pygments
|
|
|
127
129
|
### Fedora
|
|
128
130
|
|
|
129
131
|
Fedora has a package available for mycli; install it using dnf. The `fzf` and
|
|
130
|
-
`python-pygments` packages are optional:
|
|
132
|
+
`python-pygments` packages are optional but recommended:
|
|
131
133
|
|
|
132
134
|
```bash
|
|
133
135
|
sudo dnf install mycli fzf python-pygments
|
|
@@ -139,7 +141,9 @@ sudo dnf install mycli fzf python-pygments
|
|
|
139
141
|
|
|
140
142
|
Install the `less` pager, for example by `scoop install less`.
|
|
141
143
|
|
|
142
|
-
|
|
144
|
+
Install the `fzf` fuzzy finder, for example by `scoop install fzf`.
|
|
145
|
+
|
|
146
|
+
Follow the instructions on this blog post: https://web.archive.org/web/20221006045208/https://www.codewall.co.uk/installing-using-mycli-on-windows/
|
|
143
147
|
|
|
144
148
|
The libraries used in mycli are Windows-compatible, but there are known
|
|
145
149
|
limitations according to the test suite. The basics work without any
|
|
@@ -152,11 +156,24 @@ PRs to address shortcomings on Windows would be welcome!
|
|
|
152
156
|
Mycli is more compatible with WSL than with native Windows, though still
|
|
153
157
|
not 100% perfect. This is a good option for using mycli on Windows.
|
|
154
158
|
|
|
159
|
+
With WSL, you are probably using an Ubuntu distribution, in which case
|
|
160
|
+
recommended dependencies can be installed by
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
sudo apt-get install fzf python3-pygments
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
and mycli can be installed by `apt-get` or by `pip` (recommended):
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pip install --upgrade 'mycli[all]'
|
|
170
|
+
```
|
|
171
|
+
|
|
155
172
|
PRs to complete WSL support would be welcome!
|
|
156
173
|
|
|
157
174
|
### Thanks
|
|
158
175
|
|
|
159
|
-
This project was funded through
|
|
176
|
+
This project was funded through Kickstarter. Our thanks to the [backers](https://mycli.net/sponsors) who supported the project.
|
|
160
177
|
|
|
161
178
|
A special thanks to [Jonathan Slenders](https://twitter.com/jonathan_s) for
|
|
162
179
|
creating [Python Prompt Toolkit](https://github.com/jonathanslenders/python-prompt-toolkit),
|
|
@@ -184,7 +201,7 @@ following in `~/.myclirc`:
|
|
|
184
201
|
default_character_set = utf8
|
|
185
202
|
```
|
|
186
203
|
|
|
187
|
-
or set `--charset=utf8` when invoking
|
|
204
|
+
or set `--charset=utf8` when invoking mycli
|
|
188
205
|
|
|
189
206
|
### Configuration and Usage
|
|
190
207
|
|
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
2.4.0 (2026/07/18)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
---------
|
|
6
|
+
* Make password sources and precedence configurable.
|
|
7
|
+
* Ability to deselect fallback interactive password prompt.
|
|
8
|
+
* Add `\e` prompt/toolbar format string for edit mode.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
Bug Fixes
|
|
12
|
+
---------
|
|
13
|
+
* Don't create `~/.myclirc` if the user adopted the XDG layout for myclirc.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Internal
|
|
17
|
+
---------
|
|
18
|
+
* Make flaky `/watch` test even more lenient for CI.
|
|
19
|
+
* Add missing file to `AGENTS.md` project layout.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
2.3.0 (2026/07/16)
|
|
23
|
+
==============
|
|
24
|
+
|
|
25
|
+
Features
|
|
26
|
+
---------
|
|
27
|
+
* Set minimum times for transient toolbar messages.
|
|
28
|
+
* `editor_command` entry in `~/.myclirc` which overrides environment.
|
|
29
|
+
* Experimental: let Vault properties be set in DSNs.
|
|
30
|
+
* Add a `\x` special command to send output to an explorer rather than a pager.
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
Documentation
|
|
34
|
+
---------
|
|
35
|
+
* Spellcheck myclirc commentary.
|
|
36
|
+
* Better ordering for `/help` table.
|
|
37
|
+
|
|
38
|
+
|
|
1
39
|
2.2.0 (2026/07/11)
|
|
2
40
|
==============
|
|
3
41
|
|
|
@@ -138,7 +138,9 @@ set environment variable MYSQL_DSN to set a default DSN!
|
|
|
138
138
|
### general
|
|
139
139
|
###
|
|
140
140
|
|
|
141
|
-
display
|
|
141
|
+
display output vertically using \G at the end of a query!
|
|
142
|
+
|
|
143
|
+
display output in an interactive explorer \x at the end of a query!
|
|
142
144
|
|
|
143
145
|
run SQL scripts in batch mode using the standard input!
|
|
144
146
|
|
|
@@ -282,6 +284,12 @@ use "min_completion_trigger" in ~/.myclirc to defer completions!
|
|
|
282
284
|
|
|
283
285
|
colorize search previews with "highlight_preview" in ~/.myclirc!
|
|
284
286
|
|
|
287
|
+
set editor_command = "code --wait" in ~/.myclirc to edit queries using VS Code!
|
|
288
|
+
|
|
289
|
+
set up an interactive output explorer using the "[explorer]" section of ~/.myclirc!
|
|
290
|
+
|
|
291
|
+
customize password sources/precedence with "password_sources" in ~/.myclirc!
|
|
292
|
+
|
|
285
293
|
###
|
|
286
294
|
### redirection
|
|
287
295
|
###
|
|
@@ -15,6 +15,7 @@ from mycli.main_modes.checkup import main_checkup
|
|
|
15
15
|
from mycli.main_modes.execute import main_execute_from_cli
|
|
16
16
|
from mycli.main_modes.list_dsn import main_list_dsn
|
|
17
17
|
from mycli.packages.cli_utils import is_valid_connection_scheme
|
|
18
|
+
from mycli.password_sources import PasswordCandidates
|
|
18
19
|
from mycli.vault import (
|
|
19
20
|
DEFAULT_VAULT_EXECUTABLE,
|
|
20
21
|
DEFAULT_VAULT_PASSWORD_FIELD,
|
|
@@ -41,6 +42,11 @@ KNOWN_DSN_QUERY_PARAMS = {
|
|
|
41
42
|
'ssl_mode',
|
|
42
43
|
'ssl_verify_server_cert',
|
|
43
44
|
'tls_version',
|
|
45
|
+
'vault_address',
|
|
46
|
+
'vault_mount',
|
|
47
|
+
'vault_secret',
|
|
48
|
+
'vault_password_field',
|
|
49
|
+
'vault_username_field',
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
|
|
@@ -160,10 +166,15 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
160
166
|
database = cli_args.dbname or cli_args.database
|
|
161
167
|
|
|
162
168
|
dsn_uri = None
|
|
169
|
+
dsn_password: str | None = None
|
|
163
170
|
|
|
164
171
|
# Treat the database argument as a DSN alias only if it matches a configured alias
|
|
165
172
|
# todo why is port tested but not socket?
|
|
166
|
-
truthy_password =
|
|
173
|
+
truthy_password = (
|
|
174
|
+
cli_args.password not in (None, EMPTY_PASSWORD_FLAG_SENTINEL)
|
|
175
|
+
or cli_args.password_file is not None
|
|
176
|
+
or os.environ.get('MYSQL_PWD') is not None
|
|
177
|
+
)
|
|
167
178
|
if (
|
|
168
179
|
database
|
|
169
180
|
and "://" not in database
|
|
@@ -230,9 +241,6 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
230
241
|
database = dsn_database
|
|
231
242
|
if not cli_args.user and dsn_user is not None:
|
|
232
243
|
cli_args.user = dsn_user
|
|
233
|
-
# todo: rationalize the behavior of empty-string passwords here
|
|
234
|
-
if not cli_args.password and dsn_password is not None:
|
|
235
|
-
cli_args.password = dsn_password
|
|
236
244
|
if not cli_args.host:
|
|
237
245
|
cli_args.host = dsn_host
|
|
238
246
|
if not cli_args.port:
|
|
@@ -277,6 +285,16 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
277
285
|
cli_args.character_set = cli_args.character_set or params[0]
|
|
278
286
|
if params := dsn_params.get('ssh_jump'):
|
|
279
287
|
cli_args.ssh_jump = cli_args.ssh_jump or params[0]
|
|
288
|
+
if params := dsn_params.get('vault_address'):
|
|
289
|
+
cli_args.vault_address = cli_args.vault_address or params[0]
|
|
290
|
+
if params := dsn_params.get('vault_mount'):
|
|
291
|
+
cli_args.vault_mount = cli_args.vault_mount or params[0]
|
|
292
|
+
if params := dsn_params.get('vault_secret'):
|
|
293
|
+
cli_args.vault_secret = cli_args.vault_secret or params[0]
|
|
294
|
+
if params := dsn_params.get('vault_password_field'):
|
|
295
|
+
cli_args.vault_password_field = cli_args.vault_password_field or params[0]
|
|
296
|
+
if params := dsn_params.get('vault_username_field'):
|
|
297
|
+
cli_args.vault_username_field = cli_args.vault_username_field or params[0]
|
|
280
298
|
|
|
281
299
|
keepalive_ticks = cli_args.keepalive_ticks if cli_args.keepalive_ticks is not None else mycli.default_keepalive_ticks
|
|
282
300
|
ssl_mode = cli_args.ssl_mode or mycli.ssl_mode
|
|
@@ -349,25 +367,40 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
349
367
|
use_keyring = str_to_bool(cli_args.use_keyring)
|
|
350
368
|
reset_keyring = False
|
|
351
369
|
|
|
352
|
-
|
|
370
|
+
password_candidates = PasswordCandidates()
|
|
371
|
+
if cli_args.password == EMPTY_PASSWORD_FLAG_SENTINEL:
|
|
372
|
+
password_candidates.add_value('prompt', cli_args.password)
|
|
373
|
+
elif cli_args.password is not None:
|
|
374
|
+
password_candidates.add_value('literal', cli_args.password)
|
|
375
|
+
if cli_args.password_file:
|
|
376
|
+
password_candidates.add_loader('file', lambda: main_module.get_password_from_file(cli_args.password_file))
|
|
377
|
+
if os.environ.get('MYSQL_PWD') is not None:
|
|
378
|
+
password_candidates.add_value('environment', os.environ.get('MYSQL_PWD'))
|
|
379
|
+
if dsn_password is not None:
|
|
380
|
+
password_candidates.add_value('dsn', dsn_password)
|
|
381
|
+
|
|
382
|
+
if cli_args.vault_secret:
|
|
383
|
+
vault_secret = cli_args.vault_secret
|
|
353
384
|
vault_config = mycli.config.get('vault_beta', {})
|
|
354
385
|
vault_address = cli_args.vault_address or os.environ.get('VAULT_ADDR') or vault_config.get('address') or None
|
|
355
386
|
vault_mount = cli_args.vault_mount or vault_config.get('default_mount') or None
|
|
356
387
|
vault_field = cli_args.vault_password_field or vault_config.get('default_password_field') or DEFAULT_VAULT_PASSWORD_FIELD
|
|
357
388
|
vault_executable = vault_config.get('vault_executable') or DEFAULT_VAULT_EXECUTABLE
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
389
|
+
|
|
390
|
+
def load_vault_password() -> str | None:
|
|
391
|
+
try:
|
|
392
|
+
return get_field_from_vault(
|
|
393
|
+
vault_field,
|
|
394
|
+
vault_secret,
|
|
395
|
+
executable=vault_executable,
|
|
396
|
+
mount=vault_mount,
|
|
397
|
+
address=vault_address,
|
|
398
|
+
)
|
|
399
|
+
except VaultError as exc:
|
|
400
|
+
click.secho(f'Error reading password from Vault: {exc}', err=True, fg='red')
|
|
401
|
+
sys.exit(1)
|
|
402
|
+
|
|
403
|
+
password_candidates.add_loader('vault', load_vault_password)
|
|
371
404
|
|
|
372
405
|
if cli_args.user is None and cli_args.vault_secret:
|
|
373
406
|
vault_config = mycli.config.get('vault_beta', {})
|
|
@@ -388,12 +421,13 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
388
421
|
sys.exit(1)
|
|
389
422
|
else:
|
|
390
423
|
vault_username = None
|
|
424
|
+
vault_username_from_vault = vault_username is not None
|
|
391
425
|
|
|
392
426
|
try:
|
|
393
427
|
mycli.connect(
|
|
394
428
|
database=database,
|
|
395
429
|
user=vault_username if cli_args.user is None else cli_args.user,
|
|
396
|
-
|
|
430
|
+
password_candidates=password_candidates,
|
|
397
431
|
host=cli_args.host,
|
|
398
432
|
port=cli_args.port,
|
|
399
433
|
socket=cli_args.socket,
|
|
@@ -407,6 +441,12 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
407
441
|
keepalive_ticks=keepalive_ticks,
|
|
408
442
|
ssh_jump=cli_args.ssh_jump,
|
|
409
443
|
ssh_cli_options=cli_args.ssh_options,
|
|
444
|
+
vault_address=cli_args.vault_address,
|
|
445
|
+
vault_mount=cli_args.vault_mount,
|
|
446
|
+
vault_secret=cli_args.vault_secret,
|
|
447
|
+
vault_password_field=cli_args.vault_password_field,
|
|
448
|
+
vault_username_field=cli_args.vault_username_field,
|
|
449
|
+
vault_username_from_vault=vault_username_from_vault,
|
|
410
450
|
)
|
|
411
451
|
|
|
412
452
|
if combined_init_cmd:
|
|
@@ -58,9 +58,9 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
58
58
|
|
|
59
59
|
# check XDG_CONFIG_HOME exists and not an empty string
|
|
60
60
|
xdg_config_home = os.environ.get("XDG_CONFIG_HOME", "~/.config")
|
|
61
|
+
xdg_config_file = os.path.join(os.path.expanduser(xdg_config_home), "mycli", "myclirc")
|
|
61
62
|
system_config_files: list[str | IO[str]] = [
|
|
62
63
|
"/etc/myclirc",
|
|
63
|
-
os.path.join(os.path.expanduser(xdg_config_home), "mycli", "myclirc"),
|
|
64
64
|
]
|
|
65
65
|
|
|
66
66
|
def __init__(
|
|
@@ -72,7 +72,7 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
72
72
|
login_path: str | None = None,
|
|
73
73
|
auto_vertical_output: bool = False,
|
|
74
74
|
warn: bool | None = None,
|
|
75
|
-
myclirc: str =
|
|
75
|
+
myclirc: str | None = None,
|
|
76
76
|
show_warnings: bool | None = None,
|
|
77
77
|
cli_verbosity: int = 0,
|
|
78
78
|
) -> None:
|
|
@@ -87,6 +87,12 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
87
87
|
self.sandbox_mode: bool = False
|
|
88
88
|
self.checkpoint: IO | None = None
|
|
89
89
|
|
|
90
|
+
if myclirc is None:
|
|
91
|
+
if os.path.exists(self.xdg_config_file):
|
|
92
|
+
myclirc = self.xdg_config_file
|
|
93
|
+
else:
|
|
94
|
+
myclirc = '~/.myclirc'
|
|
95
|
+
|
|
90
96
|
# Load config.
|
|
91
97
|
config_files: list[str | IO[str]] = self.system_config_files + [myclirc]
|
|
92
98
|
|
|
@@ -114,10 +120,15 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
114
120
|
self.dsn_alias: str | None = None
|
|
115
121
|
self.main_formatter = TabularOutputFormatter(format_name=c["main"]["table_format"])
|
|
116
122
|
self.redirect_formatter = TabularOutputFormatter(format_name=c["main"].get("redirect_format", "csv"))
|
|
123
|
+
self.explorer_formatter = TabularOutputFormatter(format_name=c['explorer'].get('format', self.main_formatter))
|
|
117
124
|
sql_format.register_new_formatter(self.main_formatter)
|
|
118
125
|
sql_format.register_new_formatter(self.redirect_formatter)
|
|
126
|
+
sql_format.register_new_formatter(self.explorer_formatter)
|
|
119
127
|
self.main_formatter.mycli = self
|
|
120
128
|
self.redirect_formatter.mycli = self
|
|
129
|
+
self.explorer_formatter.mycli = self
|
|
130
|
+
self.explorer_command = c['explorer'].get('explorer_command')
|
|
131
|
+
self.explorer_trim_footer = c['explorer'].as_bool('trim_footer')
|
|
121
132
|
self.syntax_style = c["main"]["syntax_style"]
|
|
122
133
|
self.verbosity = -1 if c["main"].as_bool("less_chatty") else 0
|
|
123
134
|
if cli_verbosity:
|
|
@@ -155,7 +166,7 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
155
166
|
self.echo("Error: Unable to open the audit log file. Your queries will not be logged.", err=True, fg="red")
|
|
156
167
|
self.logfile = False
|
|
157
168
|
|
|
158
|
-
self.completion_refresher = CompletionRefresher()
|
|
169
|
+
self.completion_refresher = CompletionRefresher(self._invalidate_prompt_session)
|
|
159
170
|
self.prefetch_schemas_mode = c["main"].get("prefetch_schemas_mode", "always") or "always"
|
|
160
171
|
raw_prefetch_list = c["main"].as_list("prefetch_schemas_list") if "prefetch_schemas_list" in c["main"] else []
|
|
161
172
|
self.prefetch_schemas_list = [s.strip() for s in raw_prefetch_list if s and s.strip()]
|
|
@@ -201,6 +212,10 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
201
212
|
self.destructive_keywords = destructive_keywords_from_config(c)
|
|
202
213
|
special.set_destructive_keywords(self.destructive_keywords)
|
|
203
214
|
|
|
215
|
+
def _invalidate_prompt_session(self) -> None:
|
|
216
|
+
if self.prompt_session:
|
|
217
|
+
self.prompt_session.app.invalidate()
|
|
218
|
+
|
|
204
219
|
def close(self) -> None:
|
|
205
220
|
try:
|
|
206
221
|
self.schema_prefetcher.stop()
|