execsql2 2.16.14__tar.gz → 2.16.16__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 (324) hide show
  1. {execsql2-2.16.14 → execsql2-2.16.16}/.github/workflows/ci-cd.yml +23 -12
  2. {execsql2-2.16.14 → execsql2-2.16.16}/.pre-commit-config.yaml +1 -0
  3. {execsql2-2.16.14 → execsql2-2.16.16}/CHANGELOG.md +27 -0
  4. {execsql2-2.16.14 → execsql2-2.16.16}/PKG-INFO +1 -1
  5. {execsql2-2.16.14 → execsql2-2.16.16}/docs/about/divergence.md +15 -14
  6. {execsql2-2.16.14 → execsql2-2.16.16}/docs/reference/configuration.md +9 -0
  7. {execsql2-2.16.14 → execsql2-2.16.16}/docs/reference/metacommands.md +12 -20
  8. {execsql2-2.16.14 → execsql2-2.16.16}/docs/reference/security.md +30 -0
  9. {execsql2-2.16.14 → execsql2-2.16.16}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +1 -1
  10. {execsql2-2.16.14 → execsql2-2.16.16}/pyproject.toml +2 -2
  11. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/api.py +4 -0
  12. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/__init__.py +156 -134
  13. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/help.py +10 -1
  14. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/run.py +4 -0
  15. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/config.py +2 -0
  16. execsql2-2.16.16/src/execsql/data/execsql.conf.template +327 -0
  17. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/sqlite.py +47 -43
  18. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/format.py +0 -1
  19. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/debug.py +45 -41
  20. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/dispatch.py +2 -9
  21. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/system.py +10 -9
  22. execsql2-2.16.16/templates/execsql.conf +327 -0
  23. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_cli.py +24 -0
  24. {execsql2-2.16.14 → execsql2-2.16.16}/tests/conftest.py +2 -0
  25. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_extended.py +5 -3
  26. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_system.py +15 -4
  27. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_show_scripts.py +19 -9
  28. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_executor.py +16 -16
  29. execsql2-2.16.16/tests/utils/__init__.py +0 -0
  30. {execsql2-2.16.14 → execsql2-2.16.16}/uv.lock +1 -1
  31. execsql2-2.16.14/.github/PULL_REQUEST_TEMPLATE.md +0 -19
  32. execsql2-2.16.14/templates/execsql.conf +0 -287
  33. {execsql2-2.16.14 → execsql2-2.16.16}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  34. {execsql2-2.16.14 → execsql2-2.16.16}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  35. {execsql2-2.16.14 → execsql2-2.16.16}/.gitignore +0 -0
  36. {execsql2-2.16.14 → execsql2-2.16.16}/.pre-commit-hooks.yaml +0 -0
  37. {execsql2-2.16.14 → execsql2-2.16.16}/.python-version +0 -0
  38. {execsql2-2.16.14 → execsql2-2.16.16}/.readthedocs.yaml +0 -0
  39. {execsql2-2.16.14 → execsql2-2.16.16}/CONTRIBUTING.md +0 -0
  40. {execsql2-2.16.14 → execsql2-2.16.16}/LICENSE.txt +0 -0
  41. {execsql2-2.16.14 → execsql2-2.16.16}/NOTICE +0 -0
  42. {execsql2-2.16.14 → execsql2-2.16.16}/README.md +0 -0
  43. {execsql2-2.16.14 → execsql2-2.16.16}/SECURITY.md +0 -0
  44. {execsql2-2.16.14 → execsql2-2.16.16}/docs/about/contributors.md +0 -0
  45. {execsql2-2.16.14 → execsql2-2.16.16}/docs/about/copyright.md +0 -0
  46. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/cli.md +0 -0
  47. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/db.md +0 -0
  48. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/exporters.md +0 -0
  49. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/importers.md +0 -0
  50. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/index.md +0 -0
  51. {execsql2-2.16.14 → execsql2-2.16.16}/docs/api/metacommands.md +0 -0
  52. {execsql2-2.16.14 → execsql2-2.16.16}/docs/dev/adding_db_adapters.md +0 -0
  53. {execsql2-2.16.14 → execsql2-2.16.16}/docs/dev/adding_exporters.md +0 -0
  54. {execsql2-2.16.14 → execsql2-2.16.16}/docs/dev/adding_importers.md +0 -0
  55. {execsql2-2.16.14 → execsql2-2.16.16}/docs/dev/adding_metacommands.md +0 -0
  56. {execsql2-2.16.14 → execsql2-2.16.16}/docs/dev/architecture.md +0 -0
  57. {execsql2-2.16.14 → execsql2-2.16.16}/docs/getting-started/installation.md +0 -0
  58. {execsql2-2.16.14 → execsql2-2.16.16}/docs/getting-started/requirements.md +0 -0
  59. {execsql2-2.16.14 → execsql2-2.16.16}/docs/getting-started/syntax.md +0 -0
  60. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/debugging.md +0 -0
  61. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/documentation.md +0 -0
  62. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/encoding.md +0 -0
  63. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/examples.md +0 -0
  64. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/formatter.md +0 -0
  65. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/logging.md +0 -0
  66. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/sql_syntax.md +0 -0
  67. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/usage.md +0 -0
  68. {execsql2-2.16.14 → execsql2-2.16.16}/docs/guides/using_scripts.md +0 -0
  69. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/Compare_planets.png +0 -0
  70. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/actions.png +0 -0
  71. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/actions2.png +0 -0
  72. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/checkboxes.png +0 -0
  73. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/connect.b64 +0 -0
  74. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/connect.png +0 -0
  75. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/create_conf.png +0 -0
  76. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/data_error1_screenshot.jpg +0 -0
  77. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/entry_form.png +0 -0
  78. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/execsql_console.png +0 -0
  79. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/execsql_logo_01.png +0 -0
  80. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/fatals.png +0 -0
  81. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/logo_small.png +0 -0
  82. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/pause_terminal.png +0 -0
  83. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/pause_terminal_sm.b64 +0 -0
  84. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/pause_terminal_sm.png +0 -0
  85. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/prompt_compare.png +0 -0
  86. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/set_build_commands.jpg +0 -0
  87. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/unit_conversions.b64 +0 -0
  88. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/unit_conversions_029.png +0 -0
  89. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/unmatched.png +0 -0
  90. {execsql2-2.16.14 → execsql2-2.16.16}/docs/images/vim_execsql_highlight.png +0 -0
  91. {execsql2-2.16.14 → execsql2-2.16.16}/docs/index.md +0 -0
  92. {execsql2-2.16.14 → execsql2-2.16.16}/docs/reference/substitution_vars.md +0 -0
  93. {execsql2-2.16.14 → execsql2-2.16.16}/extras/plugin-template/README.md +0 -0
  94. {execsql2-2.16.14 → execsql2-2.16.16}/extras/plugin-template/pyproject.toml +0 -0
  95. {execsql2-2.16.14 → execsql2-2.16.16}/extras/plugin-template/src/execsql_plugin_YOURNAME/__init__.py +0 -0
  96. {execsql2-2.16.14 → execsql2-2.16.16}/extras/plugin-template/tests/test_plugin.py.example +0 -0
  97. {execsql2-2.16.14 → execsql2-2.16.16}/extras/vscode-execsql/README.md +0 -0
  98. {execsql2-2.16.14 → execsql2-2.16.16}/extras/vscode-execsql/package.json +0 -0
  99. {execsql2-2.16.14 → execsql2-2.16.16}/justfile +0 -0
  100. {execsql2-2.16.14 → execsql2-2.16.16}/scripts/generate_vscode_grammar.py +0 -0
  101. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/__init__.py +0 -0
  102. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/__main__.py +0 -0
  103. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/dsn.py +0 -0
  104. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/lint.py +0 -0
  105. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/cli/lint_ast.py +0 -0
  106. {execsql2-2.16.14/tests → execsql2-2.16.16/src/execsql/data}/__init__.py +0 -0
  107. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/__init__.py +0 -0
  108. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/access.py +0 -0
  109. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/base.py +0 -0
  110. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/dsn.py +0 -0
  111. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/duckdb.py +0 -0
  112. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/factory.py +0 -0
  113. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/firebird.py +0 -0
  114. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/mysql.py +0 -0
  115. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/oracle.py +0 -0
  116. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/postgres.py +0 -0
  117. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/db/sqlserver.py +0 -0
  118. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/debug/__init__.py +0 -0
  119. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/debug/repl.py +0 -0
  120. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exceptions.py +0 -0
  121. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/__init__.py +0 -0
  122. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/base.py +0 -0
  123. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/delimited.py +0 -0
  124. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/duckdb.py +0 -0
  125. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/feather.py +0 -0
  126. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/html.py +0 -0
  127. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/json.py +0 -0
  128. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/latex.py +0 -0
  129. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/markdown.py +0 -0
  130. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/ods.py +0 -0
  131. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/parquet.py +0 -0
  132. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/pretty.py +0 -0
  133. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/protocol.py +0 -0
  134. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/raw.py +0 -0
  135. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/sqlite.py +0 -0
  136. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/templates.py +0 -0
  137. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/values.py +0 -0
  138. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/xls.py +0 -0
  139. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/xlsx.py +0 -0
  140. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/xml.py +0 -0
  141. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/yaml.py +0 -0
  142. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/exporters/zip.py +0 -0
  143. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/gui/__init__.py +0 -0
  144. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/gui/base.py +0 -0
  145. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/gui/console.py +0 -0
  146. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/gui/desktop.py +0 -0
  147. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/gui/tui.py +0 -0
  148. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/__init__.py +0 -0
  149. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/base.py +0 -0
  150. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/csv.py +0 -0
  151. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/feather.py +0 -0
  152. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/json.py +0 -0
  153. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/ods.py +0 -0
  154. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/importers/xls.py +0 -0
  155. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/__init__.py +0 -0
  156. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/conditions.py +0 -0
  157. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/connect.py +0 -0
  158. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/control.py +0 -0
  159. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/data.py +0 -0
  160. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/io.py +0 -0
  161. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/io_export.py +0 -0
  162. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/io_fileops.py +0 -0
  163. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/io_import.py +0 -0
  164. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/io_write.py +0 -0
  165. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/prompt.py +0 -0
  166. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/script_ext.py +0 -0
  167. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/metacommands/upsert.py +0 -0
  168. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/models.py +0 -0
  169. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/parser.py +0 -0
  170. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/plugins.py +0 -0
  171. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/py.typed +0 -0
  172. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/__init__.py +0 -0
  173. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/ast.py +0 -0
  174. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/control.py +0 -0
  175. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/engine.py +0 -0
  176. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/executor.py +0 -0
  177. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/parser.py +0 -0
  178. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/script/variables.py +0 -0
  179. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/state.py +0 -0
  180. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/types.py +0 -0
  181. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/__init__.py +0 -0
  182. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/auth.py +0 -0
  183. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/crypto.py +0 -0
  184. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/datetime.py +0 -0
  185. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/errors.py +0 -0
  186. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/fileio.py +0 -0
  187. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/gui.py +0 -0
  188. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/mail.py +0 -0
  189. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/numeric.py +0 -0
  190. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/regex.py +0 -0
  191. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/strings.py +0 -0
  192. {execsql2-2.16.14 → execsql2-2.16.16}/src/execsql/utils/timer.py +0 -0
  193. {execsql2-2.16.14 → execsql2-2.16.16}/templates/README.md +0 -0
  194. {execsql2-2.16.14 → execsql2-2.16.16}/templates/config_settings.sqlite +0 -0
  195. {execsql2-2.16.14 → execsql2-2.16.16}/templates/example_config_prompt.sql +0 -0
  196. {execsql2-2.16.14 → execsql2-2.16.16}/templates/make_config_db.sql +0 -0
  197. {execsql2-2.16.14 → execsql2-2.16.16}/templates/md_compare.sql +0 -0
  198. {execsql2-2.16.14 → execsql2-2.16.16}/templates/md_glossary.sql +0 -0
  199. {execsql2-2.16.14 → execsql2-2.16.16}/templates/md_upsert.sql +0 -0
  200. {execsql2-2.16.14 → execsql2-2.16.16}/templates/pg_compare.sql +0 -0
  201. {execsql2-2.16.14 → execsql2-2.16.16}/templates/pg_glossary.sql +0 -0
  202. {execsql2-2.16.14 → execsql2-2.16.16}/templates/pg_upsert.sql +0 -0
  203. {execsql2-2.16.14 → execsql2-2.16.16}/templates/script_template.sql +0 -0
  204. {execsql2-2.16.14 → execsql2-2.16.16}/templates/ss_compare.sql +0 -0
  205. {execsql2-2.16.14 → execsql2-2.16.16}/templates/ss_glossary.sql +0 -0
  206. {execsql2-2.16.14 → execsql2-2.16.16}/templates/ss_upsert.sql +0 -0
  207. {execsql2-2.16.14/tests/cli → execsql2-2.16.16/tests}/__init__.py +0 -0
  208. {execsql2-2.16.14/tests/db → execsql2-2.16.16/tests/cli}/__init__.py +0 -0
  209. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_cli_e2e.py +0 -0
  210. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_cli_run.py +0 -0
  211. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_lint.py +0 -0
  212. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_ping.py +0 -0
  213. {execsql2-2.16.14 → execsql2-2.16.16}/tests/cli/test_profile.py +0 -0
  214. {execsql2-2.16.14/tests/exporters → execsql2-2.16.16/tests/db}/__init__.py +0 -0
  215. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_base.py +0 -0
  216. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_db_adapters_mocked.py +0 -0
  217. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_dsn.py +0 -0
  218. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_duckdb.py +0 -0
  219. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_factory.py +0 -0
  220. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_postgres.py +0 -0
  221. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_sqlite.py +0 -0
  222. {execsql2-2.16.14 → execsql2-2.16.16}/tests/db/test_sqlite_extra.py +0 -0
  223. {execsql2-2.16.14/tests/gui → execsql2-2.16.16/tests/exporters}/__init__.py +0 -0
  224. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_base.py +0 -0
  225. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_db.py +0 -0
  226. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_delimited.py +0 -0
  227. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_duckdb_exporter.py +0 -0
  228. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_exporters.py +0 -0
  229. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_feather.py +0 -0
  230. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_html_extended.py +0 -0
  231. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_html_latex.py +0 -0
  232. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_json.py +0 -0
  233. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_json_extended.py +0 -0
  234. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_latex_extended.py +0 -0
  235. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_markdown.py +0 -0
  236. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_ods.py +0 -0
  237. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_parquet.py +0 -0
  238. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_pretty_extended.py +0 -0
  239. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_raw_extended.py +0 -0
  240. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_sqlite_exporter.py +0 -0
  241. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_templates.py +0 -0
  242. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_templates_extended.py +0 -0
  243. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_values_extended.py +0 -0
  244. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_xls_xlsx.py +0 -0
  245. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_xlsx.py +0 -0
  246. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_xml.py +0 -0
  247. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_yaml.py +0 -0
  248. {execsql2-2.16.14 → execsql2-2.16.16}/tests/exporters/test_zip.py +0 -0
  249. {execsql2-2.16.14/tests/importers → execsql2-2.16.16/tests/gui}/__init__.py +0 -0
  250. {execsql2-2.16.14 → execsql2-2.16.16}/tests/gui/test_backends.py +0 -0
  251. {execsql2-2.16.14 → execsql2-2.16.16}/tests/gui/test_compare_stats.py +0 -0
  252. {execsql2-2.16.14 → execsql2-2.16.16}/tests/gui/test_compute_row_diffs.py +0 -0
  253. {execsql2-2.16.14/tests/integration → execsql2-2.16.16/tests/importers}/__init__.py +0 -0
  254. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_base_extended.py +0 -0
  255. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_csv_edge_cases.py +0 -0
  256. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_csv_importer.py +0 -0
  257. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_feather_importer.py +0 -0
  258. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_json_importer.py +0 -0
  259. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_ods_importer.py +0 -0
  260. {execsql2-2.16.14 → execsql2-2.16.16}/tests/importers/test_xls_importer.py +0 -0
  261. {execsql2-2.16.14/tests/metacommands → execsql2-2.16.16/tests/integration}/__init__.py +0 -0
  262. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/conftest.py +0 -0
  263. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/test_dsn.py +0 -0
  264. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/test_duckdb.py +0 -0
  265. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/test_mysql.py +0 -0
  266. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/test_postgres.py +0 -0
  267. {execsql2-2.16.14 → execsql2-2.16.16}/tests/integration/test_sqlite.py +0 -0
  268. {execsql2-2.16.14/tests/scripts → execsql2-2.16.16/tests/metacommands}/__init__.py +0 -0
  269. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_assert.py +0 -0
  270. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_breakpoint.py +0 -0
  271. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_connect.py +0 -0
  272. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_io_export.py +0 -0
  273. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_io_import.py +0 -0
  274. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands.py +0 -0
  275. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_connect.py +0 -0
  276. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_data.py +0 -0
  277. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
  278. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_io.py +0 -0
  279. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
  280. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_script_ext.py +0 -0
  281. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_metacommands_system_extra.py +0 -0
  282. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_pg_upsert.py +0 -0
  283. {execsql2-2.16.14 → execsql2-2.16.16}/tests/metacommands/test_row_count.py +0 -0
  284. {execsql2-2.16.14/tests/utils → execsql2-2.16.16/tests/scripts}/__init__.py +0 -0
  285. {execsql2-2.16.14 → execsql2-2.16.16}/tests/scripts/fixtures/control_flow.sql +0 -0
  286. {execsql2-2.16.14 → execsql2-2.16.16}/tests/scripts/fixtures/io_roundtrip.sql +0 -0
  287. {execsql2-2.16.14 → execsql2-2.16.16}/tests/scripts/fixtures/parse_only/parse_tree.sql +0 -0
  288. {execsql2-2.16.14 → execsql2-2.16.16}/tests/scripts/fixtures/smoke.sql +0 -0
  289. {execsql2-2.16.14 → execsql2-2.16.16}/tests/scripts/test_sql_scripts.py +0 -0
  290. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_api.py +0 -0
  291. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_ast.py +0 -0
  292. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_ast_parser.py +0 -0
  293. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_config.py +0 -0
  294. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_config_data.py +0 -0
  295. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_config_extended.py +0 -0
  296. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_debug_repl.py +0 -0
  297. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_engine.py +0 -0
  298. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_error_messages.py +0 -0
  299. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_exceptions.py +0 -0
  300. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_format.py +0 -0
  301. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_mail.py +0 -0
  302. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_models.py +0 -0
  303. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_package.py +0 -0
  304. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_parser.py +0 -0
  305. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_parser_params.py +0 -0
  306. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_plugins.py +0 -0
  307. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_registry.py +0 -0
  308. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_script.py +0 -0
  309. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_state.py +0 -0
  310. {execsql2-2.16.14 → execsql2-2.16.16}/tests/test_types.py +0 -0
  311. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_auth.py +0 -0
  312. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_auth_extra.py +0 -0
  313. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_crypto.py +0 -0
  314. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_datetime.py +0 -0
  315. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_errors.py +0 -0
  316. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_errors_extra.py +0 -0
  317. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_fileio.py +0 -0
  318. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_fileio_extra.py +0 -0
  319. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_numeric.py +0 -0
  320. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_regex.py +0 -0
  321. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_strings.py +0 -0
  322. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_timer.py +0 -0
  323. {execsql2-2.16.14 → execsql2-2.16.16}/tests/utils/test_timer_extra.py +0 -0
  324. {execsql2-2.16.14 → execsql2-2.16.16}/zensical.toml +0 -0
@@ -14,6 +14,20 @@ concurrency:
14
14
  cancel-in-progress: true
15
15
 
16
16
  jobs:
17
+ lint:
18
+ name: lint
19
+ runs-on: ubuntu-latest
20
+ permissions:
21
+ contents: read
22
+ steps:
23
+ - uses: actions/checkout@v6
24
+ - uses: actions/setup-python@v6
25
+ with:
26
+ python-version: "3.13"
27
+ - run: python -m pip install ruff
28
+ - run: ruff check src/ tests/
29
+ - run: ruff format --check src/ tests/
30
+
17
31
  tests:
18
32
  strategy:
19
33
  fail-fast: false
@@ -43,7 +57,8 @@ jobs:
43
57
  uses: actions/cache@v5
44
58
  with:
45
59
  path: ~/.cache/pip
46
- key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
60
+ key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{
61
+ hashFiles('**/pyproject.toml') }}
47
62
  restore-keys: |
48
63
  ${{ runner.os }}-pip-${{ matrix.python-version }}-
49
64
  - name: Install dependencies
@@ -86,10 +101,8 @@ jobs:
86
101
  ports:
87
102
  - 5432:5432
88
103
  options: >-
89
- --health-cmd pg_isready
90
- --health-interval 10s
91
- --health-timeout 5s
92
- --health-retries 5
104
+ --health-cmd pg_isready --health-interval 10s
105
+ --health-timeout 5s --health-retries 5
93
106
  mysql:
94
107
  image: mysql:8
95
108
  env:
@@ -100,10 +113,8 @@ jobs:
100
113
  ports:
101
114
  - 3306:3306
102
115
  options: >-
103
- --health-cmd "mysqladmin ping"
104
- --health-interval 10s
105
- --health-timeout 5s
106
- --health-retries 5
116
+ --health-cmd "mysqladmin ping" --health-interval 10s
117
+ --health-timeout 5s --health-retries 5
107
118
  steps:
108
119
  - name: Check out repository code
109
120
  uses: actions/checkout@v6
@@ -122,7 +133,7 @@ jobs:
122
133
  build:
123
134
  name: Build distribution 📦
124
135
  runs-on: ubuntu-latest
125
- needs: [tests, integration-tests]
136
+ needs: [ lint, tests, integration-tests ]
126
137
  if: startsWith(github.ref, 'refs/tags/v')
127
138
  permissions:
128
139
  contents: read
@@ -147,7 +158,7 @@ jobs:
147
158
 
148
159
  publish:
149
160
  name: PyPI Publish 🚀
150
- needs: [build]
161
+ needs: [ build ]
151
162
  if: startsWith(github.ref, 'refs/tags/v')
152
163
  runs-on: ubuntu-latest
153
164
  environment:
@@ -170,7 +181,7 @@ jobs:
170
181
 
171
182
  generate-release:
172
183
  name: Generate GitHub Release
173
- needs: [build]
184
+ needs: [ build ]
174
185
  if: startsWith(github.ref, 'refs/tags/v')
175
186
  runs-on: ubuntu-latest
176
187
  permissions:
@@ -48,6 +48,7 @@ repos:
48
48
  exclude: |
49
49
  (?x)^(
50
50
  \.claude/.*|
51
+ AUDIT\.md|
51
52
  docs/api/.*|
52
53
  docs/reference/metacommands\.md|
53
54
  docs/guides/documentation\.md|
@@ -13,6 +13,33 @@ ______________________________________________________________________
13
13
 
14
14
  ______________________________________________________________________
15
15
 
16
+ ## [2.16.16] - 2026-05-02
17
+
18
+ ### Added
19
+
20
+ - `--init-config` CLI flag to print a default `execsql.conf` template (with all options commented out and documented) to stdout. Use `execsql --init-config > execsql.conf` to bootstrap a configuration file.
21
+ - `--no-system-cmd` CLI flag to disable SYSTEM_CMD/SHELL metacommand execution. Scripts that use SHELL will fail with a clear error when this flag is active. Also configurable via `allow_system_cmd = No` in `execsql.conf` `[config]` section. The library API exposes the same control via `allow_system_cmd=False`.
22
+
23
+ ### Changed
24
+
25
+ - CLI `--help` output now logically groups related options: connection, encoding, import/export, execution, GUI, configuration, and information.
26
+ - SYSTEM_CMD now uses `subprocess.run()` instead of the deprecated `subprocess.call()`.
27
+ - `execsql.conf` template updated: added missing options (`use_keyring`, `gui_framework`, `allow_system_cmd`, `log_sql`, `max_log_size_mb`, `show_progress`, `import_progress_interval`, `macos_config_file`), fixed incorrect defaults (`password_prompt`, `new_db`, `scan_lines`), added DuckDB (`k`) to database types, modernized all comments.
28
+
29
+ ### Fixed
30
+
31
+ - SYSTEM_CMD no longer wraps arguments containing `&` in spurious double quotes. The previous behavior (a Windows `cmd.exe` workaround inherited from the upstream monolith) injected literal `"` characters into subprocess arguments, which could cause commands to fail or behave unexpectedly on non-`cmd.exe` targets.
32
+
33
+ ______________________________________________________________________
34
+
35
+ ## [2.16.15] - 2026-05-02
36
+
37
+ ### Changed
38
+
39
+ - Merged `SHOW SCRIPTS` and `SHOW SCRIPT <name>` into a single `SHOW SCRIPTS [<name>]` metacommand. Without a name, lists all registered scripts; with a name, shows detail for that script.
40
+
41
+ ______________________________________________________________________
42
+
16
43
  ## [2.16.14] - 2026-05-01
17
44
 
18
45
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: execsql2
3
- Version: 2.16.14
3
+ Version: 2.16.16
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
@@ -31,6 +31,8 @@ ______________________________________________________________________
31
31
  | `--lint` | Parse the script and perform static analysis without connecting to a database. Reports unmatched IF/ENDIF, LOOP/END LOOP, and BEGIN BATCH/END BATCH blocks (errors); potentially undefined `!!$VAR!!` references (warnings); missing INCLUDE file targets (warnings); and unknown `EXECUTE SCRIPT` targets (warnings). Variable analysis uses two passes so definition order does not matter. The linter descends into named script blocks reached via `EXECUTE SCRIPT` / `EXEC SCRIPT` / `RUN SCRIPT`, reads `SUB_INI` INI files at lint time, recognizes `SUB_EMPTY` / `SUB_ADD` / `SUB_APPEND` / `SUBDATA` as definitions, suppresses false warnings for `$COUNTER_N`, and auto-discovers built-in system variables from the installed source. Exits 0 if no errors, 1 if errors found. |
32
32
  | `--parse-tree` | Parse the script into an Abstract Syntax Tree and print a visual tree showing block nesting (IF/LOOP/BATCH/SCRIPT), source line ranges, compound conditions (ANDIF/ORIF), and all metacommands. Does not connect to a database or execute anything. Useful for understanding script structure and verifying the parser handles a script correctly. |
33
33
  | `--list-plugins` | List all discovered plugins (metacommands, exporters, importers) from Python entry points and exit. Plugins extend execsql via `execsql.metacommands`, `execsql.exporters`, and `execsql.importers` entry point groups. |
34
+ | `--no-system-cmd` | Disable the `SYSTEM_CMD` (SHELL) metacommand. Scripts that use SHELL will fail with a clear error. Also configurable via `allow_system_cmd = No` in `execsql.conf` `[config]` section, or `allow_system_cmd=False` in the library API. |
35
+ | `--init-config` | Print a default `execsql.conf` template to stdout with all options commented out and documented. Redirect to a file to bootstrap a configuration: `execsql --init-config > execsql.conf`. |
34
36
 
35
37
  ### Export Formats
36
38
 
@@ -44,23 +46,22 @@ ______________________________________________________________________
44
46
 
45
47
  ### Metacommands
46
48
 
47
- | Metacommand | Description |
48
- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
49
- | `ASSERT` | Evaluate a condition and raise an error (halting the script) if it is false. Supports all IF conditions. Optional quoted failure message. Skipped in false IF blocks. |
50
- | `BREAKPOINT` | Pause script execution and drop into an interactive debug REPL. See [Debugging](#debugging) below for full details. |
51
- | `CONFIG SHOW_PROGRESS` | Enable the Rich progress bar for IMPORT operations at runtime. |
52
- | `CONFIG LOG_SQL` | Enable SQL query audit logging — writes executed SQL to the log file. |
53
- | `PG_UPSERT` | QA-checked, FK-dependency-ordered upserts from staging to base schema on PostgreSQL. Integrates [pg-upsert](https://pg-upsert.readthedocs.io/) as an optional dependency. Three modes: full pipeline, QA-only, and schema check. Supports `EXPORT_FAILURES`, `EXPORT_FORMAT`, `EXPORT_MAX_ROWS`, and `STRICT_COLUMNS` keywords. `STRICT_COLUMNS` forces all missing columns to be errors (requires `pg-upsert>=1.22.0`). |
54
- | `IMPORT … FROM JSON` | Import a JSON file (array of objects or NDJSON) into a database table. Nested objects are flattened with dot-separated column names; arrays are stored as JSON strings. |
55
- | `SHOW SCRIPTS` | List all registered SCRIPT definitions with parameter signatures and source locations. Includes scripts from INCLUDEEd files. |
56
- | `SHOW SCRIPT <name>` | Show detail for a single registered SCRIPT: name, parameters (with defaults), source file/line range, and docstring. |
49
+ | Metacommand | Description |
50
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
51
+ | `ASSERT` | Evaluate a condition and raise an error (halting the script) if it is false. Supports all IF conditions. Optional quoted failure message. Skipped in false IF blocks. |
52
+ | `BREAKPOINT` | Pause script execution and drop into an interactive debug REPL. See [Debugging](#debugging) below for full details. |
53
+ | `CONFIG SHOW_PROGRESS` | Enable the Rich progress bar for IMPORT operations at runtime. |
54
+ | `CONFIG LOG_SQL` | Enable SQL query audit logging — writes executed SQL to the log file. |
55
+ | `PG_UPSERT` | QA-checked, FK-dependency-ordered upserts from staging to base schema on PostgreSQL. Integrates [pg-upsert](https://pg-upsert.readthedocs.io/) as an optional dependency. Three modes: full pipeline, QA-only, and schema check. Supports `EXPORT_FAILURES`, `EXPORT_FORMAT`, `EXPORT_MAX_ROWS`, and `STRICT_COLUMNS` keywords. `STRICT_COLUMNS` forces all missing columns to be errors (requires `pg-upsert>=1.22.0`). |
56
+ | `IMPORT … FROM JSON` | Import a JSON file (array of objects or NDJSON) into a database table. Nested objects are flattened with dot-separated column names; arrays are stored as JSON strings. |
57
+ | `SHOW SCRIPTS [<name>]` | Without a name, lists all registered SCRIPT definitions with parameter signatures and source locations. With a name, shows detail including parameters (with defaults), source file/line range, and docstring. |
57
58
 
58
59
  ### SCRIPT Enhancements
59
60
 
60
- | Feature | Description |
61
- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
62
- | Default parameters | `BEGIN SCRIPT load(schema, table, batch=1000)` — parameters with defaults can be omitted at call site. Required parameters must precede optional parameters. |
63
- | Docstrings | Comments (`--` or `/* */`) immediately following `BEGIN SCRIPT` are captured as documentation. A blank line terminates the docstring. Displayed by `SHOW SCRIPT`, `SHOW SCRIPTS`, and `.scripts` REPL command. |
61
+ | Feature | Description |
62
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
63
+ | Default parameters | `BEGIN SCRIPT load(schema, table, batch=1000)` — parameters with defaults can be omitted at call site. Required parameters must precede optional parameters. |
64
+ | Docstrings | Comments (`--` or `/* */`) immediately following `BEGIN SCRIPT` are captured as documentation. A blank line terminates the docstring. Displayed by `SHOW SCRIPTS <name>` and `.scripts <name>` REPL command. |
64
65
 
65
66
  ### Bug Fixes
66
67
 
@@ -15,6 +15,12 @@ Configuration data is read from these files in the order listed above. Informati
15
15
 
16
16
  An explicit configuration file can also be specified with the `--config FILE` command-line option. This file is loaded **after** all four implicit search paths, so its values take precedence over system, user, script-directory, and working-directory config files. CLI arguments still override everything. The `--config` file may chain additional configs via its `[config]` section, just like any other config file.
17
17
 
18
+ To generate a starter configuration file with all options commented out and documented, use:
19
+
20
+ ```bash
21
+ execsql --init-config > execsql.conf
22
+ ```
23
+
18
24
  In addition, *execsql* will read additional configuration files if they are specified in any of the standard configuration files ([see below](#config_config)).
19
25
 
20
26
  Configuration files use the [INI](https://en.wikipedia.org/wiki/INI_file) file format. Section names are case sensitive and must be all in lowercase. Property names are not case sensitive. Property values are read as-is and may or may not be case sensitive, depending on their use. Comments can be included in configuration files; each comment line must start with the "#" character.
@@ -329,6 +335,9 @@ The section and property names that may be used in a configuration file are list
329
335
  `max_log_size_mb` { #max_log_size_mb }
330
336
  : Maximum size of the log file in megabytes before it is rotated. When set to a positive integer, the log file is rotated to `.1` before a new run appends to it if the file size exceeds the configured threshold. The default is `0` (disabled — no rotation).
331
337
 
338
+ `allow_system_cmd` { #allow_system_cmd }
339
+ : When set to "No", the `SYSTEM_CMD` (SHELL) metacommand is disabled. Any script that attempts to execute an OS command will fail with an error. The default is "Yes". This can also be set via the `--no-system-cmd` CLI flag or `allow_system_cmd=False` in the library API. See [Security — Disabling SYSTEM_CMD](security.md#disable_system_cmd) for details.
340
+
332
341
  `log_datavars` { #conf_log_datavars }
333
342
  : A value of 'Yes' or 'No' to control whether data variables that are created by the [SELECT_SUB](metacommands.md#select_sub), [PROMPT SELECT_SUB](metacommands.md#prompt_selsub) and [PROMPT ACTION](metacommands.md#prompt_action) metacommands are written to *execsql*'s [log file](../guides/logging.md#logging). By default, this is set to 'Yes', so that all data variable assignments are logged. The performance of scripts that make extensive use of these metacommands (e.g., [Example 27](../guides/examples.md#example27)) can be improved by setting this to 'No'.
334
343
 
@@ -2767,12 +2767,18 @@ The numeric expression may consist of the simple algebraic operations of additio
2767
2767
  ## SHOW SCRIPTS { #show_scripts }
2768
2768
 
2769
2769
  ```
2770
- SHOW SCRIPTS
2770
+ SHOW SCRIPTS [<name>]
2771
2771
  ```
2772
2772
 
2773
- Lists all registered SCRIPT definitions with their parameter signatures and source locations. This is useful for discovering what scripts are available at runtime, especially when scripts are loaded from INCLUDEEd files whose paths are determined dynamically.
2773
+ Without a name, lists all registered SCRIPT definitions with their parameter signatures and source locations. With a name, shows detail for that script including parameters, source file/line range, and docstring.
2774
2774
 
2775
- **Example output:**
2775
+ This is useful for discovering what scripts are available at runtime, especially when scripts are loaded from INCLUDEEd files whose paths are determined dynamically.
2776
+
2777
+ **List all scripts:**
2778
+
2779
+ ```sql
2780
+ -- !x! SHOW SCRIPTS
2781
+ ```
2776
2782
 
2777
2783
  ```
2778
2784
  Registered scripts (3):
@@ -2782,26 +2788,12 @@ Registered scripts (3):
2782
2788
  validate(schema, table) pipeline.sql:62-80
2783
2789
  ```
2784
2790
 
2785
- Default parameter values are shown in the signature. Use `SHOW SCRIPT <name>` for full detail including docstrings.
2786
-
2787
- If no scripts are registered, prints `No scripts registered.`
2788
-
2789
- ## SHOW SCRIPT { #show_script }
2790
-
2791
- ```
2792
- SHOW SCRIPT <name>
2793
- ```
2794
-
2795
- Shows detail for a single registered SCRIPT definition, including its parameter list (with required/optional status and defaults), source file/line range, and docstring.
2796
-
2797
- **Example:**
2791
+ **Show detail for one script:**
2798
2792
 
2799
2793
  ```sql
2800
- -- !x! SHOW SCRIPT load_data
2794
+ -- !x! SHOW SCRIPTS load_data
2801
2795
  ```
2802
2796
 
2803
- **Example output:**
2804
-
2805
2797
  ```
2806
2798
  Script: load_data(schema, table, batch_size=1000)
2807
2799
  Source: pipeline.sql:15-42
@@ -2813,7 +2805,7 @@ Parameters:
2813
2805
  Load data from staging into the target table.
2814
2806
  ```
2815
2807
 
2816
- If the script is not found, prints `No script named '<name>' is registered.`
2808
+ If no scripts are registered, prints `No scripts registered.` If the named script is not found, prints `No script named '<name>' is registered.`
2817
2809
 
2818
2810
  !!! tip
2819
2811
  In the debug REPL, use `.scripts` to list all scripts or `.scripts <name>` to show detail for one script.
@@ -21,6 +21,36 @@ Variable substitution is applied to the command string before execution, so any
21
21
 
22
22
  If `outdir` is derived from user input, validate or sanitize it before use in a `SYSTEM_CMD` command.
23
23
 
24
+ !!! note "Windows `.bat`/`.cmd` files"
25
+
26
+ On Windows, when the target of a `SYSTEM_CMD` is a `.bat` or `.cmd` file, Windows may invoke `cmd.exe` to interpret it. In this case, the `&` character in arguments can be interpreted as a command separator by `cmd.exe`, even though the subprocess is not launched with `shell=True`. Avoid passing untrusted data containing `&` to batch files on Windows.
27
+
28
+ ### Disabling SYSTEM_CMD { #disable_system_cmd }
29
+
30
+ To prevent scripts from executing OS commands entirely, use the `--no-system-cmd` CLI flag:
31
+
32
+ ```bash
33
+ execsql --no-system-cmd script.sql mydb
34
+ ```
35
+
36
+ Any script that uses `SYSTEM_CMD` or `SHELL` will fail with an error. This is useful for CI pipelines, shared execution environments, or running semi-trusted scripts where shell access is not appropriate.
37
+
38
+ The same restriction can be set permanently in `execsql.conf`:
39
+
40
+ ```ini
41
+ [config]
42
+ allow_system_cmd = No
43
+ ```
44
+
45
+ The library API provides the same control:
46
+
47
+ ```python
48
+ import execsql
49
+ result = execsql.run("script.sql", dsn="sqlite:///my.db", allow_system_cmd=False)
50
+ ```
51
+
52
+ The `--no-system-cmd` CLI flag always takes precedence — if the flag is passed, `SYSTEM_CMD` is disabled regardless of the config file setting.
53
+
24
54
  ## Credential Handling { #credentials }
25
55
 
26
56
  ### Interactive password prompts
@@ -93,7 +93,7 @@
93
93
  },
94
94
  "action-keywords": {
95
95
  "comment": "sub, write, execute script, export, etc.",
96
- "match": "(?i)\\b(reset\\s+dialog_canceled|write\\s+create_table|export_metadata|pg_upsert\\s+check|sub_querystring|execute\\s+script|append\\s+script|extend\\s+script|reset\\s+counter|export\\s+query|pg_upsert\\s+qa|show\\s+scripts|sub_tempfile|write\\s+script|import_file|set\\s+counter|show\\s+script|sub_decrypt|sub_encrypt|autocommit|breakpoint|copy\\s+query|disconnect|select_sub|sub_append|system_cmd|pg_upsert|pg_vacuum|sub_empty|sub_local|connect|include|max_int|rm_file|subdata|sub_add|sub_ini|assert|export|import|rm_sub|debug|email|serve|write|copy|log|run|sub|use|zip|cd)\\b",
96
+ "match": "(?i)\\b(reset\\s+dialog_canceled|write\\s+create_table|export_metadata|pg_upsert\\s+check|sub_querystring|execute\\s+script|append\\s+script|extend\\s+script|reset\\s+counter|export\\s+query|pg_upsert\\s+qa|show\\s+scripts|sub_tempfile|write\\s+script|import_file|set\\s+counter|sub_decrypt|sub_encrypt|autocommit|breakpoint|copy\\s+query|disconnect|select_sub|sub_append|system_cmd|pg_upsert|pg_vacuum|sub_empty|sub_local|connect|include|max_int|rm_file|subdata|sub_add|sub_ini|assert|export|import|rm_sub|debug|email|serve|write|copy|log|run|sub|use|zip|cd)\\b",
97
97
  "name": "keyword.other.execsql"
98
98
  },
99
99
  "config-event-keywords": {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "execsql2"
7
- version = "2.16.14"
7
+ version = "2.16.16"
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" }
@@ -165,7 +165,7 @@ skip-magic-trailing-comma = false
165
165
  line-ending = "auto"
166
166
 
167
167
  [tool.bumpversion]
168
- current_version = "2.16.14"
168
+ current_version = "2.16.16"
169
169
  commit = true
170
170
  tag = true
171
171
  tag_name = "v{new_version}"
@@ -316,6 +316,7 @@ def run(
316
316
  encoding: str = "utf-8",
317
317
  halt_on_error: bool = True,
318
318
  new_db: bool = False,
319
+ allow_system_cmd: bool = True,
319
320
  ) -> ScriptResult:
320
321
  """Execute a SQL script and return the result.
321
322
 
@@ -337,6 +338,8 @@ def run(
337
338
  error. If ``False``, capture errors and continue.
338
339
  new_db: If ``True``, create the database if it does not exist
339
340
  (SQLite, PostgreSQL, DuckDB).
341
+ allow_system_cmd: If ``False``, the SYSTEM_CMD (SHELL) metacommand
342
+ is disabled and will raise an error if encountered.
340
343
 
341
344
  Returns:
342
345
  A :class:`ScriptResult` with execution outcome, timing, errors,
@@ -434,6 +437,7 @@ def run(
434
437
  ctx.subvars = subvars
435
438
  ctx.status = StatObj()
436
439
  ctx.status.halt_on_err = halt_on_error
440
+ conf.allow_system_cmd = allow_system_cmd
437
441
  ctx.conf = conf
438
442
 
439
443
  # Capture output to a buffer (suppress stdout/stderr)