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.
Files changed (225) hide show
  1. {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/ci.yml +1 -1
  2. {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/publish.yml +1 -1
  3. {mycli-2.28.1/mycli.egg-info → mycli-2.29.1}/PKG-INFO +11 -9
  4. {mycli-2.28.1 → mycli-2.29.1}/changelog.md +58 -0
  5. {mycli-2.28.1 → mycli-2.29.1}/doc/known_bugs.md +5 -0
  6. {mycli-2.28.1 → mycli-2.29.1}/docker/resources/test_db-1.0.7.tar.gz +1 -1
  7. {mycli-2.28.1 → mycli-2.29.1}/mycli/config.py +72 -10
  8. {mycli-2.28.1 → mycli-2.29.1}/mycli/constants.py +1 -0
  9. {mycli-2.28.1 → mycli-2.29.1}/mycli/main.py +20 -15
  10. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/repl.py +112 -47
  11. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/background_runner.py +52 -6
  12. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/favorite_queries.py +3 -2
  13. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/io_commands.py +70 -35
  14. {mycli-2.28.1 → mycli-2.29.1/mycli.egg-info}/PKG-INFO +11 -9
  15. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/requires.txt +10 -8
  16. mycli-2.29.1/mycli.egg-info/scm_version.json +8 -0
  17. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_background_runner.py +352 -9
  18. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_config.py +127 -4
  19. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_favoritequeries.py +162 -4
  20. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main.py +1 -1
  21. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_repl.py +581 -4
  22. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_io_commands.py +143 -6
  23. {mycli-2.28.1 → mycli-2.29.1}/pyproject.toml +16 -10
  24. mycli-2.28.1/mycli.egg-info/scm_version.json +0 -8
  25. {mycli-2.28.1 → mycli-2.29.1}/.git-blame-ignore-revs +0 -0
  26. {mycli-2.28.1 → mycli-2.29.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  27. {mycli-2.28.1 → mycli-2.29.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  28. {mycli-2.28.1 → mycli-2.29.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  29. {mycli-2.28.1 → mycli-2.29.1}/.github/dependabot.yml +0 -0
  30. {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/lint.yml +0 -0
  31. {mycli-2.28.1 → mycli-2.29.1}/.github/workflows/typecheck.yml +0 -0
  32. {mycli-2.28.1 → mycli-2.29.1}/.gitignore +0 -0
  33. {mycli-2.28.1 → mycli-2.29.1}/AGENTS.md +0 -0
  34. {mycli-2.28.1 → mycli-2.29.1}/AUTHORS.md +0 -0
  35. {mycli-2.28.1 → mycli-2.29.1}/CONTRIBUTING.md +0 -0
  36. {mycli-2.28.1 → mycli-2.29.1}/LICENSE.txt +0 -0
  37. {mycli-2.28.1 → mycli-2.29.1}/MANIFEST.in +0 -0
  38. {mycli-2.28.1 → mycli-2.29.1}/README.md +0 -0
  39. {mycli-2.28.1 → mycli-2.29.1}/SPONSORS.md +0 -0
  40. {mycli-2.28.1 → mycli-2.29.1}/doc/cookbook.md +0 -0
  41. {mycli-2.28.1 → mycli-2.29.1}/doc/key_bindings.md +0 -0
  42. {mycli-2.28.1 → mycli-2.29.1}/doc/llm.md +0 -0
  43. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/main.gif +0 -0
  44. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_describe.png +0 -0
  45. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_group_by.png +0 -0
  46. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_histogram.png +0 -0
  47. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/polars_pivot.png +0 -0
  48. {mycli-2.28.1 → mycli-2.29.1}/doc/screenshots/tables.png +0 -0
  49. {mycli-2.28.1 → mycli-2.29.1}/doc/transforms.md +0 -0
  50. {mycli-2.28.1 → mycli-2.29.1}/docker/Dockerfile +0 -0
  51. {mycli-2.28.1 → mycli-2.29.1}/docker/resources/test_db_license.md +0 -0
  52. {mycli-2.28.1 → mycli-2.29.1}/mycli/AUTHORS.txt +0 -0
  53. {mycli-2.28.1 → mycli-2.29.1}/mycli/SPONSORS.txt +0 -0
  54. {mycli-2.28.1 → mycli-2.29.1}/mycli/TIPS.txt +0 -0
  55. {mycli-2.28.1 → mycli-2.29.1}/mycli/__init__.py +0 -0
  56. {mycli-2.28.1 → mycli-2.29.1}/mycli/app_state.py +0 -0
  57. {mycli-2.28.1 → mycli-2.29.1}/mycli/cli_runner.py +0 -0
  58. {mycli-2.28.1 → mycli-2.29.1}/mycli/client.py +0 -0
  59. {mycli-2.28.1 → mycli-2.29.1}/mycli/client_commands.py +0 -0
  60. {mycli-2.28.1 → mycli-2.29.1}/mycli/client_connection.py +0 -0
  61. {mycli-2.28.1 → mycli-2.29.1}/mycli/client_query.py +0 -0
  62. {mycli-2.28.1 → mycli-2.29.1}/mycli/compat.py +0 -0
  63. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/batch.py +0 -0
  64. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/checkup.py +0 -0
  65. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/completions.py +0 -0
  66. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/execute.py +0 -0
  67. {mycli-2.28.1 → mycli-2.29.1}/mycli/main_modes/list_dsn.py +0 -0
  68. {mycli-2.28.1 → mycli-2.29.1}/mycli/myclirc +0 -0
  69. {mycli-2.28.1 → mycli-2.29.1}/mycli/output.py +0 -0
  70. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/__init__.py +0 -0
  71. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/__init__.py +0 -0
  72. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/completion_engine.py +0 -0
  73. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/completion_refresher.py +0 -0
  74. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/schema_prefetcher.py +0 -0
  75. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/completion/sql_completer.py +0 -0
  76. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/credentials/__init__.py +0 -0
  77. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/credentials/password_sources.py +0 -0
  78. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/__init__.py +0 -0
  79. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/completion.py +0 -0
  80. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/dataframes/transform.py +0 -0
  81. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/__init__.py +0 -0
  82. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/execution/sql_execute.py +0 -0
  83. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/__init__.py +0 -0
  84. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/boundary/__init__.py +0 -0
  85. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/boundary/boundary_tunnel.py +0 -0
  86. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/fzf/__init__.py +0 -0
  87. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/fzf/fzf.py +0 -0
  88. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/kubernetes/__init__.py +0 -0
  89. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/kubernetes/kubectl_tunnel.py +0 -0
  90. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/macos/__init__.py +0 -0
  91. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/macos/macos_keychain.py +0 -0
  92. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/openssh/__init__.py +0 -0
  93. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/openssh/ssh_tunnel.py +0 -0
  94. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/vault/__init__.py +0 -0
  95. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/integrations/vault/vault_credentials.py +0 -0
  96. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/__init__.py +0 -0
  97. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/fzf_history.py +0 -0
  98. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/history.py +0 -0
  99. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/key_bindings.py +0 -0
  100. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/multiline.py +0 -0
  101. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/style.py +0 -0
  102. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/toolbar.py +0 -0
  103. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/prompt_toolkit/utils.py +0 -0
  104. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/pygments/__init__.py +0 -0
  105. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/pygments/mycli_lexer.py +0 -0
  106. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/redirection/__init__.py +0 -0
  107. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/redirection/hybrid_redirection.py +0 -0
  108. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/__init__.py +0 -0
  109. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/db_commands.py +0 -0
  110. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/delimiter_command.py +0 -0
  111. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/dsn_aliases.py +0 -0
  112. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/llm.py +0 -0
  113. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/main.py +0 -0
  114. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/source.py +0 -0
  115. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/special_commands/special_command_utils.py +0 -0
  116. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/sql_result/__init__.py +0 -0
  117. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/sql_result/sql_result.py +0 -0
  118. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/tabular_output/__init__.py +0 -0
  119. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/tabular_output/sql_format.py +0 -0
  120. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/__init__.py +0 -0
  121. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/batch_utils.py +0 -0
  122. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/cli_utils.py +0 -0
  123. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/interactive_utils.py +0 -0
  124. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/key_binding_utils.py +0 -0
  125. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/keyring_utils.py +0 -0
  126. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/path_utils.py +0 -0
  127. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/sql_utils.py +0 -0
  128. {mycli-2.28.1 → mycli-2.29.1}/mycli/packages/utils/string_utils.py +0 -0
  129. {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/bash/mycli +0 -0
  130. {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/fish/mycli.fish +0 -0
  131. {mycli-2.28.1 → mycli-2.29.1}/mycli/resources/completions/zsh/_mycli +0 -0
  132. {mycli-2.28.1 → mycli-2.29.1}/mycli/types.py +0 -0
  133. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/SOURCES.txt +0 -0
  134. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/dependency_links.txt +0 -0
  135. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/entry_points.txt +0 -0
  136. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/scm_file_list.json +0 -0
  137. {mycli-2.28.1 → mycli-2.29.1}/mycli.egg-info/top_level.txt +0 -0
  138. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/__init__.py +0 -0
  139. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/__init__.py +0 -0
  140. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/auto_vertical.feature +0 -0
  141. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/basic_commands.feature +0 -0
  142. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/connection.feature +0 -0
  143. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/crud_database.feature +0 -0
  144. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/crud_table.feature +0 -0
  145. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/db_utils.py +0 -0
  146. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/environment.py +0 -0
  147. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/fixture_data/help_commands.txt +0 -0
  148. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/fixture_utils.py +0 -0
  149. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/iocommands.feature +0 -0
  150. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/named_queries.feature +0 -0
  151. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/specials.feature +0 -0
  152. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/__init__.py +0 -0
  153. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/auto_vertical.py +0 -0
  154. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/basic_commands.py +0 -0
  155. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/connection.py +0 -0
  156. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/crud_database.py +0 -0
  157. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/crud_table.py +0 -0
  158. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/iocommands.py +0 -0
  159. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/named_queries.py +0 -0
  160. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/specials.py +0 -0
  161. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/utils.py +0 -0
  162. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/steps/wrappers.py +0 -0
  163. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/features/wrappager.py +0 -0
  164. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/myclirc +0 -0
  165. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/mylogin.cnf +0 -0
  166. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/conftest.py +0 -0
  167. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_app_state.py +0 -0
  168. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_bash_completion.py +0 -0
  169. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_batch_utils.py +0 -0
  170. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_boundary_tunnel.py +0 -0
  171. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_checkup.py +0 -0
  172. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_cli_runner.py +0 -0
  173. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_cli_utils.py +0 -0
  174. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_clibuffer.py +0 -0
  175. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client.py +0 -0
  176. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_commands.py +0 -0
  177. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_connection.py +0 -0
  178. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_client_query.py +0 -0
  179. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completer_use_switch.py +0 -0
  180. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completion_engine.py +0 -0
  181. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_completion_refresher.py +0 -0
  182. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_delimitercommand.py +0 -0
  183. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_dsn_aliases.py +0 -0
  184. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_fish_completion.py +0 -0
  185. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_fzf.py +0 -0
  186. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_hybrid_redirection.py +0 -0
  187. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_interactive_utils.py +0 -0
  188. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_key_binding_utils.py +0 -0
  189. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_key_bindings.py +0 -0
  190. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_keyring_utils.py +0 -0
  191. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_kubectl_tunnel.py +0 -0
  192. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_macos_keychain.py +0 -0
  193. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_batch.py +0 -0
  194. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_execute.py +0 -0
  195. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_main_modes_list_dsn.py +0 -0
  196. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_naive_completion.py +0 -0
  197. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_output.py +0 -0
  198. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_password_sources.py +0 -0
  199. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_path_utils.py +0 -0
  200. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_polars_completion.py +0 -0
  201. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_polars_transform.py +0 -0
  202. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_fzf_history.py +0 -0
  203. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_history.py +0 -0
  204. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_style.py +0 -0
  205. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_toolbar.py +0 -0
  206. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_prompt_toolkit_utils.py +0 -0
  207. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_schema_prefetcher.py +0 -0
  208. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_smart_completion_public_schema_only.py +0 -0
  209. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_commands_init.py +0 -0
  210. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_db_commands.py +0 -0
  211. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_llm.py +0 -0
  212. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_main.py +0 -0
  213. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_source.py +0 -0
  214. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_special_utils.py +0 -0
  215. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sql_execute.py +0 -0
  216. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sql_utils.py +0 -0
  217. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sqlcompleter.py +0 -0
  218. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_sqlresult.py +0 -0
  219. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_ssh_tunnel.py +0 -0
  220. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_string_utils.py +0 -0
  221. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_tabular_output.py +0 -0
  222. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_vault.py +0 -0
  223. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/pytests/test_zsh_completion.py +0 -0
  224. {mycli-2.28.1 → mycli-2.29.1}/mycli_test/utils.py +0 -0
  225. {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@083ec148d28e62f2b24b8f4541693dfe1d50488d # v1.54.0
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@083ec148d28e62f2b24b8f4541693dfe1d50488d # v1.54.0
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.28.1
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<4.0.0,>=3.0.41
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.8.3
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.5
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.4.0
48
+ Requires-Dist: yaspin~=3.5.1
49
49
  Provides-Extra: llm
50
- Requires-Dist: llm~=0.33; extra == "llm"
51
- Requires-Dist: setuptools==83.*; extra == "llm"
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~=1.44.1; extra == "dataframe"
55
- Requires-Dist: altair~=6.2.2; extra == "dataframe"
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.
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
- name: mycli-2.28.1/docker/resources/test_db-1.0.7.tar.gz
2
+ name: mycli-2.29.1/docker/resources/test_db-1.0.7.tar.gz
3
3
  size: 35607473 bytes
4
4
  sha256: c44c140f352f35d47fdb65df60f52b779ef552822fad6c4efcfa7b134c3faf84
@@ -14,24 +14,86 @@ from Cryptodome.Cipher import AES
14
14
  logger = logging.getLogger(__name__)
15
15
 
16
16
 
17
- class LimiitedQuotePreservingConfigObj(ConfigObj):
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
- Triplequotes must be manually added for multiline values, and despite the
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 _quote(self, value, multiline=True):
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 f"'''{value}'''"
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 | LimiitedQuotePreservingConfigObj | None:
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 = LimiitedQuotePreservingConfigObj(f, interpolation=False, encoding="utf8", list_values=False)
133
+ config = LimitedQuotePreservingConfigObj(f, interpolation=False, encoding="utf8", list_values=False)
72
134
  else:
73
- config = ConfigObj(f, interpolation=False, encoding="utf8", list_values=list_values)
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
@@ -58,6 +58,7 @@ TTY_ERASE_LINE = '\r\x1b[2K'
58
58
 
59
59
 
60
60
  class QueryState(enum.StrEnum):
61
+ REDIRECTING = 'redirecting'
61
62
  RENDERING = 'rendering'
62
63
  STREAMING = 'streaming'
63
64
  TRANSFORMING = 'transforming'
@@ -66,13 +66,13 @@ class CliArgs:
66
66
  'host',
67
67
  type=str,
68
68
  envvar='MYSQL_HOST',
69
- help='Host address of the database.',
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 to use for connection. Honors $MYSQL_TCP_PORT.',
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 database.',
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
- help='The socket file to use for connection.',
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 database.
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 db if not specified otherwise.',
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 cert in PEM format.',
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. This option is disabled by default."""),
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='Automatically show warnings after executing a SQL statement.',
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='Warn before running a destructive query.',
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 after connecting.',
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, to save memory.',
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(