mycli 2.29.6__tar.gz → 2.30.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.29.6 → mycli-2.30.0}/.github/workflows/ci.yml +4 -4
- {mycli-2.29.6 → mycli-2.30.0}/.github/workflows/publish.yml +4 -4
- {mycli-2.29.6/mycli.egg-info → mycli-2.30.0}/PKG-INFO +3 -3
- {mycli-2.29.6 → mycli-2.30.0}/changelog.md +28 -0
- mycli-2.30.0/doc/key_bindings.md +155 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/transforms.md +12 -11
- {mycli-2.29.6 → mycli-2.30.0}/docker/Dockerfile +2 -1
- mycli-2.30.0/docker/resources/dot_mycli_history.txt +26 -0
- {mycli-2.29.6 → mycli-2.30.0}/docker/resources/test_db-1.0.7.tar.gz +1 -1
- {mycli-2.29.6 → mycli-2.30.0}/mycli/cli_runner.py +30 -24
- {mycli-2.29.6 → mycli-2.30.0}/mycli/client.py +6 -9
- {mycli-2.29.6 → mycli-2.30.0}/mycli/config.py +18 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main.py +1 -2
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/list_dsn.py +11 -8
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/execution/sql_execute.py +1 -1
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/dsn_aliases.py +3 -38
- mycli-2.30.0/mycli/packages/utils/dsn_utils.py +37 -0
- {mycli-2.29.6 → mycli-2.30.0/mycli.egg-info}/PKG-INFO +3 -3
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/SOURCES.txt +2 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/requires.txt +2 -2
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/scm_file_list.json +2 -0
- mycli-2.30.0/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_cli_runner.py +8 -6
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_client_query.py +20 -19
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_dsn_aliases.py +8 -7
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_main.py +36 -34
- mycli-2.30.0/mycli_test/pytests/test_main_modes_list_dsn.py +291 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_sql_execute.py +16 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_tabular_output.py +1 -1
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/utils.py +3 -2
- {mycli-2.29.6 → mycli-2.30.0}/pyproject.toml +3 -3
- mycli-2.29.6/doc/key_bindings.md +0 -75
- mycli-2.29.6/mycli.egg-info/scm_version.json +0 -8
- mycli-2.29.6/mycli_test/pytests/test_main_modes_list_dsn.py +0 -112
- {mycli-2.29.6 → mycli-2.30.0}/.git-blame-ignore-revs +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/actions/lint/action.yml +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/actions/typecheck/action.yml +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/dependabot.yml +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/workflows/lint.yml +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.github/workflows/typecheck.yml +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/.gitignore +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/AGENTS.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/AUTHORS.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/CONTRIBUTING.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/LICENSE.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/MANIFEST.in +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/README.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/SPONSORS.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/cookbook.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/known_bugs.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/llm.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/main.gif +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/polars_describe.png +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/polars_group_by.png +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/polars_histogram.png +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/polars_pivot.png +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/doc/screenshots/tables.png +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/docker/resources/test_db_license.md +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/AUTHORS.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/SPONSORS.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/TIPS.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/app_state.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/client_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/client_connection.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/client_query.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/compat.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/constants.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/batch.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/checkup.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/completions.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/execute.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/main_modes/repl.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/myclirc +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/output.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/completion/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/completion/completion_engine.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/completion/completion_refresher.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/completion/schema_prefetcher.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/completion/sql_completer.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/credentials/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/credentials/password_sources.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/dataframes/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/dataframes/completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/dataframes/transform.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/execution/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/execution/background_runner.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/boundary/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/boundary/boundary_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/fzf/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/fzf/fzf.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/kubernetes/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/kubernetes/kubectl_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/macos/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/macos/macos_keychain.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/openssh/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/openssh/ssh_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/vault/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/integrations/vault/vault_credentials.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/fzf_history.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/history.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/key_bindings.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/multiline.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/style.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/toolbar.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/prompt_toolkit/utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/pygments/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/pygments/mycli_lexer.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/redirection/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/redirection/hybrid_redirection.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/db_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/delimiter_command.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/favorite_queries.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/io_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/llm.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/main.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/source.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/special_commands/special_command_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/sql_result/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/sql_result/sql_result.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/tabular_output/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/batch_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/cli_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/interactive_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/key_binding_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/keyring_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/path_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/sql_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/packages/utils/string_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/resources/completions/bash/mycli +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/resources/completions/fish/mycli.fish +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/resources/completions/zsh/_mycli +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli/types.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/auto_vertical.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/basic_commands.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/connection.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/crud_database.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/crud_table.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/db_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/environment.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/fixture_data/help_commands.txt +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/fixture_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/iocommands.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/named_queries.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/specials.feature +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/__init__.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/auto_vertical.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/basic_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/connection.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/crud_database.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/crud_table.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/iocommands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/named_queries.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/specials.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/steps/wrappers.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/features/wrappager.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/myclirc +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/mylogin.cnf +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/conftest.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_app_state.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_background_runner.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_bash_completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_batch_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_boundary_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_checkup.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_cli_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_clibuffer.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_client.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_client_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_client_connection.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_completer_use_switch.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_completion_engine.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_completion_refresher.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_config.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_favoritequeries.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_fish_completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_fzf.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_hybrid_redirection.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_key_bindings.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_keyring_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_kubectl_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_macos_keychain.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_main_modes_repl.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_naive_completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_output.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_password_sources.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_path_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_polars_completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_polars_transform.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_prompt_toolkit_fzf_history.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_prompt_toolkit_history.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_prompt_toolkit_style.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_prompt_toolkit_toolbar.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_prompt_toolkit_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_schema_prefetcher.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_smart_completion_public_schema_only.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_commands_init.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_db_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_io_commands.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_llm.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_main.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_source.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_special_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_sql_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_sqlcompleter.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_sqlresult.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_ssh_tunnel.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_string_utils.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_vault.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/mycli_test/pytests/test_zsh_completion.py +0 -0
- {mycli-2.29.6 → mycli-2.30.0}/setup.cfg +0 -0
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
steps:
|
|
25
25
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
26
|
|
|
27
|
-
- uses: astral-sh/setup-uv@
|
|
27
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
28
28
|
with:
|
|
29
29
|
version: "latest"
|
|
30
30
|
|
|
@@ -66,7 +66,7 @@ jobs:
|
|
|
66
66
|
steps:
|
|
67
67
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
68
68
|
|
|
69
|
-
- uses: astral-sh/setup-uv@
|
|
69
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
70
70
|
with:
|
|
71
71
|
version: "latest"
|
|
72
72
|
|
|
@@ -116,7 +116,7 @@ jobs:
|
|
|
116
116
|
steps:
|
|
117
117
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
118
118
|
|
|
119
|
-
- uses: astral-sh/setup-uv@
|
|
119
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
120
120
|
with:
|
|
121
121
|
version: 'latest'
|
|
122
122
|
|
|
@@ -220,7 +220,7 @@ jobs:
|
|
|
220
220
|
steps:
|
|
221
221
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
222
222
|
|
|
223
|
-
- uses: astral-sh/setup-uv@
|
|
223
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
224
224
|
with:
|
|
225
225
|
version: "latest"
|
|
226
226
|
|
|
@@ -51,7 +51,7 @@ jobs:
|
|
|
51
51
|
|
|
52
52
|
steps:
|
|
53
53
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
54
|
-
- uses: astral-sh/setup-uv@
|
|
54
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
55
55
|
with:
|
|
56
56
|
version: "latest"
|
|
57
57
|
|
|
@@ -93,7 +93,7 @@ jobs:
|
|
|
93
93
|
steps:
|
|
94
94
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
95
95
|
|
|
96
|
-
- uses: astral-sh/setup-uv@
|
|
96
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
97
97
|
with:
|
|
98
98
|
version: "latest"
|
|
99
99
|
|
|
@@ -144,7 +144,7 @@ jobs:
|
|
|
144
144
|
steps:
|
|
145
145
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
146
146
|
|
|
147
|
-
- uses: astral-sh/setup-uv@
|
|
147
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
148
148
|
with:
|
|
149
149
|
version: 'latest'
|
|
150
150
|
|
|
@@ -248,7 +248,7 @@ jobs:
|
|
|
248
248
|
|
|
249
249
|
steps:
|
|
250
250
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
251
|
-
- uses: astral-sh/setup-uv@
|
|
251
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
252
252
|
with:
|
|
253
253
|
version: "latest"
|
|
254
254
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.30.0
|
|
4
4
|
Summary: Rich MySQL terminal client with autocompletion, syntax highlighting, and dataframes
|
|
5
5
|
Author: Mycli Core Team
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -38,7 +38,7 @@ Requires-Dist: sqlparse~=0.6.0
|
|
|
38
38
|
Requires-Dist: sqlglot~=30.23.0
|
|
39
39
|
Requires-Dist: sqlglotc~=30.23.0
|
|
40
40
|
Requires-Dist: configobj~=5.0.9
|
|
41
|
-
Requires-Dist: cli_helpers[styles]~=2.15.
|
|
41
|
+
Requires-Dist: cli_helpers[styles]~=2.15.2
|
|
42
42
|
Requires-Dist: wcwidth~=0.9.2
|
|
43
43
|
Requires-Dist: pyperclip~=1.11.0
|
|
44
44
|
Requires-Dist: pycryptodomex~=3.24.0
|
|
@@ -67,7 +67,7 @@ Requires-Dist: pytest-cov~=7.1.0; extra == "dev"
|
|
|
67
67
|
Requires-Dist: pytest-random-order~=1.2.0; extra == "dev"
|
|
68
68
|
Requires-Dist: tox~=4.64.9; extra == "dev"
|
|
69
69
|
Requires-Dist: pdbpp~=0.12.1; extra == "dev"
|
|
70
|
-
Requires-Dist: ruff~=0.
|
|
70
|
+
Requires-Dist: ruff~=0.17.0; extra == "dev"
|
|
71
71
|
Dynamic: license-file
|
|
72
72
|
|
|
73
73
|
# mycli
|
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
v2.30.6 (2026/10/17)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
--------
|
|
6
|
+
* Populate history file in Docker with examples.
|
|
7
|
+
* Faster dynamic completions via faster `--list-dsn`.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Bug Fixes
|
|
11
|
+
--------
|
|
12
|
+
* Show the username in the Docker prompt.
|
|
13
|
+
* Show the username in the prompt if a default user was used.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Documentation
|
|
17
|
+
--------
|
|
18
|
+
* Dataframe transforms are no longer experimental.
|
|
19
|
+
* Update key bindings doc.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Internal
|
|
23
|
+
--------
|
|
24
|
+
* Update `cli_helpers` to v2.15.2, improving vertical output.
|
|
25
|
+
* Update `ruff` to v0.17.0.
|
|
26
|
+
* Complete moving `MyCli` to `client.py`.
|
|
27
|
+
|
|
28
|
+
|
|
1
29
|
v2.29.6 (2026/10/15)
|
|
2
30
|
==============
|
|
3
31
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Key Bindings
|
|
2
|
+
|
|
3
|
+
There are two major editing modes available: Emacs mode and Vi mode. The mode
|
|
4
|
+
can be changed via the `key_bindings` property in the config file (`~/.myclirc`) or
|
|
5
|
+
toggled via the <kbd>F4</kbd> key.
|
|
6
|
+
|
|
7
|
+
Emacs mode is the default. In Emacs mode you can type <kbd>Control-a</kbd> to go
|
|
8
|
+
to the beginning of a line, <kbd>Control-e</kbd> to go to the end of a line,
|
|
9
|
+
with many more options for navigation, similar to the defaults of the [readline](https://tiswww.case.edu/php/chet/readline/rluserman.html)
|
|
10
|
+
library.
|
|
11
|
+
|
|
12
|
+
When Vi mode is enabled you can use vi-style navigation, along with modal
|
|
13
|
+
editing features offered by Vim in the REPL, including text objects.
|
|
14
|
+
|
|
15
|
+
Most key bindings are simply inherited from [prompt-toolkit](https://python-prompt-toolkit.readthedocs.io/en/master/index.html).
|
|
16
|
+
|
|
17
|
+
Mycli also adds some custom keybindings which are summarized here along with
|
|
18
|
+
completion navigation.
|
|
19
|
+
|
|
20
|
+
## The Basics: Custom Bindings and Completion Navigation
|
|
21
|
+
|
|
22
|
+
### <kbd>F1</kbd>
|
|
23
|
+
|
|
24
|
+
Open the web documentation index in a browser tab.
|
|
25
|
+
|
|
26
|
+
### <kbd>F2</kbd>
|
|
27
|
+
|
|
28
|
+
Toggle smart completions.
|
|
29
|
+
|
|
30
|
+
### <kbd>F3</kbd>
|
|
31
|
+
|
|
32
|
+
Toggle multi-line mode.
|
|
33
|
+
|
|
34
|
+
### <kbd>F4</kbd>
|
|
35
|
+
|
|
36
|
+
Toggle Emacs/Vi editing modes.
|
|
37
|
+
|
|
38
|
+
### <kbd>Tab</kbd>
|
|
39
|
+
|
|
40
|
+
Summon completions + always advance in candidates (configurable).
|
|
41
|
+
|
|
42
|
+
### <kbd>Control-Space</kbd>
|
|
43
|
+
|
|
44
|
+
Summon completions or advance in candidates if present (configurable).
|
|
45
|
+
|
|
46
|
+
### <kbd>Enter</kbd>
|
|
47
|
+
|
|
48
|
+
Choose a completion candidate.
|
|
49
|
+
|
|
50
|
+
### <kbd>Esc</kbd>
|
|
51
|
+
|
|
52
|
+
Cancel the completions popup.
|
|
53
|
+
|
|
54
|
+
### <kbd>Control-g</kbd>
|
|
55
|
+
|
|
56
|
+
Cancel the completions popup.
|
|
57
|
+
|
|
58
|
+
### <kbd>Control-r</kbd>
|
|
59
|
+
|
|
60
|
+
Search the query history with [fzf](https://github.com/junegunn/fzf) if available, or use
|
|
61
|
+
[prompt-toolkit](https://python-prompt-toolkit.readthedocs.io/en/master/index.html)'s
|
|
62
|
+
`reverse-i-search` as a fallback (configurable).
|
|
63
|
+
|
|
64
|
+
### <kbd>Alt-Enter</kbd>
|
|
65
|
+
|
|
66
|
+
Introduce a line break in multi-line mode, or dispatch the current query in
|
|
67
|
+
single-line mode.
|
|
68
|
+
|
|
69
|
+
The keyboard combination <kbd>Alt-Enter</kbd> usually sends the sequence
|
|
70
|
+
`ESC`,`Enter` on the wire, and it may also be possible to use the <kbd>ESC</kbd>,<kbd>Enter</kbd>
|
|
71
|
+
key sequence.
|
|
72
|
+
|
|
73
|
+
### Arrow keys
|
|
74
|
+
|
|
75
|
+
Completion navigation (when popup is present).
|
|
76
|
+
|
|
77
|
+
### Right-arrow
|
|
78
|
+
|
|
79
|
+
Accept full-line history suggestion (when suggestion is visible).
|
|
80
|
+
|
|
81
|
+
### <kbd>Control-d</kbd>
|
|
82
|
+
|
|
83
|
+
Exit the REPL (configurable).
|
|
84
|
+
|
|
85
|
+
## In Emacs Mode Only
|
|
86
|
+
|
|
87
|
+
A comma indicates a sequence of multiple keystrokes.
|
|
88
|
+
|
|
89
|
+
### <kbd>Control-x</kbd>, <kbd>p</kbd>
|
|
90
|
+
|
|
91
|
+
Prettify and indent the current statement, usually into multiple lines.
|
|
92
|
+
|
|
93
|
+
Only works for buffers containing single SQL statements.
|
|
94
|
+
|
|
95
|
+
### <kbd>Control-x</kbd>, <kbd>u</kbd>
|
|
96
|
+
|
|
97
|
+
Unprettify and dedent the current statement, usually into one line.
|
|
98
|
+
|
|
99
|
+
Only works for buffers containing single SQL statements.
|
|
100
|
+
|
|
101
|
+
### <kbd>Control-o</kbd>, <kbd>d</kbd>
|
|
102
|
+
|
|
103
|
+
Insert the current literal date at the cursor, as defined by `NOW()` on the
|
|
104
|
+
server.
|
|
105
|
+
|
|
106
|
+
### <kbd>Control-o</kbd>, <kbd>t</kbd>
|
|
107
|
+
|
|
108
|
+
Insert the current literal datetime at the cursor, as defined by `NOW()` on
|
|
109
|
+
the server.
|
|
110
|
+
|
|
111
|
+
### <kbd>Control-o</kbd>, <kbd>Control-d</kbd>
|
|
112
|
+
|
|
113
|
+
Insert the _quoted_ current literal date at the cursor, as defined by `NOW()`
|
|
114
|
+
on the server.
|
|
115
|
+
|
|
116
|
+
### <kbd>Control-o</kbd>, <kbd>Control-t</kbd>
|
|
117
|
+
|
|
118
|
+
Insert the _quoted_ current literal datetime at the cursor, as defined by
|
|
119
|
+
`NOW()` on the server.
|
|
120
|
+
|
|
121
|
+
### <kbd>Control-o</kbd>, <kbd>u</kbd>
|
|
122
|
+
|
|
123
|
+
Insert the current literal Unix timestamp at the cursor, in seconds, as defined
|
|
124
|
+
by `time.time()` on the client.
|
|
125
|
+
|
|
126
|
+
### <kbd>Control-o</kbd>, <kbd>Control-u</kbd>
|
|
127
|
+
|
|
128
|
+
Insert the current literal Unix timestamp at the cursor, in microseconds, as
|
|
129
|
+
defined by `time.time()` on the client.
|
|
130
|
+
|
|
131
|
+
### <kbd>Alt-r</kbd>
|
|
132
|
+
|
|
133
|
+
Search query history with [fzf](https://github.com/junegunn/fzf) even if `~/.myclirc`
|
|
134
|
+
is configured not to use fuzzy search on the default key <kbd>Control-r</kbd>.
|
|
135
|
+
|
|
136
|
+
## Advanced
|
|
137
|
+
|
|
138
|
+
Since <kbd>Alt</kbd> key combinations usually work by sending a series of characters
|
|
139
|
+
on the wire, there is sometimes an ambiguity with regard to which characters were
|
|
140
|
+
physically typed. A timeout heuristic is used to resolve this.
|
|
141
|
+
|
|
142
|
+
Advanced users, and those on slow connections, may want to consult the following
|
|
143
|
+
settings in `~/.myclirc` to adjust the timeout heuristic. The threshold is separate
|
|
144
|
+
for Emacs and Vi edit modes:
|
|
145
|
+
|
|
146
|
+
```ini
|
|
147
|
+
[keys]
|
|
148
|
+
# How long to wait for an Escape key sequence in vi mode.
|
|
149
|
+
# 0.5 seconds is the prompt_toolkit default, but vi users may find that too long.
|
|
150
|
+
# Shorter values mean that "Escape" alone is recognized more quickly.
|
|
151
|
+
vi_ttimeoutlen = 0.1
|
|
152
|
+
|
|
153
|
+
# How long to wait for an Escape key sequence in Emacs mode.
|
|
154
|
+
emacs_ttimeoutlen = 0.5
|
|
155
|
+
```
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Installing
|
|
4
4
|
|
|
5
|
+
### Homebrew
|
|
6
|
+
|
|
7
|
+
No additional steps needed; Homebrew already comes with dataframe support.
|
|
8
|
+
|
|
9
|
+
### pip
|
|
10
|
+
|
|
5
11
|
Install mycli with dataframe support using:
|
|
6
12
|
|
|
7
13
|
```bash
|
|
@@ -14,18 +20,13 @@ or install these libraries separately:
|
|
|
14
20
|
* [`altair`](https://pypi.org/project/altair/)
|
|
15
21
|
* [`vl-convert-python`](https://pypi.org/project/vl-convert-python/)
|
|
16
22
|
|
|
17
|
-
##
|
|
18
|
-
|
|
19
|
-
Dataframe transforms and plots are new and experimental. The interface and
|
|
20
|
-
functionality may still change.
|
|
21
|
-
|
|
22
|
-
Here are some known limitations:
|
|
23
|
-
|
|
24
|
-
* composing multiple transform operations is not supported
|
|
25
|
-
* results from `UNION`s may be unable to be transformed
|
|
23
|
+
## Limitations
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
* composing multiple transform operations is not supported, though there is no
|
|
26
|
+
limitation on the code within one operation
|
|
27
|
+
* results from `UNION`s may not be able to be transformed
|
|
28
|
+
* the post-processing model means that the entire SQL result must be transferred
|
|
29
|
+
from the server and loaded into local memory
|
|
29
30
|
|
|
30
31
|
## Transforming
|
|
31
32
|
|
|
@@ -13,6 +13,7 @@ RUN apt-get update -qq && \
|
|
|
13
13
|
rm -rf /var/lib/{apt,dpkg,cache,log}/
|
|
14
14
|
|
|
15
15
|
COPY . /app
|
|
16
|
+
COPY docker/resources/dot_mycli_history.txt /root/.mycli-history
|
|
16
17
|
|
|
17
18
|
RUN service mariadb restart && \
|
|
18
19
|
cd /app/docker/resources && \
|
|
@@ -24,4 +25,4 @@ RUN service mariadb restart && \
|
|
|
24
25
|
|
|
25
26
|
RUN cd /app && pip install --root-user-action=ignore -e .[llm,dataframe]
|
|
26
27
|
|
|
27
|
-
CMD ["sh", "-c", "service mariadb start && mycli --database employees"]
|
|
28
|
+
CMD ["sh", "-c", "service mariadb start && mycli --user root --database employees"]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# 2026-10-08 07:35:11.242332
|
|
2
|
+
+SELECT MAX(salary) AS current_salary FROM salaries GROUP BY emp_no .| df['current_salary'].plot.hist();
|
|
3
|
+
|
|
4
|
+
# 2026-10-09 07:35:11.242332
|
|
5
|
+
+SELECT * FROM salaries .| df.group_by('emp_no').len(name='num_raises').with_columns(pl.col('num_raises') - 1);
|
|
6
|
+
|
|
7
|
+
# 2026-10-10 07:35:11.242332
|
|
8
|
+
+SELECT * FROM salaries LIMIT 10000 .| df.describe();
|
|
9
|
+
|
|
10
|
+
# 2026-10-11 07:35:11.242332
|
|
11
|
+
+SELECT employees.first_name, employees.last_name, MAX(salary) AS current_salary FROM salaries JOIN employees ON salaries.emp_no = employees.emp_no GROUP BY salaries.emp_no;
|
|
12
|
+
|
|
13
|
+
# 2026-10-12 07:35:11.242332
|
|
14
|
+
+SELECT salaries.emp_no, MAX(salary) AS current_salary FROM salaries JOIN employees ON salaries.emp_no = employees.emp_no GROUP BY salaries.emp_no;
|
|
15
|
+
|
|
16
|
+
# 2026-10-13 07:35:11.242332
|
|
17
|
+
+DESCRIBE employees;
|
|
18
|
+
|
|
19
|
+
# 2026-10-14 07:35:11.242332
|
|
20
|
+
+SELECT emp_no, MAX(salary) AS current_salary FROM salaries GROUP BY emp_no;
|
|
21
|
+
|
|
22
|
+
# 2026-10-15 07:35:11.242332
|
|
23
|
+
+SELECT emp_no, salary FROM salaries LIMIT 1000;
|
|
24
|
+
|
|
25
|
+
# 2026-10-16 07:35:11.242332
|
|
26
|
+
+DESCRIBE salaries;
|
|
@@ -14,7 +14,7 @@ __lazy_modules__ = [
|
|
|
14
14
|
'mycli.main_modes.list_dsn',
|
|
15
15
|
'mycli.packages.credentials.password_sources',
|
|
16
16
|
'mycli.packages.integrations.vault.vault_credentials',
|
|
17
|
-
'mycli.packages.
|
|
17
|
+
'mycli.packages.utils.dsn_utils',
|
|
18
18
|
'mycli.packages.utils.cli_utils',
|
|
19
19
|
]
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ from mycli.main_modes.batch import main_batch_from_stdin, main_batch_with_progre
|
|
|
32
32
|
from mycli.main_modes.checkup import main_checkup
|
|
33
33
|
from mycli.main_modes.completions import main_completions
|
|
34
34
|
from mycli.main_modes.execute import main_execute_from_cli
|
|
35
|
-
from mycli.main_modes.list_dsn import main_list_dsn
|
|
35
|
+
from mycli.main_modes.list_dsn import load_list_dsn_config, main_list_dsn
|
|
36
36
|
from mycli.packages.credentials.password_sources import PasswordCandidates
|
|
37
37
|
from mycli.packages.integrations.vault.vault_credentials import (
|
|
38
38
|
DEFAULT_VAULT_EXECUTABLE,
|
|
@@ -41,8 +41,8 @@ from mycli.packages.integrations.vault.vault_credentials import (
|
|
|
41
41
|
VaultError,
|
|
42
42
|
get_field_from_vault,
|
|
43
43
|
)
|
|
44
|
-
from mycli.packages.special_commands.dsn_aliases import INVALID_DSN_ALIAS_ERROR, is_valid_dsn_alias
|
|
45
44
|
from mycli.packages.utils.cli_utils import is_valid_connection_scheme
|
|
45
|
+
from mycli.packages.utils.dsn_utils import INVALID_DSN_ALIAS_ERROR, is_valid_dsn_alias
|
|
46
46
|
|
|
47
47
|
if TYPE_CHECKING:
|
|
48
48
|
from mycli.main import CliArgs
|
|
@@ -122,7 +122,7 @@ def expand_dsn_alias_env_vars(
|
|
|
122
122
|
)
|
|
123
123
|
|
|
124
124
|
|
|
125
|
-
def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> None:
|
|
125
|
+
def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory | None = None) -> None:
|
|
126
126
|
from mycli import main as main_module
|
|
127
127
|
|
|
128
128
|
if cli_args.completions:
|
|
@@ -131,6 +131,32 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
131
131
|
|
|
132
132
|
cli_verbosity = main_module.preprocess_cli_args(cli_args, is_valid_connection_scheme)
|
|
133
133
|
|
|
134
|
+
if not cli_args.checkup:
|
|
135
|
+
if cli_args.csv and cli_args.format not in [None, 'csv']:
|
|
136
|
+
click.secho("Conflicting --csv and --format arguments.", err=True, fg="red")
|
|
137
|
+
sys.exit(1)
|
|
138
|
+
|
|
139
|
+
if cli_args.table and cli_args.format not in [None, 'table']:
|
|
140
|
+
click.secho("Conflicting --table and --format arguments.", err=True, fg="red")
|
|
141
|
+
sys.exit(1)
|
|
142
|
+
|
|
143
|
+
if not cli_args.format:
|
|
144
|
+
cli_args.format = 'default'
|
|
145
|
+
if cli_args.csv:
|
|
146
|
+
cli_args.format = 'csv'
|
|
147
|
+
if cli_args.table:
|
|
148
|
+
cli_args.format = 'table'
|
|
149
|
+
|
|
150
|
+
if cli_args.list_dsn:
|
|
151
|
+
config = load_list_dsn_config(cli_args.myclirc)
|
|
152
|
+
verbosity = cli_verbosity or (-1 if config['main'].as_bool('less_chatty') else 0)
|
|
153
|
+
sys.exit(main_list_dsn(config, verbosity))
|
|
154
|
+
|
|
155
|
+
if client_factory is None:
|
|
156
|
+
import mycli.client as mycli_client
|
|
157
|
+
|
|
158
|
+
client_factory = mycli_client.MyCli
|
|
159
|
+
|
|
134
160
|
mycli = client_factory(
|
|
135
161
|
prompt=cli_args.prompt,
|
|
136
162
|
toolbar_format=cli_args.toolbar,
|
|
@@ -147,26 +173,6 @@ def run_from_cli_args(cli_args: 'CliArgs', client_factory: ClientFactory) -> Non
|
|
|
147
173
|
main_checkup(mycli)
|
|
148
174
|
sys.exit(0)
|
|
149
175
|
|
|
150
|
-
if cli_args.csv and cli_args.format not in [None, 'csv']:
|
|
151
|
-
click.secho("Conflicting --csv and --format arguments.", err=True, fg="red")
|
|
152
|
-
sys.exit(1)
|
|
153
|
-
|
|
154
|
-
if cli_args.table and cli_args.format not in [None, 'table']:
|
|
155
|
-
click.secho("Conflicting --table and --format arguments.", err=True, fg="red")
|
|
156
|
-
sys.exit(1)
|
|
157
|
-
|
|
158
|
-
if not cli_args.format:
|
|
159
|
-
cli_args.format = 'default'
|
|
160
|
-
|
|
161
|
-
if cli_args.csv:
|
|
162
|
-
cli_args.format = 'csv'
|
|
163
|
-
|
|
164
|
-
if cli_args.table:
|
|
165
|
-
cli_args.format = 'table'
|
|
166
|
-
|
|
167
|
-
if cli_args.list_dsn:
|
|
168
|
-
sys.exit(main_list_dsn(mycli))
|
|
169
|
-
|
|
170
176
|
dsn_uri = None
|
|
171
177
|
dsn_password: str | None = None
|
|
172
178
|
database: str | None = ''
|
|
@@ -24,10 +24,13 @@ from mycli.client_commands import ClientCommandsMixin, get_config_property_names
|
|
|
24
24
|
from mycli.client_connection import ClientConnectionMixin
|
|
25
25
|
from mycli.client_query import ClientQueryMixin
|
|
26
26
|
from mycli.config import (
|
|
27
|
+
SYSTEM_CONFIG_FILES,
|
|
27
28
|
get_mylogin_cnf_path,
|
|
29
|
+
get_xdg_config_file,
|
|
28
30
|
open_mylogin_cnf,
|
|
29
31
|
read_config_file,
|
|
30
32
|
read_config_files,
|
|
33
|
+
resolve_user_config_path,
|
|
31
34
|
write_default_config,
|
|
32
35
|
)
|
|
33
36
|
from mycli.constants import DEFAULT_PROMPT
|
|
@@ -61,10 +64,8 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
61
64
|
|
|
62
65
|
# check XDG_CONFIG_HOME exists and not an empty string
|
|
63
66
|
xdg_config_home = os.environ.get("XDG_CONFIG_HOME", "~/.config")
|
|
64
|
-
xdg_config_file =
|
|
65
|
-
system_config_files: list[str | IO[str]] =
|
|
66
|
-
"/etc/myclirc",
|
|
67
|
-
]
|
|
67
|
+
xdg_config_file = get_xdg_config_file()
|
|
68
|
+
system_config_files: list[str | IO[str]] = SYSTEM_CONFIG_FILES
|
|
68
69
|
|
|
69
70
|
def __init__(
|
|
70
71
|
self,
|
|
@@ -92,11 +93,7 @@ class MyCli(AppStateMixin, OutputMixin, ClientCommandsMixin, ClientConnectionMix
|
|
|
92
93
|
self.sandbox_mode: bool = False
|
|
93
94
|
self.checkpoint: IO | None = None
|
|
94
95
|
|
|
95
|
-
|
|
96
|
-
if os.path.exists(self.xdg_config_file):
|
|
97
|
-
myclirc = self.xdg_config_file
|
|
98
|
-
else:
|
|
99
|
-
myclirc = '~/.myclirc'
|
|
96
|
+
myclirc = resolve_user_config_path(myclirc, xdg_config_file=self.xdg_config_file)
|
|
100
97
|
self.myclirc_path = os.path.abspath(os.path.expanduser(myclirc))
|
|
101
98
|
|
|
102
99
|
# Load config.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
__lazy_modules__ = ['Cryptodome.Cipher']
|
|
2
|
+
|
|
1
3
|
from copy import copy
|
|
2
4
|
from importlib import resources
|
|
3
5
|
from io import BytesIO, TextIOWrapper
|
|
@@ -12,6 +14,22 @@ from configobj import ConfigObj, ConfigObjError
|
|
|
12
14
|
from Cryptodome.Cipher import AES
|
|
13
15
|
|
|
14
16
|
logger = logging.getLogger(__name__)
|
|
17
|
+
SYSTEM_CONFIG_FILES: list[str | IO[str]] = ['/etc/myclirc']
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_xdg_config_file() -> str:
|
|
21
|
+
return os.path.join(os.path.expanduser(os.environ.get('XDG_CONFIG_HOME', '~/.config')), 'mycli', 'myclirc')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def resolve_user_config_path(myclirc: str | None, *, xdg_config_file: str | None = None) -> str:
|
|
25
|
+
if myclirc is not None:
|
|
26
|
+
return myclirc
|
|
27
|
+
xdg_config_file = get_xdg_config_file() if xdg_config_file is None else xdg_config_file
|
|
28
|
+
return xdg_config_file if os.path.exists(xdg_config_file) else '~/.myclirc'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def read_user_config(myclirc: str | None) -> ConfigObj:
|
|
32
|
+
return read_config_files(SYSTEM_CONFIG_FILES + [resolve_user_config_path(myclirc)])
|
|
15
33
|
|
|
16
34
|
|
|
17
35
|
class SQLValuePreservingConfigObj(ConfigObj):
|
|
@@ -23,7 +23,6 @@ import clickdc
|
|
|
23
23
|
|
|
24
24
|
import mycli as mycli_package
|
|
25
25
|
from mycli.cli_runner import run_from_cli_args
|
|
26
|
-
from mycli.client import MyCli
|
|
27
26
|
from mycli.constants import (
|
|
28
27
|
DEFAULT_PROMPT,
|
|
29
28
|
EMPTY_PASSWORD_FLAG_SENTINEL,
|
|
@@ -482,7 +481,7 @@ def click_entrypoint(
|
|
|
482
481
|
|
|
483
482
|
"""
|
|
484
483
|
|
|
485
|
-
run_from_cli_args(cli_args, client_factory=
|
|
484
|
+
run_from_cli_args(cli_args, client_factory=None)
|
|
486
485
|
|
|
487
486
|
|
|
488
487
|
def main() -> int | None:
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import TYPE_CHECKING
|
|
4
|
-
|
|
5
3
|
import click
|
|
4
|
+
from configobj import ConfigObj
|
|
5
|
+
|
|
6
|
+
from mycli.config import read_user_config
|
|
7
|
+
from mycli.packages.utils.dsn_utils import is_valid_dsn_alias, merge_shared_dsns
|
|
6
8
|
|
|
7
|
-
from mycli.packages.special_commands.dsn_aliases import is_valid_dsn_alias
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
def load_list_dsn_config(myclirc: str | None) -> ConfigObj:
|
|
11
|
+
config = read_user_config(myclirc)
|
|
12
|
+
merge_shared_dsns(config, config['main'].get('shared_dsns_file'))
|
|
13
|
+
return config
|
|
11
14
|
|
|
12
15
|
|
|
13
|
-
def main_list_dsn(
|
|
16
|
+
def main_list_dsn(config: ConfigObj, verbosity: int) -> int:
|
|
14
17
|
try:
|
|
15
|
-
alias_dsn =
|
|
18
|
+
alias_dsn = config['alias_dsn']
|
|
16
19
|
except KeyError:
|
|
17
20
|
click.secho('Invalid DSNs found in the config file. Please check the "[alias_dsn]" section in myclirc.', err=True, fg='red')
|
|
18
21
|
return 1
|
|
@@ -22,7 +25,7 @@ def main_list_dsn(mycli: 'MyCli') -> int:
|
|
|
22
25
|
for alias, value in alias_dsn.items():
|
|
23
26
|
if not is_valid_dsn_alias(alias):
|
|
24
27
|
continue
|
|
25
|
-
if
|
|
28
|
+
if verbosity >= 1:
|
|
26
29
|
click.secho(f'{alias} : {value}')
|
|
27
30
|
else:
|
|
28
31
|
click.secho(alias)
|
|
@@ -320,7 +320,7 @@ class SQLExecute:
|
|
|
320
320
|
# Update them after the connection is made to ensure that it was a
|
|
321
321
|
# successful connection.
|
|
322
322
|
self.dbname = db
|
|
323
|
-
self.user = user
|
|
323
|
+
self.user = user or (conn.user.decode(conn.encoding) if isinstance(conn.user, bytes) else conn.user)
|
|
324
324
|
self.password = password
|
|
325
325
|
self.host = host
|
|
326
326
|
self.port = port
|
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import logging
|
|
4
3
|
import os
|
|
5
4
|
from typing import TYPE_CHECKING, Any
|
|
6
5
|
from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
|
7
6
|
|
|
8
|
-
from mycli.config import
|
|
7
|
+
from mycli.config import read_config_file, str_to_bool
|
|
9
8
|
from mycli.constants import DEFAULT_CHARSET, DEFAULT_PROMPT, KNOWN_DSN_QUERY_PARAMS
|
|
10
|
-
|
|
11
|
-
logger = logging.getLogger(__name__)
|
|
9
|
+
from mycli.packages.utils.dsn_utils import INVALID_DSN_ALIAS_ERROR, is_valid_dsn_alias, merge_shared_dsns
|
|
12
10
|
|
|
13
11
|
if TYPE_CHECKING:
|
|
14
12
|
from mycli.client import MyCli
|
|
15
13
|
|
|
16
14
|
DSN_SUBCOMMANDS = {'help', 'list', 'show', 'save', 'edit', 'delete'}
|
|
17
|
-
INVALID_DSN_ALIAS_ERROR = 'Error: DSN aliases cannot start with a dash.'
|
|
18
15
|
MISSING = object()
|
|
19
16
|
|
|
20
17
|
SSL_QUERY_PARAMS = {
|
|
@@ -29,10 +26,6 @@ SSL_QUERY_PARAMS = {
|
|
|
29
26
|
}
|
|
30
27
|
|
|
31
28
|
|
|
32
|
-
def is_valid_dsn_alias(alias: str) -> bool:
|
|
33
|
-
return not alias.startswith('-')
|
|
34
|
-
|
|
35
|
-
|
|
36
29
|
def _config_bool(value: Any) -> bool:
|
|
37
30
|
try:
|
|
38
31
|
return str_to_bool(value)
|
|
@@ -108,35 +101,7 @@ Examples:
|
|
|
108
101
|
shared_dsns_file: str | None = None,
|
|
109
102
|
) -> DsnAliases:
|
|
110
103
|
aliases = cls(config, mycli, config_file)
|
|
111
|
-
|
|
112
|
-
return aliases
|
|
113
|
-
|
|
114
|
-
shared_dsns_file = os.path.expanduser(shared_dsns_file)
|
|
115
|
-
if not os.path.isabs(shared_dsns_file):
|
|
116
|
-
log(
|
|
117
|
-
logger,
|
|
118
|
-
logging.WARNING,
|
|
119
|
-
f"Shared DSNs file path must be absolute: '{shared_dsns_file}'.",
|
|
120
|
-
)
|
|
121
|
-
return aliases
|
|
122
|
-
|
|
123
|
-
if not os.path.isfile(shared_dsns_file):
|
|
124
|
-
log(
|
|
125
|
-
logger,
|
|
126
|
-
logging.WARNING,
|
|
127
|
-
f"Unable to read shared DSNs file '{shared_dsns_file}'.",
|
|
128
|
-
)
|
|
129
|
-
return aliases
|
|
130
|
-
|
|
131
|
-
shared_config = read_config_file(shared_dsns_file)
|
|
132
|
-
if shared_config is None:
|
|
133
|
-
return aliases
|
|
134
|
-
|
|
135
|
-
configured_aliases = config.get(cls.section_name, {})
|
|
136
|
-
shared_aliases = shared_config.get(cls.section_name, {})
|
|
137
|
-
config[cls.section_name] = {}
|
|
138
|
-
config[cls.section_name].update(shared_aliases)
|
|
139
|
-
config[cls.section_name].update(configured_aliases)
|
|
104
|
+
merge_shared_dsns(config, shared_dsns_file)
|
|
140
105
|
return aliases
|
|
141
106
|
|
|
142
107
|
def _config_for_write(self) -> Any:
|