execsql2 2.22.1__tar.gz → 2.22.2__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 (377) hide show
  1. {execsql2-2.22.1 → execsql2-2.22.2}/CHANGELOG.md +8 -0
  2. {execsql2-2.22.1 → execsql2-2.22.2}/PKG-INFO +2 -2
  3. {execsql2-2.22.1 → execsql2-2.22.2}/README.md +1 -1
  4. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/formatter.md +1 -1
  5. {execsql2-2.22.1 → execsql2-2.22.2}/pyproject.toml +2 -2
  6. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/gui.py +15 -6
  7. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_backends.py +15 -5
  8. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_prompt.py +27 -0
  9. {execsql2-2.22.1 → execsql2-2.22.2}/uv.lock +1 -1
  10. {execsql2-2.22.1 → execsql2-2.22.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  11. {execsql2-2.22.1 → execsql2-2.22.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  12. {execsql2-2.22.1 → execsql2-2.22.2}/.github/dependabot.yml +0 -0
  13. {execsql2-2.22.1 → execsql2-2.22.2}/.github/workflows/ci-cd.yml +0 -0
  14. {execsql2-2.22.1 → execsql2-2.22.2}/.gitignore +0 -0
  15. {execsql2-2.22.1 → execsql2-2.22.2}/.pre-commit-config.yaml +0 -0
  16. {execsql2-2.22.1 → execsql2-2.22.2}/.pre-commit-hooks.yaml +0 -0
  17. {execsql2-2.22.1 → execsql2-2.22.2}/.python-version +0 -0
  18. {execsql2-2.22.1 → execsql2-2.22.2}/.readthedocs.yaml +0 -0
  19. {execsql2-2.22.1 → execsql2-2.22.2}/CONTRIBUTING.md +0 -0
  20. {execsql2-2.22.1 → execsql2-2.22.2}/LICENSE.txt +0 -0
  21. {execsql2-2.22.1 → execsql2-2.22.2}/NOTICE +0 -0
  22. {execsql2-2.22.1 → execsql2-2.22.2}/SECURITY.md +0 -0
  23. {execsql2-2.22.1 → execsql2-2.22.2}/docs/about/contributors.md +0 -0
  24. {execsql2-2.22.1 → execsql2-2.22.2}/docs/about/copyright.md +0 -0
  25. {execsql2-2.22.1 → execsql2-2.22.2}/docs/about/divergence.md +0 -0
  26. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/cli.md +0 -0
  27. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/db.md +0 -0
  28. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/exporters.md +0 -0
  29. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/importers.md +0 -0
  30. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/index.md +0 -0
  31. {execsql2-2.22.1 → execsql2-2.22.2}/docs/api/metacommands.md +0 -0
  32. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/adding_db_adapters.md +0 -0
  33. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/adding_exporters.md +0 -0
  34. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/adding_importers.md +0 -0
  35. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/adding_metacommands.md +0 -0
  36. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/architecture.md +0 -0
  37. {execsql2-2.22.1 → execsql2-2.22.2}/docs/dev/releasing.md +0 -0
  38. {execsql2-2.22.1 → execsql2-2.22.2}/docs/getting-started/installation.md +0 -0
  39. {execsql2-2.22.1 → execsql2-2.22.2}/docs/getting-started/requirements.md +0 -0
  40. {execsql2-2.22.1 → execsql2-2.22.2}/docs/getting-started/syntax.md +0 -0
  41. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/debugging.md +0 -0
  42. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/documentation.md +0 -0
  43. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/encoding.md +0 -0
  44. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/examples.md +0 -0
  45. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/logging.md +0 -0
  46. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/sql_syntax.md +0 -0
  47. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/usage.md +0 -0
  48. {execsql2-2.22.1 → execsql2-2.22.2}/docs/guides/using_scripts.md +0 -0
  49. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/Compare_planets.png +0 -0
  50. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/actions.png +0 -0
  51. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/actions2.png +0 -0
  52. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/checkboxes.png +0 -0
  53. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/connect.b64 +0 -0
  54. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/connect.png +0 -0
  55. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/create_conf.png +0 -0
  56. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/data_error1_screenshot.jpg +0 -0
  57. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/entry_form.png +0 -0
  58. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/execsql_console.png +0 -0
  59. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/execsql_logo_01.png +0 -0
  60. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/fatals.png +0 -0
  61. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/logo_small.png +0 -0
  62. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/pause_terminal.png +0 -0
  63. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/pause_terminal_sm.b64 +0 -0
  64. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/pause_terminal_sm.png +0 -0
  65. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/prompt_compare.png +0 -0
  66. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/set_build_commands.jpg +0 -0
  67. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/unit_conversions.b64 +0 -0
  68. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/unit_conversions_029.png +0 -0
  69. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/unmatched.png +0 -0
  70. {execsql2-2.22.1 → execsql2-2.22.2}/docs/images/vim_execsql_highlight.png +0 -0
  71. {execsql2-2.22.1 → execsql2-2.22.2}/docs/index.md +0 -0
  72. {execsql2-2.22.1 → execsql2-2.22.2}/docs/reference/configuration.md +0 -0
  73. {execsql2-2.22.1 → execsql2-2.22.2}/docs/reference/metacommands.md +0 -0
  74. {execsql2-2.22.1 → execsql2-2.22.2}/docs/reference/security.md +0 -0
  75. {execsql2-2.22.1 → execsql2-2.22.2}/docs/reference/substitution_vars.md +0 -0
  76. {execsql2-2.22.1 → execsql2-2.22.2}/extras/plugin-template/README.md +0 -0
  77. {execsql2-2.22.1 → execsql2-2.22.2}/extras/plugin-template/pyproject.toml +0 -0
  78. {execsql2-2.22.1 → execsql2-2.22.2}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
  79. {execsql2-2.22.1 → execsql2-2.22.2}/extras/plugin-template/tests/test_plugin.py.example +0 -0
  80. {execsql2-2.22.1 → execsql2-2.22.2}/extras/vscode-execsql/README.md +0 -0
  81. {execsql2-2.22.1 → execsql2-2.22.2}/extras/vscode-execsql/package.json +0 -0
  82. {execsql2-2.22.1 → execsql2-2.22.2}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +0 -0
  83. {execsql2-2.22.1 → execsql2-2.22.2}/justfile +0 -0
  84. {execsql2-2.22.1 → execsql2-2.22.2}/scripts/benchmarks/README.md +0 -0
  85. {execsql2-2.22.1 → execsql2-2.22.2}/scripts/benchmarks/results/.gitignore +0 -0
  86. {execsql2-2.22.1 → execsql2-2.22.2}/scripts/benchmarks/run_benchmarks.py +0 -0
  87. {execsql2-2.22.1 → execsql2-2.22.2}/scripts/generate_vscode_grammar.py +0 -0
  88. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/__init__.py +0 -0
  89. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/__main__.py +0 -0
  90. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/api.py +0 -0
  91. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/cli/__init__.py +0 -0
  92. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/cli/dsn.py +0 -0
  93. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/cli/help.py +0 -0
  94. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/cli/lint.py +0 -0
  95. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/cli/run.py +0 -0
  96. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/config.py +0 -0
  97. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/data/__init__.py +0 -0
  98. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/data/execsql.conf.template +0 -0
  99. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/__init__.py +0 -0
  100. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/access.py +0 -0
  101. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/base.py +0 -0
  102. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/dsn.py +0 -0
  103. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/duckdb.py +0 -0
  104. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/factory.py +0 -0
  105. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/firebird.py +0 -0
  106. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/mysql.py +0 -0
  107. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/oracle.py +0 -0
  108. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/postgres.py +0 -0
  109. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/sqlite.py +0 -0
  110. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/db/sqlserver.py +0 -0
  111. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/debug/__init__.py +0 -0
  112. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/debug/repl.py +0 -0
  113. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exceptions.py +0 -0
  114. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/__init__.py +0 -0
  115. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/base.py +0 -0
  116. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/delimited.py +0 -0
  117. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/duckdb.py +0 -0
  118. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/feather.py +0 -0
  119. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/html.py +0 -0
  120. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/json.py +0 -0
  121. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/latex.py +0 -0
  122. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/markdown.py +0 -0
  123. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/ods.py +0 -0
  124. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/parquet.py +0 -0
  125. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/pretty.py +0 -0
  126. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/protocol.py +0 -0
  127. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/raw.py +0 -0
  128. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/sqlite.py +0 -0
  129. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/templates.py +0 -0
  130. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/values.py +0 -0
  131. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/xls.py +0 -0
  132. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/xlsx.py +0 -0
  133. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/xml.py +0 -0
  134. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/yaml.py +0 -0
  135. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/exporters/zip.py +0 -0
  136. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/format.py +0 -0
  137. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/gui/__init__.py +0 -0
  138. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/gui/base.py +0 -0
  139. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/gui/console.py +0 -0
  140. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/gui/desktop.py +0 -0
  141. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/gui/tui.py +0 -0
  142. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/__init__.py +0 -0
  143. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/base.py +0 -0
  144. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/csv.py +0 -0
  145. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/feather.py +0 -0
  146. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/json.py +0 -0
  147. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/ods.py +0 -0
  148. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/importers/xls.py +0 -0
  149. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/__init__.py +0 -0
  150. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/conditions.py +0 -0
  151. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/connect.py +0 -0
  152. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/control.py +0 -0
  153. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/data.py +0 -0
  154. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/debug.py +0 -0
  155. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/dispatch.py +0 -0
  156. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/io.py +0 -0
  157. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/io_export.py +0 -0
  158. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/io_fileops.py +0 -0
  159. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/io_import.py +0 -0
  160. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/io_write.py +0 -0
  161. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/prompt.py +0 -0
  162. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/script_ext.py +0 -0
  163. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/system.py +0 -0
  164. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/metacommands/upsert.py +0 -0
  165. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/models.py +0 -0
  166. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/parser.py +0 -0
  167. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/plugins.py +0 -0
  168. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/py.typed +0 -0
  169. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/__init__.py +0 -0
  170. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/ast.py +0 -0
  171. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/control.py +0 -0
  172. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/engine.py +0 -0
  173. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/executor.py +0 -0
  174. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/parser.py +0 -0
  175. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/script/variables.py +0 -0
  176. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/state.py +0 -0
  177. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/state.pyi +0 -0
  178. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/types.py +0 -0
  179. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/__init__.py +0 -0
  180. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/auth.py +0 -0
  181. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/crypto.py +0 -0
  182. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/datetime.py +0 -0
  183. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/errors.py +0 -0
  184. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/fileio.py +0 -0
  185. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/mail.py +0 -0
  186. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/numeric.py +0 -0
  187. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/regex.py +0 -0
  188. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/strings.py +0 -0
  189. {execsql2-2.22.1 → execsql2-2.22.2}/src/execsql/utils/timer.py +0 -0
  190. {execsql2-2.22.1 → execsql2-2.22.2}/templates/README.md +0 -0
  191. {execsql2-2.22.1 → execsql2-2.22.2}/templates/config_settings.sqlite +0 -0
  192. {execsql2-2.22.1 → execsql2-2.22.2}/templates/example_config_prompt.sql +0 -0
  193. {execsql2-2.22.1 → execsql2-2.22.2}/templates/make_config_db.sql +0 -0
  194. {execsql2-2.22.1 → execsql2-2.22.2}/templates/md_compare.sql +0 -0
  195. {execsql2-2.22.1 → execsql2-2.22.2}/templates/md_glossary.sql +0 -0
  196. {execsql2-2.22.1 → execsql2-2.22.2}/templates/md_upsert.sql +0 -0
  197. {execsql2-2.22.1 → execsql2-2.22.2}/templates/pg_compare.sql +0 -0
  198. {execsql2-2.22.1 → execsql2-2.22.2}/templates/pg_glossary.sql +0 -0
  199. {execsql2-2.22.1 → execsql2-2.22.2}/templates/pg_upsert.sql +0 -0
  200. {execsql2-2.22.1 → execsql2-2.22.2}/templates/script_template.sql +0 -0
  201. {execsql2-2.22.1 → execsql2-2.22.2}/templates/ss_compare.sql +0 -0
  202. {execsql2-2.22.1 → execsql2-2.22.2}/templates/ss_glossary.sql +0 -0
  203. {execsql2-2.22.1 → execsql2-2.22.2}/templates/ss_upsert.sql +0 -0
  204. {execsql2-2.22.1 → execsql2-2.22.2}/tests/__init__.py +0 -0
  205. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/__init__.py +0 -0
  206. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_cli.py +0 -0
  207. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_cli_e2e.py +0 -0
  208. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_cli_run.py +0 -0
  209. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_lint.py +0 -0
  210. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_ping.py +0 -0
  211. {execsql2-2.22.1 → execsql2-2.22.2}/tests/cli/test_profile.py +0 -0
  212. {execsql2-2.22.1 → execsql2-2.22.2}/tests/conftest.py +0 -0
  213. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/__init__.py +0 -0
  214. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_access_windows.py +0 -0
  215. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_base.py +0 -0
  216. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_db_adapters_mocked.py +0 -0
  217. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_db_adapters_mocked_extra.py +0 -0
  218. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_dsn.py +0 -0
  219. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_duckdb.py +0 -0
  220. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_factory.py +0 -0
  221. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_mysql_case_folding.py +0 -0
  222. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_mysql_inprocess.py +0 -0
  223. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_postgres.py +0 -0
  224. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_postgres_inprocess.py +0 -0
  225. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_sqlite.py +0 -0
  226. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_sqlite_extra.py +0 -0
  227. {execsql2-2.22.1 → execsql2-2.22.2}/tests/db/test_sqlserver_inprocess.py +0 -0
  228. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/__init__.py +0 -0
  229. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_base.py +0 -0
  230. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_db.py +0 -0
  231. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_delimited.py +0 -0
  232. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_duckdb_exporter.py +0 -0
  233. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_exporters.py +0 -0
  234. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_feather.py +0 -0
  235. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_html_extended.py +0 -0
  236. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_html_latex.py +0 -0
  237. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_json.py +0 -0
  238. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_json_extended.py +0 -0
  239. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_latex_extended.py +0 -0
  240. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_markdown.py +0 -0
  241. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_ods.py +0 -0
  242. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_ods_export.py +0 -0
  243. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_parquet.py +0 -0
  244. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_pretty_extended.py +0 -0
  245. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_raw_extended.py +0 -0
  246. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_sqlite_exporter.py +0 -0
  247. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_templates.py +0 -0
  248. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_templates_extended.py +0 -0
  249. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_values_extended.py +0 -0
  250. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_xls_xlsx.py +0 -0
  251. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_xlsx.py +0 -0
  252. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_xml.py +0 -0
  253. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_yaml.py +0 -0
  254. {execsql2-2.22.1 → execsql2-2.22.2}/tests/exporters/test_zip.py +0 -0
  255. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/__init__.py +0 -0
  256. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_backends_extended.py +0 -0
  257. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_compare_stats.py +0 -0
  258. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_compute_row_diffs.py +0 -0
  259. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_desktop_dialogs.py +0 -0
  260. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_tui_pilot.py +0 -0
  261. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_tui_pilot_complex.py +0 -0
  262. {execsql2-2.22.1 → execsql2-2.22.2}/tests/gui/test_utils_gui_extended.py +0 -0
  263. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/__init__.py +0 -0
  264. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_base_extended.py +0 -0
  265. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_csv_edge_cases.py +0 -0
  266. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_csv_importer.py +0 -0
  267. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_feather_importer.py +0 -0
  268. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_json_importer.py +0 -0
  269. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_ods_importer.py +0 -0
  270. {execsql2-2.22.1 → execsql2-2.22.2}/tests/importers/test_xls_importer.py +0 -0
  271. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/__init__.py +0 -0
  272. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/conftest.py +0 -0
  273. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/test_dsn.py +0 -0
  274. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/test_duckdb.py +0 -0
  275. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/test_mysql.py +0 -0
  276. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/test_postgres.py +0 -0
  277. {execsql2-2.22.1 → execsql2-2.22.2}/tests/integration/test_sqlite.py +0 -0
  278. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/__init__.py +0 -0
  279. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_assert.py +0 -0
  280. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_breakpoint.py +0 -0
  281. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_conditions_extra.py +0 -0
  282. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_connect.py +0 -0
  283. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_io_export.py +0 -0
  284. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_io_import.py +0 -0
  285. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands.py +0 -0
  286. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_connect.py +0 -0
  287. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_data.py +0 -0
  288. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_extended.py +0 -0
  289. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
  290. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_io.py +0 -0
  291. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
  292. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_script_ext.py +0 -0
  293. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_system.py +0 -0
  294. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_metacommands_system_extra.py +0 -0
  295. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_pg_upsert.py +0 -0
  296. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_row_count.py +0 -0
  297. {execsql2-2.22.1 → execsql2-2.22.2}/tests/metacommands/test_show_scripts.py +0 -0
  298. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/__init__.py +0 -0
  299. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/audit_lint_bad.sql +0 -0
  300. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/audit_smoke/sample.json +0 -0
  301. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/audit_smoke/sample.jsonl +0 -0
  302. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/audit_smoke.sql +0 -0
  303. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/config_runtime.sql +0 -0
  304. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/control_flow.sql +0 -0
  305. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/counters_and_locals.sql +0 -0
  306. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/error_handling.sql +0 -0
  307. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/import_options/has_comments.csv +0 -0
  308. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/import_options.sql +0 -0
  309. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/includes/helper.sql +0 -0
  310. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/includes.sql +0 -0
  311. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/io_formats.sql +0 -0
  312. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
  313. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/multi_db.sql +0 -0
  314. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/parquet_feather_roundtrip.sql +0 -0
  315. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
  316. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/predicates.sql +0 -0
  317. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/scripts.sql +0 -0
  318. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/smoke.sql +0 -0
  319. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/subroutine_loops.sql +0 -0
  320. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/subvars_advanced.sql +0 -0
  321. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/template_export/greeting.tmpl +0 -0
  322. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/template_export.sql +0 -0
  323. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/timer.sql +0 -0
  324. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/transactions.sql +0 -0
  325. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/write_create_table.sql +0 -0
  326. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/fixtures/xlsx_ods_roundtrip.sql +0 -0
  327. {execsql2-2.22.1 → execsql2-2.22.2}/tests/scripts/test_sql_scripts.py +0 -0
  328. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/__init__.py +0 -0
  329. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_env_detection.py +0 -0
  330. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_expansion_bomb.py +0 -0
  331. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_import_regex_hardening.py +0 -0
  332. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_log_redaction.py +0 -0
  333. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_odbc_injection.py +0 -0
  334. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_path_containment.py +0 -0
  335. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_substitution_injection.py +0 -0
  336. {execsql2-2.22.1 → execsql2-2.22.2}/tests/security/test_zip_bomb.py +0 -0
  337. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_api.py +0 -0
  338. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_api_extended.py +0 -0
  339. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_ast.py +0 -0
  340. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_ast_parser.py +0 -0
  341. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_bundled_templates.py +0 -0
  342. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_config.py +0 -0
  343. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_config_data.py +0 -0
  344. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_config_extended.py +0 -0
  345. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_debug_repl.py +0 -0
  346. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_engine.py +0 -0
  347. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_error_messages.py +0 -0
  348. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_exceptions.py +0 -0
  349. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_executor.py +0 -0
  350. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_executor_inprocess.py +0 -0
  351. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_format.py +0 -0
  352. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_mail.py +0 -0
  353. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_models.py +0 -0
  354. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_package.py +0 -0
  355. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_parser.py +0 -0
  356. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_parser_params.py +0 -0
  357. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_plugins.py +0 -0
  358. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_registry.py +0 -0
  359. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_script.py +0 -0
  360. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_state.py +0 -0
  361. {execsql2-2.22.1 → execsql2-2.22.2}/tests/test_types.py +0 -0
  362. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/__init__.py +0 -0
  363. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_auth.py +0 -0
  364. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_auth_extra.py +0 -0
  365. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_crypto.py +0 -0
  366. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_datetime.py +0 -0
  367. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_encodedfile_context.py +0 -0
  368. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_errors.py +0 -0
  369. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_errors_extra.py +0 -0
  370. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_fileio.py +0 -0
  371. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_fileio_extra.py +0 -0
  372. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_numeric.py +0 -0
  373. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_regex.py +0 -0
  374. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_strings.py +0 -0
  375. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_timer.py +0 -0
  376. {execsql2-2.22.1 → execsql2-2.22.2}/tests/utils/test_timer_extra.py +0 -0
  377. {execsql2-2.22.1 → execsql2-2.22.2}/zensical.toml +0 -0
@@ -13,6 +13,14 @@ ______________________________________________________________________
13
13
 
14
14
  ______________________________________________________________________
15
15
 
16
+ ## [2.22.2] - 2026-07-13
17
+
18
+ ### Fixed
19
+
20
+ - `ASK … SUB` now stores the actual answer ("Yes" or "No"); it previously stored "No" for every response, so `IF(IS_TRUE(…))` and `IF(…)` branches keyed on the answer never took the yes path. Pressing `Esc` at the prompt again quits the script.
21
+
22
+ ______________________________________________________________________
23
+
16
24
  ## [2.22.1] - 2026-07-04
17
25
 
18
26
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.22.1
3
+ Version: 2.22.2
4
4
  Summary: Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables.
5
5
  Project-URL: Homepage, https://execsql2.readthedocs.io
6
6
  Project-URL: Repository, https://github.com/geocoug/execsql
@@ -384,7 +384,7 @@ execsql-format --no-sql --in-place scripts/
384
384
  ```yaml
385
385
  repos:
386
386
  - repo: https://github.com/geocoug/execsql
387
- rev: v2.22.1
387
+ rev: v2.22.2
388
388
  hooks:
389
389
  - id: execsql-format
390
390
  ```
@@ -253,7 +253,7 @@ execsql-format --no-sql --in-place scripts/
253
253
  ```yaml
254
254
  repos:
255
255
  - repo: https://github.com/geocoug/execsql
256
- rev: v2.22.1
256
+ rev: v2.22.2
257
257
  hooks:
258
258
  - id: execsql-format
259
259
  ```
@@ -160,7 +160,7 @@ select id,name,created_at from users where active = true order by name;
160
160
  ```yaml
161
161
  repos:
162
162
  - repo: https://github.com/geocoug/execsql
163
- rev: v2.22.1
163
+ rev: v2.22.2
164
164
  hooks:
165
165
  - id: execsql-format
166
166
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "execsql2"
7
- version = "2.22.1"
7
+ version = "2.22.2"
8
8
  description = "Runs a SQL script against a PostgreSQL, SQLite, MariaDB/MySQL, DuckDB, Firebird, MS-Access, MS-SQL-Server, or Oracle database, or an ODBC DSN. Provides metacommands to import and export data, copy data between databases, conditionally execute SQL and metacommands, and dynamically alter SQL and metacommands with substitution variables."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = { file = "LICENSE.txt" }
@@ -178,7 +178,7 @@ skip-magic-trailing-comma = false
178
178
  line-ending = "auto"
179
179
 
180
180
  [tool.bumpversion]
181
- current_version = "2.22.1"
181
+ current_version = "2.22.2"
182
182
  commit = true
183
183
  tag = true
184
184
  tag_name = "v{new_version}"
@@ -540,18 +540,27 @@ def gui_credentials(
540
540
  # ---------------------------------------------------------------------------
541
541
 
542
542
 
543
- def get_yn(prompt: str) -> bool:
544
- """Prompt for a yes/no answer on the terminal."""
543
+ def get_yn(prompt: str) -> str:
544
+ """Prompt for a yes/no answer on the terminal.
545
+
546
+ Returns:
547
+ ``"y"`` or ``"n"``, or ``chr(27)`` (ESC) if the user aborts via EOF
548
+ (Ctrl-D / piped stdin closed). Matches the upstream v1.130.1
549
+ ``get_yn`` character contract expected by callers such as ``x_ask``.
550
+ """
545
551
  while True:
546
- answer = input(f"{prompt} [y/n]: ").strip().lower()
552
+ try:
553
+ answer = input(f"{prompt} [y/n]: ").strip().lower()
554
+ except EOFError:
555
+ return chr(27)
547
556
  if answer in ("y", "yes"):
548
- return True
557
+ return "y"
549
558
  if answer in ("n", "no"):
550
- return False
559
+ return "n"
551
560
  print("Please enter y or n.", file=sys.stderr)
552
561
 
553
562
 
554
- def get_yn_win(prompt: str) -> bool:
563
+ def get_yn_win(prompt: str) -> str:
555
564
  """GUI yes/no dialog — falls back to terminal in headless mode."""
556
565
  return get_yn(prompt)
557
566
 
@@ -786,27 +786,37 @@ class TestGuiPublicAPI:
786
786
  from execsql.utils.gui import get_yn
787
787
 
788
788
  monkeypatch.setattr("builtins.input", lambda *a: "y")
789
- assert get_yn("Continue?") is True
789
+ assert get_yn("Continue?") == "y"
790
790
 
791
791
  def test_get_yn_no(self, monkeypatch):
792
792
  from execsql.utils.gui import get_yn
793
793
 
794
794
  monkeypatch.setattr("builtins.input", lambda *a: "n")
795
- assert get_yn("Continue?") is False
795
+ assert get_yn("Continue?") == "n"
796
796
 
797
797
  def test_get_yn_full_words(self, monkeypatch):
798
798
  from execsql.utils.gui import get_yn
799
799
 
800
800
  inputs = iter(["yes"])
801
801
  monkeypatch.setattr("builtins.input", lambda *a: next(inputs))
802
- assert get_yn("?") is True
802
+ assert get_yn("?") == "y"
803
803
 
804
804
  def test_get_yn_retry_on_bad_input(self, monkeypatch):
805
805
  from execsql.utils.gui import get_yn
806
806
 
807
807
  inputs = iter(["maybe", "no"])
808
808
  monkeypatch.setattr("builtins.input", lambda *a: next(inputs))
809
- assert get_yn("?") is False
809
+ assert get_yn("?") == "n"
810
+
811
+ def test_get_yn_eof_returns_esc(self, monkeypatch):
812
+ """Ctrl-D / piped EOF is treated as the quit sentinel, matching upstream."""
813
+ from execsql.utils.gui import get_yn
814
+
815
+ def _raise_eof(*a):
816
+ raise EOFError
817
+
818
+ monkeypatch.setattr("builtins.input", _raise_eof)
819
+ assert get_yn("?") == chr(27)
810
820
 
811
821
  def test_gui_credentials_console_fallback(self, monkeypatch):
812
822
  """gui_credentials must not call auth.get_password (which needs
@@ -912,7 +922,7 @@ class TestGuiPublicAPI:
912
922
  from execsql.utils.gui import get_yn_win
913
923
 
914
924
  monkeypatch.setattr("builtins.input", lambda *a: "y")
915
- assert get_yn_win("?") is True
925
+ assert get_yn_win("?") == "y"
916
926
 
917
927
  def test_gui_console_on_off_updates_isrunning(self):
918
928
  """gui_console_on/off should be reflected by gui_console_isrunning()."""
@@ -499,6 +499,33 @@ class TestXAsk:
499
499
  os_mock.name = "posix"
500
500
  _prompt.x_ask(**self._kwargs())
501
501
 
502
+ def test_real_get_yn_yes_stores_yes(self, fake_state, monkeypatch) -> None:
503
+ """Regression: ASK ... SUB var must store "Yes" when the user answers y.
504
+
505
+ Exercises the real (unmocked) execsql.utils.gui.get_yn through x_ask,
506
+ driven by a patched builtins.input, instead of mocking get_yn itself.
507
+ This is what caught the bool-vs-char-contract regression where
508
+ get_yn() started returning True/False instead of "y"/"n"/chr(27),
509
+ making x_ask's `resp == "y"` comparison always false.
510
+ """
511
+ s = fake_state()
512
+ _state.gui_console = None
513
+ monkeypatch.setattr("builtins.input", lambda *a: "y")
514
+ with patch("execsql.metacommands.prompt.os") as os_mock:
515
+ os_mock.name = "posix"
516
+ _prompt.x_ask(**self._kwargs())
517
+ s.subvars.add_substitution.assert_called_with("ans", "Yes")
518
+
519
+ def test_real_get_yn_no_stores_no(self, fake_state, monkeypatch) -> None:
520
+ """Regression: ASK ... SUB var must store "No" when the user answers n."""
521
+ s = fake_state()
522
+ _state.gui_console = None
523
+ monkeypatch.setattr("builtins.input", lambda *a: "n")
524
+ with patch("execsql.metacommands.prompt.os") as os_mock:
525
+ os_mock.name = "posix"
526
+ _prompt.x_ask(**self._kwargs())
527
+ s.subvars.add_substitution.assert_called_with("ans", "No")
528
+
502
529
 
503
530
  # ---------------------------------------------------------------------------
504
531
  # x_pause
@@ -722,7 +722,7 @@ wheels = [
722
722
 
723
723
  [[package]]
724
724
  name = "execsql2"
725
- version = "2.22.1"
725
+ version = "2.22.2"
726
726
  source = { editable = "." }
727
727
  dependencies = [
728
728
  { name = "python-dateutil" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes