mycli 2.28.1__tar.gz → 2.29.1__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.28.1 → mycli-2.29.1}/.github/workflows/ci.yml +1 -1
- {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/publish.yml +1 -1
- {mycli-2.28.1/mycli.egg-info → mycli-2.29.1}/PKG-INFO +11 -9
- {mycli-2.28.1 → mycli-2.29.1}/changelog.md +58 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/known_bugs.md +5 -0
- {mycli-2.28.1 → mycli-2.29.1}/docker/resources/test_db-1.0.7.tar.gz +1 -1
- {mycli-2.28.1 → mycli-2.29.1}/mycli/config.py +72 -10
- {mycli-2.28.1 → mycli-2.29.1}/mycli/constants.py +1 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main.py +20 -15
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/repl.py +112 -47
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/background_runner.py +52 -6
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/favorite_queries.py +3 -2
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/io_commands.py +70 -35
- {mycli-2.28.1 → mycli-2.29.1/mycli.egg-info}/PKG-INFO +11 -9
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/requires.txt +10 -8
- mycli-2.29.1/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_background_runner.py +352 -9
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_config.py +127 -4
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_favoritequeries.py +162 -4
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main.py +1 -1
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_repl.py +581 -4
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_io_commands.py +143 -6
- {mycli-2.28.1 → mycli-2.29.1}/pyproject.toml +16 -10
- mycli-2.28.1/mycli.egg-info/scm_version.json +0 -8
- {mycli-2.28.1 → mycli-2.29.1}/.git-blame-ignore-revs +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/dependabot.yml +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/lint.yml +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/typecheck.yml +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/.gitignore +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/AGENTS.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/AUTHORS.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/CONTRIBUTING.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/LICENSE.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/MANIFEST.in +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/README.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/SPONSORS.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/cookbook.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/key_bindings.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/llm.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/main.gif +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_describe.png +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_group_by.png +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_histogram.png +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_pivot.png +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/tables.png +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/doc/transforms.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/docker/Dockerfile +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/docker/resources/test_db_license.md +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/AUTHORS.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/SPONSORS.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/TIPS.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/app_state.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/cli_runner.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/client.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/client_commands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/client_connection.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/client_query.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/compat.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/batch.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/checkup.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/completions.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/execute.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/list_dsn.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/myclirc +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/output.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/completion_engine.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/completion_refresher.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/schema_prefetcher.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/sql_completer.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/credentials/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/credentials/password_sources.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/transform.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/sql_execute.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/boundary/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/boundary/boundary_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/fzf/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/fzf/fzf.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/kubernetes/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/kubernetes/kubectl_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/macos/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/macos/macos_keychain.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/openssh/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/openssh/ssh_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/vault/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/vault/vault_credentials.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/fzf_history.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/history.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/key_bindings.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/multiline.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/style.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/toolbar.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/pygments/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/pygments/mycli_lexer.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/redirection/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/redirection/hybrid_redirection.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/db_commands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/delimiter_command.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/dsn_aliases.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/llm.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/main.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/source.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/special_command_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/sql_result/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/sql_result/sql_result.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/tabular_output/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/batch_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/cli_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/interactive_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/key_binding_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/keyring_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/path_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/sql_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/string_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/bash/mycli +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/fish/mycli.fish +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/zsh/_mycli +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli/types.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/SOURCES.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/scm_file_list.json +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/auto_vertical.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/basic_commands.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/connection.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/crud_database.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/crud_table.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/db_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/environment.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/fixture_data/help_commands.txt +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/fixture_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/iocommands.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/named_queries.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/specials.feature +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/__init__.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/auto_vertical.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/basic_commands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/connection.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/crud_database.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/crud_table.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/iocommands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/named_queries.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/specials.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/wrappers.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/wrappager.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/myclirc +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/mylogin.cnf +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/conftest.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_app_state.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_bash_completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_batch_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_boundary_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_checkup.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_cli_runner.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_cli_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_clibuffer.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_commands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_connection.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_query.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completer_use_switch.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completion_engine.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completion_refresher.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_dsn_aliases.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_fish_completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_fzf.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_hybrid_redirection.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_key_bindings.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_keyring_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_kubectl_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_macos_keychain.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_list_dsn.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_naive_completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_output.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_password_sources.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_path_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_polars_completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_polars_transform.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_fzf_history.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_history.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_style.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_toolbar.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_schema_prefetcher.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_smart_completion_public_schema_only.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_commands_init.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_db_commands.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_llm.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_main.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_source.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sql_execute.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sql_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sqlcompleter.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sqlresult.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_ssh_tunnel.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_string_utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_tabular_output.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_vault.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_zsh_completion.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/mycli_test/utils.py +0 -0
- {mycli-2.28.1 → mycli-2.29.1}/setup.cfg +0 -0
|
@@ -130,7 +130,7 @@ jobs:
|
|
|
130
130
|
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
131
131
|
|
|
132
132
|
- name: Set up MySQL
|
|
133
|
-
uses: shogo82148/actions-setup-mysql@
|
|
133
|
+
uses: shogo82148/actions-setup-mysql@1d4ebc60ba1227dd13fc7e6ba845bd3997928d75 # v1.54.2
|
|
134
134
|
with:
|
|
135
135
|
mysql-version: '9.7'
|
|
136
136
|
root-password: root
|
|
@@ -147,7 +147,7 @@ jobs:
|
|
|
147
147
|
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
148
148
|
|
|
149
149
|
- name: Set up MySQL
|
|
150
|
-
uses: shogo82148/actions-setup-mysql@
|
|
150
|
+
uses: shogo82148/actions-setup-mysql@1d4ebc60ba1227dd13fc7e6ba845bd3997928d75 # v1.54.2
|
|
151
151
|
with:
|
|
152
152
|
mysql-version: '9.7'
|
|
153
153
|
root-password: root
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.29.1
|
|
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
|
|
@@ -32,27 +32,28 @@ Requires-Dist: click~=8.5.0
|
|
|
32
32
|
Requires-Dist: clickdc~=0.1.1
|
|
33
33
|
Requires-Dist: cryptography~=50.0.1
|
|
34
34
|
Requires-Dist: Pygments~=2.21.0
|
|
35
|
-
Requires-Dist: prompt_toolkit
|
|
35
|
+
Requires-Dist: prompt_toolkit~=3.0.53
|
|
36
36
|
Requires-Dist: PyMySQL~=1.2.3
|
|
37
37
|
Requires-Dist: sqlparse~=0.6.0
|
|
38
38
|
Requires-Dist: sqlglot~=30.17.0
|
|
39
39
|
Requires-Dist: sqlglotc~=30.17.0
|
|
40
40
|
Requires-Dist: configobj~=5.0.9
|
|
41
41
|
Requires-Dist: cli_helpers[styles]~=2.15.1
|
|
42
|
-
Requires-Dist: wcwidth~=0.
|
|
42
|
+
Requires-Dist: wcwidth~=0.9.1
|
|
43
43
|
Requires-Dist: pyperclip~=1.11.0
|
|
44
44
|
Requires-Dist: pycryptodomex~=3.23.0
|
|
45
|
-
Requires-Dist: rapidfuzz~=3.14.
|
|
45
|
+
Requires-Dist: rapidfuzz~=3.14.6
|
|
46
46
|
Requires-Dist: keyring~=25.7.0
|
|
47
47
|
Requires-Dist: jinja2~=3.1.6
|
|
48
|
-
Requires-Dist: yaspin~=3.
|
|
48
|
+
Requires-Dist: yaspin~=3.5.1
|
|
49
49
|
Provides-Extra: llm
|
|
50
|
-
Requires-Dist: llm~=0.
|
|
51
|
-
Requires-Dist: setuptools==
|
|
50
|
+
Requires-Dist: llm~=0.36; extra == "llm"
|
|
51
|
+
Requires-Dist: setuptools==84.*; extra == "llm"
|
|
52
52
|
Requires-Dist: pip~=26.2.1; extra == "llm"
|
|
53
|
+
Requires-Dist: httpx2~=2.13.1; extra == "llm"
|
|
53
54
|
Provides-Extra: dataframe
|
|
54
|
-
Requires-Dist: polars~=
|
|
55
|
-
Requires-Dist: altair~=6.
|
|
55
|
+
Requires-Dist: polars~=2.0.0; extra == "dataframe"
|
|
56
|
+
Requires-Dist: altair~=6.3.0; extra == "dataframe"
|
|
56
57
|
Requires-Dist: vl-convert-python~=1.9.0; extra == "dataframe"
|
|
57
58
|
Provides-Extra: all
|
|
58
59
|
Requires-Dist: mycli[dataframe,llm]; extra == "all"
|
|
@@ -67,6 +68,7 @@ Requires-Dist: pytest-random-order~=1.2.0; extra == "dev"
|
|
|
67
68
|
Requires-Dist: tox~=4.35.0; extra == "dev"
|
|
68
69
|
Requires-Dist: pdbpp~=0.11.7; extra == "dev"
|
|
69
70
|
Requires-Dist: ruff~=0.16.5; extra == "dev"
|
|
71
|
+
Requires-Dist: virtualenv~=21.7.12; extra == "dev"
|
|
70
72
|
Dynamic: license-file
|
|
71
73
|
|
|
72
74
|
# mycli
|
|
@@ -1,3 +1,61 @@
|
|
|
1
|
+
v2.29.1 (2026/10/10)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Internal
|
|
5
|
+
--------
|
|
6
|
+
* Pin tox's ruff version to match `dev` dependency group.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
v2.29.0 (2026/10/10)
|
|
10
|
+
==============
|
|
11
|
+
|
|
12
|
+
Features
|
|
13
|
+
--------
|
|
14
|
+
* Add "redirecting" query state for shell-style redirects, `/once`, or `/pipe_once`.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Bug Fixes
|
|
18
|
+
--------
|
|
19
|
+
* Fix exceptions when interrupting "streaming" unbuffered queries.
|
|
20
|
+
* Fix exceptions when interrupting "executing" unbuffered queries.
|
|
21
|
+
* Don't try to kill a remote thread when a query is already in the "rendering" state.
|
|
22
|
+
* Don't try to kill a remote thread when a query is already in the "transforming" state.
|
|
23
|
+
* Don't try to kill a remote thread when a query is already in the "redirecting" state.
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
Documentation
|
|
27
|
+
--------
|
|
28
|
+
* Refine several items in the helpdoc.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Internal
|
|
32
|
+
--------
|
|
33
|
+
* Fix typo in class name `LimitedQuotePreservingConfigObj`.
|
|
34
|
+
* Update `polars` to v2.0.0.
|
|
35
|
+
* Update `altair` to v6.3.0.
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
v2.28.2 (2026/10/07)
|
|
39
|
+
==============
|
|
40
|
+
|
|
41
|
+
Bug Fixes
|
|
42
|
+
--------
|
|
43
|
+
* Let the `beep_after_seconds` slow query alert happen before paged output.
|
|
44
|
+
* Allow comma-containing favorite queries in `~/.myclirc`.
|
|
45
|
+
* Allow comma-containing init-commands in `~/.myclirc`.
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Internal
|
|
49
|
+
--------
|
|
50
|
+
* `pyproject.toml` readability tweak.
|
|
51
|
+
* Force some transitive dependency updates, to pass `uv audit`.
|
|
52
|
+
* No-op updates to pinned dependencies.
|
|
53
|
+
* Upgrade `yaspin` dependency to v3.5.1.
|
|
54
|
+
* Upgrade `wcwidth` dependency to v0.9.1, which includes a C11 core.
|
|
55
|
+
* Upgrade `setuptools` optional dependency to v84.x.x.
|
|
56
|
+
* Pin `prompt_toolkit` dependency to v3.0.53.
|
|
57
|
+
|
|
58
|
+
|
|
1
59
|
v2.28.1 (2026/10/03)
|
|
2
60
|
==============
|
|
3
61
|
|
|
@@ -59,3 +59,8 @@ The prompt and toolbar are updated more often than needed, even with caching.
|
|
|
59
59
|
|
|
60
60
|
When syntax highlighting with `pygmentize` is enabled for history search previews,
|
|
61
61
|
the colors do not match the user's preferences in `~/.myclirc`.
|
|
62
|
+
|
|
63
|
+
## favorite queries
|
|
64
|
+
|
|
65
|
+
Favorite queries are triple-quoted on save in `~/.myclirc`. If the text of the SQL
|
|
66
|
+
in the favorite query contains both possible triple-quote delimiters, this fails.
|
|
@@ -14,24 +14,86 @@ from Cryptodome.Cipher import AES
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
class
|
|
17
|
+
class SQLValuePreservingConfigObj(ConfigObj):
|
|
18
|
+
"""When reading, quote SQL text on the fly which ConfigObj would otherwise interpret as a list."""
|
|
19
|
+
|
|
20
|
+
# Buglet: the use of _get_triple_quote() does not allow values which
|
|
21
|
+
# contain _both_ possible triple-quote delimiters to be read.
|
|
22
|
+
def _parse(self, infile: list[str]) -> None:
|
|
23
|
+
if not self.list_values or self.unrepr:
|
|
24
|
+
super()._parse(infile)
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
lines = infile.copy()
|
|
28
|
+
in_sql_stanza = False
|
|
29
|
+
index = 0
|
|
30
|
+
while index < len(lines):
|
|
31
|
+
line = lines[index]
|
|
32
|
+
if not line.strip() or line.lstrip().startswith('#'):
|
|
33
|
+
index += 1
|
|
34
|
+
continue
|
|
35
|
+
section = self._sectionmarker.match(line)
|
|
36
|
+
if section is not None:
|
|
37
|
+
_, opening, name, closing, _ = section.groups()
|
|
38
|
+
in_sql_stanza = opening.count('[') == closing.count(']') == 1 and (
|
|
39
|
+
self._unquote(name) == 'favorite_queries' or 'init-commands' in name
|
|
40
|
+
)
|
|
41
|
+
else:
|
|
42
|
+
entry = self._keyword.match(line)
|
|
43
|
+
if entry is not None:
|
|
44
|
+
indent, key, value = entry.groups()
|
|
45
|
+
if value.startswith(('"""', "'''")):
|
|
46
|
+
# Skip complete multiline values, including section-like SQL.
|
|
47
|
+
try:
|
|
48
|
+
_, _, index = self._multiline(value, lines, index, len(lines) - 1)
|
|
49
|
+
except SyntaxError:
|
|
50
|
+
break
|
|
51
|
+
elif in_sql_stanza and not value.startswith(('"', "'")):
|
|
52
|
+
match = self._nolistvalue.match(value)
|
|
53
|
+
if match is not None:
|
|
54
|
+
sql, comment = match.groups()
|
|
55
|
+
lines[index] = f'{indent}{key} = {self._get_triple_quote(sql) % sql} {comment or ""}'
|
|
56
|
+
index += 1
|
|
57
|
+
|
|
58
|
+
super()._parse(lines)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TripleQuotedConfigValue(str):
|
|
62
|
+
"""A value that must retain triple quoting when written."""
|
|
63
|
+
|
|
64
|
+
quote: str | None
|
|
65
|
+
|
|
66
|
+
def __new__(cls, value: str, quote: str | None = None) -> 'TripleQuotedConfigValue':
|
|
67
|
+
instance = super().__new__(cls, value)
|
|
68
|
+
instance.quote = quote
|
|
69
|
+
return instance
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class LimitedQuotePreservingConfigObj(ConfigObj):
|
|
18
73
|
"""Useful for saving individual items without modifying the whole file.
|
|
19
74
|
|
|
20
|
-
|
|
21
|
-
name of the class, could change from double to single in style. If we
|
|
22
|
-
don't do this, multiline triplequoted strings lose their quotes entirely,
|
|
23
|
-
resulting in unreadable files.
|
|
75
|
+
Preserve existing quoting and add triple quotes for new multiline values.
|
|
24
76
|
"""
|
|
25
77
|
|
|
78
|
+
# Buglet: the use of _get_triple_quote() does not allow values which
|
|
79
|
+
# contain _both_ possible triple-quote delimiters to be saved.
|
|
26
80
|
def __init__(self, *args, **kwargs):
|
|
27
81
|
ConfigObj.__init__(self, *args, **kwargs)
|
|
28
82
|
|
|
29
83
|
def _unquote(self, value):
|
|
30
84
|
return value
|
|
31
85
|
|
|
32
|
-
def
|
|
86
|
+
def _multiline(self, value: str, infile: list[str], cur_index: int, maxline: int) -> tuple[str, str | None, int]:
|
|
87
|
+
parsed, comment, end_index = super()._multiline(value, infile, cur_index, maxline)
|
|
88
|
+
return TripleQuotedConfigValue(parsed, value[:3]), comment, end_index
|
|
89
|
+
|
|
90
|
+
def _quote(self, value: str, multiline: bool = True) -> str:
|
|
91
|
+
if isinstance(value, TripleQuotedConfigValue):
|
|
92
|
+
if value.quote is not None:
|
|
93
|
+
return f'{value.quote}{value}{value.quote}'
|
|
94
|
+
return self._get_triple_quote(value) % value
|
|
33
95
|
if '\n' in value:
|
|
34
|
-
return
|
|
96
|
+
return self._get_triple_quote(value) % value
|
|
35
97
|
return value
|
|
36
98
|
|
|
37
99
|
|
|
@@ -49,7 +111,7 @@ def read_config_file(
|
|
|
49
111
|
list_values: bool = True,
|
|
50
112
|
preserve_quotes: bool = False,
|
|
51
113
|
raise_errors: bool = False,
|
|
52
|
-
) -> ConfigObj |
|
|
114
|
+
) -> ConfigObj | LimitedQuotePreservingConfigObj | None:
|
|
53
115
|
"""Read a config file.
|
|
54
116
|
|
|
55
117
|
*list_values* set to `True` is the default behavior of ConfigObj.
|
|
@@ -68,9 +130,9 @@ def read_config_file(
|
|
|
68
130
|
|
|
69
131
|
try:
|
|
70
132
|
if preserve_quotes:
|
|
71
|
-
config =
|
|
133
|
+
config = LimitedQuotePreservingConfigObj(f, interpolation=False, encoding="utf8", list_values=False)
|
|
72
134
|
else:
|
|
73
|
-
config =
|
|
135
|
+
config = SQLValuePreservingConfigObj(f, interpolation=False, encoding="utf8", list_values=list_values)
|
|
74
136
|
except ConfigObjError as e:
|
|
75
137
|
if raise_errors:
|
|
76
138
|
raise
|
|
@@ -66,13 +66,13 @@ class CliArgs:
|
|
|
66
66
|
'host',
|
|
67
67
|
type=str,
|
|
68
68
|
envvar='MYSQL_HOST',
|
|
69
|
-
help='Host address of the
|
|
69
|
+
help='Host address of the MySQL server.',
|
|
70
70
|
)
|
|
71
71
|
port: int | None = clickdc.option(
|
|
72
72
|
'-P',
|
|
73
73
|
type=int,
|
|
74
74
|
envvar='MYSQL_TCP_PORT',
|
|
75
|
-
help='Port number
|
|
75
|
+
help='Port number on the MySQL server.',
|
|
76
76
|
)
|
|
77
77
|
user: str | None = clickdc.option(
|
|
78
78
|
'-u',
|
|
@@ -81,13 +81,14 @@ class CliArgs:
|
|
|
81
81
|
'user',
|
|
82
82
|
type=str,
|
|
83
83
|
envvar='MYSQL_USER',
|
|
84
|
-
help='User name to connect to the
|
|
84
|
+
help='User name to connect to the MySQL server.',
|
|
85
85
|
)
|
|
86
86
|
socket: str | None = clickdc.option(
|
|
87
87
|
'-S',
|
|
88
88
|
type=str,
|
|
89
89
|
envvar='MYSQL_UNIX_SOCKET',
|
|
90
|
-
|
|
90
|
+
metavar='PATH',
|
|
91
|
+
help='Socket path to connect to the MySQL server.',
|
|
91
92
|
)
|
|
92
93
|
password: int | str | None = clickdc.option(
|
|
93
94
|
'-p',
|
|
@@ -96,14 +97,14 @@ class CliArgs:
|
|
|
96
97
|
'password',
|
|
97
98
|
type=INT_OR_STRING_CLICK_TYPE,
|
|
98
99
|
help=dedent(
|
|
99
|
-
"""Password to connect to the
|
|
100
|
+
"""Password to connect to the MySQL server..
|
|
100
101
|
Use with a value to set the password at the CLI, or alone in the last position to request a prompt.
|
|
101
102
|
"""
|
|
102
103
|
),
|
|
103
104
|
)
|
|
104
105
|
password_file: str | None = clickdc.option(
|
|
105
106
|
type=click.Path(),
|
|
106
|
-
help='File or FIFO path containing the password to connect to the
|
|
107
|
+
help='File or FIFO path containing the password to connect to the server.',
|
|
107
108
|
)
|
|
108
109
|
vault_address: str | None = clickdc.option(
|
|
109
110
|
type=str,
|
|
@@ -139,7 +140,7 @@ class CliArgs:
|
|
|
139
140
|
)
|
|
140
141
|
ssl_cert: str | None = clickdc.option(
|
|
141
142
|
type=click.Path(exists=True),
|
|
142
|
-
help='X509
|
|
143
|
+
help='X509 certificate in PEM format.',
|
|
143
144
|
)
|
|
144
145
|
ssl_key: str | None = clickdc.option(
|
|
145
146
|
type=click.Path(exists=True),
|
|
@@ -155,7 +156,7 @@ class CliArgs:
|
|
|
155
156
|
)
|
|
156
157
|
ssl_verify_server_cert: bool = clickdc.option(
|
|
157
158
|
is_flag=True,
|
|
158
|
-
help=("""Verify server's "Common Name" in its cert against hostname used when connecting.
|
|
159
|
+
help=("""Verify server's "Common Name" in its cert against hostname used when connecting."""),
|
|
159
160
|
)
|
|
160
161
|
verbose: int = clickdc.option(
|
|
161
162
|
'-v',
|
|
@@ -201,11 +202,12 @@ class CliArgs:
|
|
|
201
202
|
logfile: TextIOWrapper | None = clickdc.option(
|
|
202
203
|
'-l',
|
|
203
204
|
type=click.File(mode='a', encoding='utf-8'),
|
|
205
|
+
metavar='PATH',
|
|
204
206
|
help='Log every query and its results to a file.',
|
|
205
207
|
)
|
|
206
208
|
checkpoint: str | None = clickdc.option(
|
|
207
209
|
type=str,
|
|
208
|
-
help='In batch or --execute mode, log successful queries to a file, and skip them with --resume.',
|
|
210
|
+
help='In batch or --execute mode, log successful queries to a file, and skip them on replay with --resume.',
|
|
209
211
|
)
|
|
210
212
|
resume: bool = clickdc.option(
|
|
211
213
|
'--resume',
|
|
@@ -214,7 +216,7 @@ class CliArgs:
|
|
|
214
216
|
)
|
|
215
217
|
myclirc: str = clickdc.option(
|
|
216
218
|
type=click.Path(),
|
|
217
|
-
help='Location of myclirc file.',
|
|
219
|
+
help='Location of the myclirc configuration file.',
|
|
218
220
|
)
|
|
219
221
|
auto_vertical_output: bool = clickdc.option(
|
|
220
222
|
is_flag=True,
|
|
@@ -225,7 +227,7 @@ class CliArgs:
|
|
|
225
227
|
is_flag=True,
|
|
226
228
|
default=None,
|
|
227
229
|
clickdc=None,
|
|
228
|
-
help='
|
|
230
|
+
help='Whether to show warnings after executing a SQL statement.',
|
|
229
231
|
)
|
|
230
232
|
table: bool = clickdc.option(
|
|
231
233
|
'-t',
|
|
@@ -240,7 +242,7 @@ class CliArgs:
|
|
|
240
242
|
'--warn/--no-warn',
|
|
241
243
|
default=None,
|
|
242
244
|
clickdc=None,
|
|
243
|
-
help='
|
|
245
|
+
help='Whether to warn before running a destructive query.',
|
|
244
246
|
)
|
|
245
247
|
warn_batch: bool = clickdc.option(
|
|
246
248
|
is_flag=True,
|
|
@@ -264,11 +266,11 @@ class CliArgs:
|
|
|
264
266
|
)
|
|
265
267
|
init_command: str | None = clickdc.option(
|
|
266
268
|
type=str,
|
|
267
|
-
help='SQL statement to execute
|
|
269
|
+
help='Initial SQL statement to execute when connecting.',
|
|
268
270
|
)
|
|
269
271
|
unbuffered: bool | None = clickdc.option(
|
|
270
272
|
is_flag=True,
|
|
271
|
-
help='Instead of copying every row of data into a buffer, fetch rows as needed,
|
|
273
|
+
help='Instead of copying every row of data into a buffer, fetch rows as needed, saving memory.',
|
|
272
274
|
)
|
|
273
275
|
character_set: str | None = clickdc.option(
|
|
274
276
|
'--charset',
|
|
@@ -279,6 +281,7 @@ class CliArgs:
|
|
|
279
281
|
)
|
|
280
282
|
batch: str | None = clickdc.option(
|
|
281
283
|
type=str,
|
|
284
|
+
metavar='PATH',
|
|
282
285
|
help='SQL script to execute in batch mode.',
|
|
283
286
|
)
|
|
284
287
|
# deprecated 2026-06-20
|
|
@@ -319,10 +322,11 @@ class CliArgs:
|
|
|
319
322
|
)
|
|
320
323
|
ssh_options: str | None = clickdc.option(
|
|
321
324
|
type=str,
|
|
322
|
-
help='Extra CLI arguments for SSH with --ssh-jump, placed after options from myclirc.',
|
|
325
|
+
help='Extra CLI arguments for SSH with --ssh-jump, placed after options from ~/.myclirc.',
|
|
323
326
|
)
|
|
324
327
|
kubectl_resource: str | None = clickdc.option(
|
|
325
328
|
type=str,
|
|
329
|
+
metavar='RESOURCE',
|
|
326
330
|
help='Open a kubectl port-forward tunnel to RESOURCE and connect through it.',
|
|
327
331
|
)
|
|
328
332
|
kubectl_options: str | None = clickdc.option(
|
|
@@ -331,6 +335,7 @@ class CliArgs:
|
|
|
331
335
|
)
|
|
332
336
|
boundary_id: str | None = clickdc.option(
|
|
333
337
|
type=str,
|
|
338
|
+
metavar='TARGET_ID',
|
|
334
339
|
help='Open a HashiCorp Boundary tunnel to TARGET_ID and connect through it.',
|
|
335
340
|
)
|
|
336
341
|
checkup: bool = clickdc.option(
|