mycli 2.1.1__tar.gz → 2.3.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.1.1 → mycli-2.3.0}/.github/workflows/ci.yml +4 -4
- {mycli-2.1.1 → mycli-2.3.0}/.github/workflows/publish.yml +4 -4
- {mycli-2.1.1 → mycli-2.3.0}/.github/workflows/typecheck.yml +1 -1
- {mycli-2.1.1 → mycli-2.3.0}/AGENTS.md +9 -5
- {mycli-2.1.1/mycli.egg-info → mycli-2.3.0}/PKG-INFO +30 -13
- {mycli-2.1.1 → mycli-2.3.0}/README.md +29 -12
- {mycli-2.1.1 → mycli-2.3.0}/changelog.md +52 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/TIPS +9 -1
- {mycli-2.1.1 → mycli-2.3.0}/mycli/cli_runner.py +97 -11
- {mycli-2.1.1 → mycli-2.3.0}/mycli/clibuffer.py +1 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/client.py +10 -1
- {mycli-2.1.1 → mycli-2.3.0}/mycli/client_connection.py +56 -6
- {mycli-2.1.1 → mycli-2.3.0}/mycli/client_query.py +2 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/completion_refresher.py +56 -21
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main.py +24 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main_modes/execute.py +3 -3
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main_modes/repl.py +17 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/myclirc +56 -8
- {mycli-2.1.1 → mycli-2.3.0}/mycli/output.py +34 -5
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/__init__.py +4 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/dsn_aliases.py +4 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/iocommands.py +11 -1
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/main.py +9 -1
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/utils.py +53 -14
- {mycli-2.1.1 → mycli-2.3.0}/mycli/schema_prefetcher.py +27 -3
- {mycli-2.1.1 → mycli-2.3.0}/mycli/sqlexecute.py +10 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/ssh_tunnel.py +74 -17
- mycli-2.3.0/mycli/vault.py +54 -0
- {mycli-2.1.1 → mycli-2.3.0/mycli.egg-info}/PKG-INFO +30 -13
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/SOURCES.txt +3 -1
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/scm_file_list.json +130 -128
- mycli-2.3.0/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/fixture_data/help_commands.txt +8 -7
- {mycli-2.1.1 → mycli-2.3.0}/test/myclirc +55 -7
- mycli-2.3.0/test/pytests/test_cli_runner.py +1033 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_client.py +10 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_client_connection.py +185 -14
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_completion_refresher.py +133 -1
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_main.py +28 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_main_modes_repl.py +47 -1
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_output.py +102 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_schema_prefetcher.py +140 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_iocommands.py +2 -2
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_utils.py +51 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_sqlexecute.py +15 -5
- mycli-2.3.0/test/pytests/test_ssh_tunnel.py +512 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_tabular_output.py +5 -0
- mycli-2.3.0/test/pytests/test_vault.py +96 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/utils.py +1 -0
- mycli-2.1.1/mycli.egg-info/scm_version.json +0 -8
- mycli-2.1.1/test/pytests/test_cli_runner.py +0 -476
- mycli-2.1.1/test/pytests/test_ssh_tunnel.py +0 -307
- {mycli-2.1.1 → mycli-2.3.0}/.git-blame-ignore-revs +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.github/dependabot.yml +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.github/workflows/lint.yml +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/.gitignore +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/AUTHORS.rst +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/CONTRIBUTING.md +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/LICENSE.txt +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/MANIFEST.in +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/SPONSORS.rst +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/doc/key_bindings.rst +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/doc/llm.md +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/doc/screenshots/main.gif +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/doc/screenshots/tables.png +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/AUTHORS +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/SPONSORS +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/app_state.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/client_commands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/clistyle.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/clitoolbar.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/compat.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/config.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/constants.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/key_bindings.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/lexer.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main_modes/batch.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main_modes/checkup.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/main_modes/list_dsn.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/batch_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/cli_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/completion_engine.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/filepaths.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/hybrid_redirection.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/interactive_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/key_binding_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/ptoolkit/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/ptoolkit/fzf.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/ptoolkit/history.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/ptoolkit/utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/dbcommands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/delimitercommand.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/favoritequeries.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/special/llm.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/sql_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/sqlresult.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/string_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/tabular_output/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/sqlcompleter.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli/types.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/requires.txt +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/pyproject.toml +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/setup.cfg +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/auto_vertical.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/basic_commands.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/connection.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/crud_database.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/crud_table.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/db_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/environment.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/fixture_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/iocommands.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/named_queries.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/specials.feature +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/__init__.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/auto_vertical.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/basic_commands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/connection.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/crud_database.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/crud_table.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/iocommands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/named_queries.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/specials.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/steps/wrappers.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/features/wrappager.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/mylogin.cnf +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/conftest.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_app_state.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_batch_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_checkup.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_cli_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_clibuffer.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_client_commands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_client_query.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_clistyle.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_clitoolbar.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_completer_use_switch.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_completion_engine.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_config.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_dsn_aliases.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_favoritequeries.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_filepaths.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_hybrid_redirection.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_key_bindings.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_lexer.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_main_modes_list_dsn.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_naive_completion.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_ptoolkit_fzf.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_ptoolkit_history.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_ptoolkit_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_smart_completion_public_schema_only.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_dbcommands.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_init.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_llm.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_special_main.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_sql_utils.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_sqlcompleter.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_sqlresult.py +0 -0
- {mycli-2.1.1 → mycli-2.3.0}/test/pytests/test_string_utils.py +0 -0
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
steps:
|
|
25
25
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
26
26
|
|
|
27
|
-
- uses: astral-sh/setup-uv@
|
|
27
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
28
28
|
with:
|
|
29
29
|
version: "latest"
|
|
30
30
|
|
|
@@ -66,7 +66,7 @@ jobs:
|
|
|
66
66
|
steps:
|
|
67
67
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
68
68
|
|
|
69
|
-
- uses: astral-sh/setup-uv@
|
|
69
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
70
70
|
with:
|
|
71
71
|
version: "latest"
|
|
72
72
|
|
|
@@ -116,7 +116,7 @@ jobs:
|
|
|
116
116
|
steps:
|
|
117
117
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
118
118
|
|
|
119
|
-
- uses: astral-sh/setup-uv@
|
|
119
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
120
120
|
with:
|
|
121
121
|
version: 'latest'
|
|
122
122
|
|
|
@@ -219,7 +219,7 @@ jobs:
|
|
|
219
219
|
steps:
|
|
220
220
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
221
221
|
|
|
222
|
-
- uses: astral-sh/setup-uv@
|
|
222
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
223
223
|
with:
|
|
224
224
|
version: "latest"
|
|
225
225
|
|
|
@@ -29,7 +29,7 @@ jobs:
|
|
|
29
29
|
|
|
30
30
|
steps:
|
|
31
31
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
32
|
-
- uses: astral-sh/setup-uv@
|
|
32
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
33
33
|
with:
|
|
34
34
|
version: "latest"
|
|
35
35
|
|
|
@@ -74,7 +74,7 @@ jobs:
|
|
|
74
74
|
steps:
|
|
75
75
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
76
76
|
|
|
77
|
-
- uses: astral-sh/setup-uv@
|
|
77
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
78
78
|
with:
|
|
79
79
|
version: "latest"
|
|
80
80
|
|
|
@@ -124,7 +124,7 @@ jobs:
|
|
|
124
124
|
steps:
|
|
125
125
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
126
126
|
|
|
127
|
-
- uses: astral-sh/setup-uv@
|
|
127
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
128
128
|
with:
|
|
129
129
|
version: 'latest'
|
|
130
130
|
|
|
@@ -226,7 +226,7 @@ jobs:
|
|
|
226
226
|
|
|
227
227
|
steps:
|
|
228
228
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
229
|
-
- uses: astral-sh/setup-uv@
|
|
229
|
+
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
|
|
230
230
|
with:
|
|
231
231
|
version: "latest"
|
|
232
232
|
|
|
@@ -27,8 +27,11 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
27
27
|
├── mycli/lexer.py # extends `MySqlLexer` from Pygments
|
|
28
28
|
├── mycli/main.py # processes CLI arguments
|
|
29
29
|
├── mycli/main_modes/ # main execution paths
|
|
30
|
-
├── mycli/main_modes/batch.py # batch mode
|
|
31
|
-
├── mycli/main_modes/checkup.py #
|
|
30
|
+
├── mycli/main_modes/batch.py # `--batch` mode
|
|
31
|
+
├── mycli/main_modes/checkup.py # `--checkup` mode
|
|
32
|
+
├── mycli/main_modes/execute.py # `--execute` mode
|
|
33
|
+
├── mycli/main_modes/list_dsn.py # `--list-dsn` mode
|
|
34
|
+
├── mycli/main_modes/repl.py # interactive REPL mode
|
|
32
35
|
├── mycli/myclirc # project-level configuration file
|
|
33
36
|
├── mycli/output.py # `OutputMixin` mixin for feedback and output of query results
|
|
34
37
|
├── mycli/packages/ # application packages
|
|
@@ -48,13 +51,14 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
48
51
|
├── mycli/schema_prefetcher.py # background prefetcher for multi-schema auto-completion
|
|
49
52
|
├── mycli/sqlcompleter.py # offers SQL completions
|
|
50
53
|
├── mycli/sqlexecute.py # runs SQL queries
|
|
51
|
-
├──
|
|
54
|
+
├── mycli/types.py # shared types
|
|
55
|
+
├── mycli/vault.py # Vault integration
|
|
52
56
|
├── test/features/ # behave tests
|
|
53
57
|
├── test/myclirc # mycli configuration used for tests
|
|
54
58
|
├── test/mylogin.cnf # `mylogin.cnf` example used for tests
|
|
55
59
|
├── test/pytests/ # pytest tests
|
|
56
|
-
├── test/
|
|
57
|
-
└──
|
|
60
|
+
├── test/pytests/conftest.py # pytest configuration
|
|
61
|
+
└── test/utils.py # shared utilities for tests
|
|
58
62
|
|
|
59
63
|
## Development
|
|
60
64
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.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,55 @@
|
|
|
1
|
+
2.3.0 (2026/07/16)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
---------
|
|
6
|
+
* Set minimum times for transient toolbar messages.
|
|
7
|
+
* `editor_command` entry in `~/.myclirc` which overrides environment.
|
|
8
|
+
* Experimental: let Vault properties be set in DSNs.
|
|
9
|
+
* Add a `\x` special command to send output to an explorer rather than a pager.
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Documentation
|
|
13
|
+
---------
|
|
14
|
+
* Spellcheck myclirc commentary.
|
|
15
|
+
* Better ordering for `/help` table.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
2.2.0 (2026/07/11)
|
|
19
|
+
==============
|
|
20
|
+
|
|
21
|
+
Breaking Changes
|
|
22
|
+
---------
|
|
23
|
+
* `ssl` is no longer supported as a DSN parameter. Use `ssl_mode` instead.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Features
|
|
27
|
+
---------
|
|
28
|
+
* Configurable tunnel method for `--ssh-jump`, making UDS usually default.
|
|
29
|
+
* Add `--ssh-options` CLI argument to pass extra options with `--ssh-jump`.
|
|
30
|
+
* Make `ssh_jump` a DSN query parameter.
|
|
31
|
+
* Warn on unknown DSN query parameters.
|
|
32
|
+
* Experimental: reading credentials from Vault using the `vault kv get` CLI.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
Bug Fixes
|
|
36
|
+
---------
|
|
37
|
+
* Allow `/dsn` command to show correct values with `--ssh-jump`.
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
Documentation
|
|
41
|
+
---------
|
|
42
|
+
* Add `--ssh-jump` to TIPS.
|
|
43
|
+
* Better document `/dsn show`.
|
|
44
|
+
* Improve `ssh_options` commentary.
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
Internal
|
|
48
|
+
---------
|
|
49
|
+
* Make flaky `/watch` test more lenient for CI.
|
|
50
|
+
* Tweak `AGENTS.md` project structure.
|
|
51
|
+
|
|
52
|
+
|
|
1
53
|
2.1.1 (2026/07/08)
|
|
2
54
|
==============
|
|
3
55
|
|
|
@@ -40,6 +40,8 @@ the --login-path option lets you work with login-path files!
|
|
|
40
40
|
|
|
41
41
|
--keepalive-ticks=<num> sets keepalive pings for a single session!
|
|
42
42
|
|
|
43
|
+
connect via an SSH tunnel with --ssh-jump!
|
|
44
|
+
|
|
43
45
|
###
|
|
44
46
|
### commands
|
|
45
47
|
###
|
|
@@ -136,7 +138,9 @@ set environment variable MYSQL_DSN to set a default DSN!
|
|
|
136
138
|
### general
|
|
137
139
|
###
|
|
138
140
|
|
|
139
|
-
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!
|
|
140
144
|
|
|
141
145
|
run SQL scripts in batch mode using the standard input!
|
|
142
146
|
|
|
@@ -280,6 +284,10 @@ use "min_completion_trigger" in ~/.myclirc to defer completions!
|
|
|
280
284
|
|
|
281
285
|
colorize search previews with "highlight_preview" in ~/.myclirc!
|
|
282
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
|
+
|
|
283
291
|
###
|
|
284
292
|
### redirection
|
|
285
293
|
###
|
|
@@ -9,18 +9,44 @@ from urllib.parse import parse_qs, unquote, urlparse
|
|
|
9
9
|
import click
|
|
10
10
|
|
|
11
11
|
from mycli.config import str_to_bool
|
|
12
|
-
from mycli.constants import EMPTY_PASSWORD_FLAG_SENTINEL
|
|
12
|
+
from mycli.constants import EMPTY_PASSWORD_FLAG_SENTINEL
|
|
13
13
|
from mycli.main_modes.batch import main_batch_from_stdin, main_batch_with_progress_bar, main_batch_without_progress_bar
|
|
14
14
|
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.vault import (
|
|
19
|
+
DEFAULT_VAULT_EXECUTABLE,
|
|
20
|
+
DEFAULT_VAULT_PASSWORD_FIELD,
|
|
21
|
+
DEFAULT_VAULT_USERNAME_FIELD,
|
|
22
|
+
VaultError,
|
|
23
|
+
get_field_from_vault,
|
|
24
|
+
)
|
|
18
25
|
|
|
19
26
|
if TYPE_CHECKING:
|
|
20
27
|
from mycli.main import CliArgs
|
|
21
28
|
|
|
22
29
|
ClientFactory = Callable[..., Any]
|
|
23
30
|
ENV_VAR_PATTERN = re.compile(r'^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$')
|
|
31
|
+
KNOWN_DSN_QUERY_PARAMS = {
|
|
32
|
+
'character_set',
|
|
33
|
+
'keepalive_ticks',
|
|
34
|
+
'socket',
|
|
35
|
+
'ssh_jump',
|
|
36
|
+
'ssl_ca',
|
|
37
|
+
'ssl_capath',
|
|
38
|
+
'ssl_cert',
|
|
39
|
+
'ssl_cipher',
|
|
40
|
+
'ssl_key',
|
|
41
|
+
'ssl_mode',
|
|
42
|
+
'ssl_verify_server_cert',
|
|
43
|
+
'tls_version',
|
|
44
|
+
'vault_address',
|
|
45
|
+
'vault_mount',
|
|
46
|
+
'vault_secret',
|
|
47
|
+
'vault_password_field',
|
|
48
|
+
'vault_username_field',
|
|
49
|
+
}
|
|
24
50
|
|
|
25
51
|
|
|
26
52
|
class DsnAliasEnvVarError(ValueError):
|
|
@@ -79,7 +105,10 @@ def expand_dsn_alias_env_vars(
|
|
|
79
105
|
except ValueError as exc:
|
|
80
106
|
raise DsnAliasEnvVarError(f'Port in DSN alias {alias_name} must be an integer.') from exc
|
|
81
107
|
|
|
82
|
-
params = {
|
|
108
|
+
params = {
|
|
109
|
+
key: [expand_dsn_alias_env_var(value, alias_name) or '' for value in values]
|
|
110
|
+
for key, values in parse_qs(uri.query, keep_blank_values=True).items()
|
|
111
|
+
}
|
|
83
112
|
|
|
84
113
|
return (
|
|
85
114
|
expand_dsn_alias_env_var(unquote(username) if username is not None else None, alias_name),
|
|
@@ -200,7 +229,7 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
200
229
|
dsn_host = uri.hostname
|
|
201
230
|
dsn_port = uri.port
|
|
202
231
|
dsn_database = uri.path[1:]
|
|
203
|
-
dsn_params = parse_qs(uri.query) if uri.query else {}
|
|
232
|
+
dsn_params = parse_qs(uri.query, keep_blank_values=True) if uri.query else {}
|
|
204
233
|
|
|
205
234
|
if not database:
|
|
206
235
|
database = dsn_database
|
|
@@ -214,16 +243,13 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
214
243
|
if not cli_args.port:
|
|
215
244
|
cli_args.port = dsn_port
|
|
216
245
|
|
|
217
|
-
if
|
|
246
|
+
if unknown_dsn_params := sorted(set(dsn_params) - KNOWN_DSN_QUERY_PARAMS):
|
|
218
247
|
click.secho(
|
|
219
|
-
'Warning:
|
|
220
|
-
'Please use the "ssl_mode" parameter instead. '
|
|
221
|
-
f'See issue {ISSUES_URL}/1507',
|
|
248
|
+
f'Warning: Ignored unknown DSN URI query parameters: {", ".join(unknown_dsn_params)}.',
|
|
222
249
|
err=True,
|
|
223
250
|
fg='yellow',
|
|
224
251
|
)
|
|
225
|
-
|
|
226
|
-
cli_args.ssl_mode = 'on'
|
|
252
|
+
|
|
227
253
|
if params := dsn_params.get('ssl_mode'):
|
|
228
254
|
cli_args.ssl_mode = cli_args.ssl_mode or params[0]
|
|
229
255
|
if params := dsn_params.get('ssl_ca'):
|
|
@@ -254,6 +280,18 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
254
280
|
cli_args.keepalive_ticks = int(params[0])
|
|
255
281
|
if params := dsn_params.get('character_set'):
|
|
256
282
|
cli_args.character_set = cli_args.character_set or params[0]
|
|
283
|
+
if params := dsn_params.get('ssh_jump'):
|
|
284
|
+
cli_args.ssh_jump = cli_args.ssh_jump or params[0]
|
|
285
|
+
if params := dsn_params.get('vault_address'):
|
|
286
|
+
cli_args.vault_address = cli_args.vault_address or params[0]
|
|
287
|
+
if params := dsn_params.get('vault_mount'):
|
|
288
|
+
cli_args.vault_mount = cli_args.vault_mount or params[0]
|
|
289
|
+
if params := dsn_params.get('vault_secret'):
|
|
290
|
+
cli_args.vault_secret = cli_args.vault_secret or params[0]
|
|
291
|
+
if params := dsn_params.get('vault_password_field'):
|
|
292
|
+
cli_args.vault_password_field = cli_args.vault_password_field or params[0]
|
|
293
|
+
if params := dsn_params.get('vault_username_field'):
|
|
294
|
+
cli_args.vault_username_field = cli_args.vault_username_field or params[0]
|
|
257
295
|
|
|
258
296
|
keepalive_ticks = cli_args.keepalive_ticks if cli_args.keepalive_ticks is not None else mycli.default_keepalive_ticks
|
|
259
297
|
ssl_mode = cli_args.ssl_mode or mycli.ssl_mode
|
|
@@ -326,11 +364,52 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
326
364
|
use_keyring = str_to_bool(cli_args.use_keyring)
|
|
327
365
|
reset_keyring = False
|
|
328
366
|
|
|
367
|
+
if cli_args.password is None and cli_args.vault_secret:
|
|
368
|
+
vault_config = mycli.config.get('vault_beta', {})
|
|
369
|
+
vault_address = cli_args.vault_address or os.environ.get('VAULT_ADDR') or vault_config.get('address') or None
|
|
370
|
+
vault_mount = cli_args.vault_mount or vault_config.get('default_mount') or None
|
|
371
|
+
vault_field = cli_args.vault_password_field or vault_config.get('default_password_field') or DEFAULT_VAULT_PASSWORD_FIELD
|
|
372
|
+
vault_executable = vault_config.get('vault_executable') or DEFAULT_VAULT_EXECUTABLE
|
|
373
|
+
try:
|
|
374
|
+
vault_password: str | None = get_field_from_vault(
|
|
375
|
+
vault_field,
|
|
376
|
+
cli_args.vault_secret,
|
|
377
|
+
executable=vault_executable,
|
|
378
|
+
mount=vault_mount,
|
|
379
|
+
address=vault_address,
|
|
380
|
+
)
|
|
381
|
+
except VaultError as exc:
|
|
382
|
+
click.secho(f'Error reading password from Vault: {exc}', err=True, fg='red')
|
|
383
|
+
sys.exit(1)
|
|
384
|
+
else:
|
|
385
|
+
vault_password = None
|
|
386
|
+
|
|
387
|
+
if cli_args.user is None and cli_args.vault_secret:
|
|
388
|
+
vault_config = mycli.config.get('vault_beta', {})
|
|
389
|
+
vault_address = cli_args.vault_address or os.environ.get('VAULT_ADDR') or vault_config.get('address') or None
|
|
390
|
+
vault_mount = cli_args.vault_mount or vault_config.get('default_mount') or None
|
|
391
|
+
vault_field = cli_args.vault_username_field or vault_config.get('default_username_field') or DEFAULT_VAULT_USERNAME_FIELD
|
|
392
|
+
vault_executable = vault_config.get('vault_executable') or DEFAULT_VAULT_EXECUTABLE
|
|
393
|
+
try:
|
|
394
|
+
vault_username = get_field_from_vault(
|
|
395
|
+
vault_field,
|
|
396
|
+
cli_args.vault_secret,
|
|
397
|
+
executable=vault_executable,
|
|
398
|
+
mount=vault_mount,
|
|
399
|
+
address=vault_address,
|
|
400
|
+
)
|
|
401
|
+
except VaultError as exc:
|
|
402
|
+
click.secho(f'Error reading username from Vault: {exc}', err=True, fg='red')
|
|
403
|
+
sys.exit(1)
|
|
404
|
+
else:
|
|
405
|
+
vault_username = None
|
|
406
|
+
vault_username_from_vault = vault_username is not None
|
|
407
|
+
|
|
329
408
|
try:
|
|
330
409
|
mycli.connect(
|
|
331
410
|
database=database,
|
|
332
|
-
user=cli_args.user,
|
|
333
|
-
passwd=cli_args.password,
|
|
411
|
+
user=vault_username if cli_args.user is None else cli_args.user,
|
|
412
|
+
passwd=vault_password if cli_args.password is None else cli_args.password,
|
|
334
413
|
host=cli_args.host,
|
|
335
414
|
port=cli_args.port,
|
|
336
415
|
socket=cli_args.socket,
|
|
@@ -343,6 +422,13 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
343
422
|
reset_keyring=reset_keyring,
|
|
344
423
|
keepalive_ticks=keepalive_ticks,
|
|
345
424
|
ssh_jump=cli_args.ssh_jump,
|
|
425
|
+
ssh_cli_options=cli_args.ssh_options,
|
|
426
|
+
vault_address=cli_args.vault_address,
|
|
427
|
+
vault_mount=cli_args.vault_mount,
|
|
428
|
+
vault_secret=cli_args.vault_secret,
|
|
429
|
+
vault_password_field=cli_args.vault_password_field,
|
|
430
|
+
vault_username_field=cli_args.vault_username_field,
|
|
431
|
+
vault_username_from_vault=vault_username_from_vault,
|
|
346
432
|
)
|
|
347
433
|
|
|
348
434
|
if combined_init_cmd:
|
|
@@ -114,10 +114,15 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
114
114
|
self.dsn_alias: str | None = None
|
|
115
115
|
self.main_formatter = TabularOutputFormatter(format_name=c["main"]["table_format"])
|
|
116
116
|
self.redirect_formatter = TabularOutputFormatter(format_name=c["main"].get("redirect_format", "csv"))
|
|
117
|
+
self.explorer_formatter = TabularOutputFormatter(format_name=c['explorer'].get('format', self.main_formatter))
|
|
117
118
|
sql_format.register_new_formatter(self.main_formatter)
|
|
118
119
|
sql_format.register_new_formatter(self.redirect_formatter)
|
|
120
|
+
sql_format.register_new_formatter(self.explorer_formatter)
|
|
119
121
|
self.main_formatter.mycli = self
|
|
120
122
|
self.redirect_formatter.mycli = self
|
|
123
|
+
self.explorer_formatter.mycli = self
|
|
124
|
+
self.explorer_command = c['explorer'].get('explorer_command')
|
|
125
|
+
self.explorer_trim_footer = c['explorer'].as_bool('trim_footer')
|
|
121
126
|
self.syntax_style = c["main"]["syntax_style"]
|
|
122
127
|
self.verbosity = -1 if c["main"].as_bool("less_chatty") else 0
|
|
123
128
|
if cli_verbosity:
|
|
@@ -155,7 +160,7 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
155
160
|
self.echo("Error: Unable to open the audit log file. Your queries will not be logged.", err=True, fg="red")
|
|
156
161
|
self.logfile = False
|
|
157
162
|
|
|
158
|
-
self.completion_refresher = CompletionRefresher()
|
|
163
|
+
self.completion_refresher = CompletionRefresher(self._invalidate_prompt_session)
|
|
159
164
|
self.prefetch_schemas_mode = c["main"].get("prefetch_schemas_mode", "always") or "always"
|
|
160
165
|
raw_prefetch_list = c["main"].as_list("prefetch_schemas_list") if "prefetch_schemas_list" in c["main"] else []
|
|
161
166
|
self.prefetch_schemas_list = [s.strip() for s in raw_prefetch_list if s and s.strip()]
|
|
@@ -201,6 +206,10 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
201
206
|
self.destructive_keywords = destructive_keywords_from_config(c)
|
|
202
207
|
special.set_destructive_keywords(self.destructive_keywords)
|
|
203
208
|
|
|
209
|
+
def _invalidate_prompt_session(self) -> None:
|
|
210
|
+
if self.prompt_session:
|
|
211
|
+
self.prompt_session.app.invalidate()
|
|
212
|
+
|
|
204
213
|
def close(self) -> None:
|
|
205
214
|
try:
|
|
206
215
|
self.schema_prefetcher.stop()
|