execsql2 2.11.0__tar.gz → 2.11.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.
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/project_context.md +24 -8
- {execsql2-2.11.0 → execsql2-2.11.1}/CHANGELOG.md +22 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/PKG-INFO +5 -2
- {execsql2-2.11.0 → execsql2-2.11.1}/README.md +4 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/about/divergence.md +1 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/pyproject.toml +2 -2
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/cli/lint.py +1 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/cli/run.py +3 -2
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/xlsx.py +5 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/yaml.py +2 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/control.py +4 -10
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/debug.py +1 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/debug_repl.py +4 -3
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/script/engine.py +13 -3
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/state.py +2 -2
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/gui.py +26 -4
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_extended.py +1 -3
- {execsql2-2.11.0 → execsql2-2.11.1}/uv.lock +1 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/dba.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/herald.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/inspector.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/oracle.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/patcher.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/qa.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/agents/scribe.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/code-oracle.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/migrate.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/review-changes.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/test-module.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/update-changelog.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/commands/where-is.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.claude/state/status.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.github/workflows/ci-cd.yml +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.gitignore +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.pre-commit-config.yaml +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.pre-commit-hooks.yaml +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.python-version +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/.readthedocs.yaml +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/CLAUDE.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/CONTRIBUTING.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/LICENSE.txt +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/NOTICE +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/SECURITY.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/about/contributors.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/about/copyright.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/cli.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/db.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/exporters.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/importers.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/index.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/api/metacommands.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/dev/adding_db_adapters.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/dev/adding_exporters.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/dev/adding_importers.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/dev/adding_metacommands.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/dev/architecture.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/getting-started/installation.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/getting-started/requirements.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/getting-started/syntax.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/debugging.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/documentation.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/encoding.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/examples.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/formatter.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/logging.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/sql_syntax.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/usage.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/guides/using_scripts.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/Compare_planets.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/actions.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/actions2.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/checkboxes.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/connect.b64 +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/connect.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/create_conf.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/data_error1_screenshot.jpg +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/entry_form.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/execsql_console.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/execsql_logo_01.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/fatals.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/logo_small.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/pause_terminal.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/pause_terminal_sm.b64 +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/pause_terminal_sm.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/prompt_compare.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/set_build_commands.jpg +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/unit_conversions.b64 +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/unit_conversions_029.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/unmatched.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/images/vim_execsql_highlight.png +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/index.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/reference/configuration.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/reference/metacommands.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/reference/security.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/docs/reference/substitution_vars.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/extras/vscode-execsql/README.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/extras/vscode-execsql/package.json +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/justfile +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/scripts/generate_vscode_grammar.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/__main__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/cli/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/cli/dsn.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/cli/help.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/config.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/constants.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/access.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/dsn.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/duckdb.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/factory.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/firebird.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/mysql.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/oracle.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/postgres.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/sqlite.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/db/sqlserver.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exceptions.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/delimited.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/duckdb.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/feather.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/html.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/json.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/latex.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/markdown.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/ods.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/parquet.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/pretty.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/protocol.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/raw.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/sqlite.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/templates.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/values.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/xls.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/xml.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/exporters/zip.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/format.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/gui/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/gui/base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/gui/console.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/gui/desktop.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/gui/tui.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/csv.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/feather.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/ods.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/importers/xls.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/conditions.py +1 -1
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/connect.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/data.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/dispatch.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/io.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/io_export.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/io_fileops.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/io_import.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/io_write.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/prompt.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/script_ext.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/metacommands/system.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/models.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/parser.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/py.typed +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/script/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/script/control.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/script/variables.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/types.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/auth.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/crypto.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/datetime.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/errors.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/fileio.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/mail.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/numeric.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/regex.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/strings.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/src/execsql/utils/timer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/README.md +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/config_settings.sqlite +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/example_config_prompt.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/execsql.conf +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/make_config_db.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/md_compare.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/md_glossary.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/md_upsert.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/pg_compare.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/pg_glossary.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/pg_upsert.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/script_template.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/ss_compare.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/ss_glossary.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/templates/ss_upsert.sql +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_cli.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_cli_e2e.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_cli_run.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_lint.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_ping.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/cli/test_profile.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/conftest.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_duckdb.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_factory.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_postgres.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_sqlite.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/db/test_sqlite_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_base.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_db.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_delimited.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_duckdb_exporter.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_exporters.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_feather.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_html_latex.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_json.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_markdown.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_ods.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_parquet.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_sqlite_exporter.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_templates.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_xls_xlsx.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_xlsx.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_xml.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_yaml.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/exporters/test_zip.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/gui/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/gui/test_backends.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/importers/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/importers/test_csv_importer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/importers/test_feather_importer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/importers/test_ods_importer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/importers/test_xls_importer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/conftest.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/test_dsn.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/test_duckdb.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/test_mysql.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/test_postgres.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/integration/test_sqlite.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_assert.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_breakpoint.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_connect.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_connect.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_data.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_io.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_script_ext.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_system.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_metacommands_system_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/metacommands/test_row_count.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_config.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_config_data.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_constants.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_engine.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_error_messages.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_exceptions.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_format.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_mail.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_models.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_package.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_parser.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_registry.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_script.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_state.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/test_types.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/__init__.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_auth.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_auth_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_crypto.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_datetime.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_errors.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_errors_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_fileio.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_fileio_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_numeric.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_regex.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_strings.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_timer.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/tests/utils/test_timer_extra.py +0 -0
- {execsql2-2.11.0 → execsql2-2.11.1}/zensical.toml +0 -0
|
@@ -189,10 +189,10 @@ Triggered on: push to `main`, any tag `v*.*.*`, pull requests.
|
|
|
189
189
|
|
|
190
190
|
## Versioning
|
|
191
191
|
|
|
192
|
-
`bump-my-version` manages versions. Current: `2.
|
|
192
|
+
`bump-my-version` manages versions. Current: `2.11.0`. Bump commands:
|
|
193
193
|
|
|
194
|
-
- `just bump-patch` → 2.
|
|
195
|
-
- `just bump-minor` → 2.
|
|
194
|
+
- `just bump-patch` → 2.11.0 → 2.11.1
|
|
195
|
+
- `just bump-minor` → 2.11.0 → 2.12.0
|
|
196
196
|
Bumps commit + tag. Pre-commit hook runs `uv lock` + stages `uv.lock`.
|
|
197
197
|
|
|
198
198
|
## Ruff Config
|
|
@@ -254,16 +254,32 @@ the foreseeable future.
|
|
|
254
254
|
| Dispatch optimization already in place (verified) | 2.5.0 | 2026-04 |
|
|
255
255
|
| PostgreSQL integration tests (9 tests, CI Docker) | 2.5.0 | 2026-04 |
|
|
256
256
|
| MySQL integration tests (9 tests, CI Docker) | 2.5.0 | 2026-04 |
|
|
257
|
+
| `RuntimeContext` refactor + module proxy | 2.6.0 | 2026-04 |
|
|
258
|
+
| `noqa` cleanup (180 suppressions removed) | 2.6.0 | 2026-04 |
|
|
259
|
+
| Coverage raised to 86% (3010 tests) | 2.6.0 | 2026-04 |
|
|
260
|
+
| Markdown, YAML, XLSX export formats | 2.7.0 | 2026-04 |
|
|
261
|
+
| `ASSERT` metacommand | 2.8.0 | 2026-04 |
|
|
262
|
+
| `--dry-run` variable expansion | 2.8.0 | 2026-04 |
|
|
263
|
+
| `--profile` per-statement timing | 2.8.0 | 2026-04 |
|
|
264
|
+
| `--ping` connectivity test | 2.9.0 | 2026-04 |
|
|
265
|
+
| `--lint` static script analysis | 2.9.0 | 2026-04 |
|
|
266
|
+
| Configuration docs audit (6 fixes) | 2.9.0 | 2026-04 |
|
|
267
|
+
| `ROW_COUNT_GT/GTE/EQ/LT` conditionals | 2.10.0 | 2026-04 |
|
|
268
|
+
| `BREAKPOINT` debug REPL with step mode | 2.10.0 | 2026-04 |
|
|
269
|
+
| Error messages restored (script location, command) | 2.11.0 | 2026-04 |
|
|
270
|
+
| 16-item codebase analysis fix sweep | 2.11.x | 2026-04 |
|
|
257
271
|
|
|
258
272
|
______________________________________________________________________
|
|
259
273
|
|
|
260
|
-
### v2.6
|
|
274
|
+
### Completed milestone detail (v2.6–v2.11)
|
|
261
275
|
|
|
262
|
-
|
|
263
|
-
- [x] **`noqa` cleanup in `metacommands/__init__.py`** — removed all 180 redundant `# noqa` comments; `__all__` already satisfies ruff F401.
|
|
264
|
-
- [x] **Coverage push to 86%** — 403 new tests (3010 total) covering `db/base.py` (55→99%), `metacommands/connect.py` (36→100%), `script/engine.py` (77→95%), `exporters/delimited.py` (76→95%). Remaining gap to 90% is in GUI, ODS, and import handlers.
|
|
276
|
+
#### v2.6 — Architecture & Internal Quality
|
|
265
277
|
|
|
266
|
-
|
|
278
|
+
- [x] `state.py` → `RuntimeContext` refactor
|
|
279
|
+
- [x] `noqa` cleanup in `metacommands/__init__.py`
|
|
280
|
+
- [x] Coverage push to 86%
|
|
281
|
+
|
|
282
|
+
#### v2.7 — New Export/Import Formats
|
|
267
283
|
|
|
268
284
|
- [x] **Parquet import** — already existed as `IMPORT TO table FROM PARQUET file` (verified present).
|
|
269
285
|
- [x] **YAML export** — `FORMAT YAML` via PyYAML, list-of-dicts with native type preservation.
|
|
@@ -13,6 +13,28 @@ ______________________________________________________________________
|
|
|
13
13
|
|
|
14
14
|
______________________________________________________________________
|
|
15
15
|
|
|
16
|
+
## [2.11.1] - 2026-04-01
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `x_assert` crash when `exec_log` is None — added null guard on `log_user_msg()` call.
|
|
21
|
+
- `--ping` version-query loop exiting prematurely — `break` was at wrong indentation, skipping fallback queries when the first query returned no rows.
|
|
22
|
+
- `CONSOLE SET WIDTH/HEIGHT` crash — `gui_console_width()`/`gui_console_height()` restored as setter functions with GUI console propagation.
|
|
23
|
+
- `$ERROR_MESSAGE` now contains full `errmsg()` (with script location and timestamp) for non-halting errors.
|
|
24
|
+
- Non-halting SQL and metacommand errors now logged to exec_log.
|
|
25
|
+
- `x_debug_log_subvars` log format — was printing full tuple instead of name/value for local variables.
|
|
26
|
+
- Dead `endloop()` removed from `control.py` — `state.endloop()` is canonical.
|
|
27
|
+
- YAML `append=True` now emits `---` document separator for valid multi-document streams.
|
|
28
|
+
- REPL dot-command parsing consistency between dispatcher and exit-check.
|
|
29
|
+
- `__delattr__` on state proxy uses cached `_DEFAULT_CTX` instead of allocating per call.
|
|
30
|
+
- `write_query_to_xlsx` single-sheet now updates `export_metadata`.
|
|
31
|
+
- `isinstance()` used instead of `type()` equality in `MetaCommandList.add()`.
|
|
32
|
+
- Module docstrings in `conditions.py` and `control.py` moved before imports.
|
|
33
|
+
- FEATHER divergence doc corrected — `polars` only, not `polars + pyarrow`.
|
|
34
|
+
- README pre-commit rev updated to `v2.11.0`; options table completed.
|
|
35
|
+
|
|
36
|
+
______________________________________________________________________
|
|
37
|
+
|
|
16
38
|
## [2.11.0] - 2026-04-01
|
|
17
39
|
|
|
18
40
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.11.
|
|
3
|
+
Version: 2.11.1
|
|
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: Repository, https://github.com/geocoug/execsql
|
|
6
6
|
Project-URL: Issues, https://github.com/geocoug/execsql/issues
|
|
@@ -220,8 +220,11 @@ execsql script.sql # read connection from config file
|
|
|
220
220
|
| `-v {0,1,2,3}` | GUI level (0=none, 1=password, 2=selection, 3=full) |
|
|
221
221
|
| `-w` | Skip password prompt when a username is supplied |
|
|
222
222
|
| `--dsn URL` | Connection string (e.g. `postgresql://user:pass@host/db`) |
|
|
223
|
+
| `--output-dir DIR` | Default base directory for EXPORT output files |
|
|
223
224
|
| `--dry-run` | Parse the script and report commands without executing |
|
|
224
225
|
| `--lint` | Static analysis: check structure and warn on issues (no DB) |
|
|
226
|
+
| `--ping` | Test database connectivity and exit |
|
|
227
|
+
| `--profile` | Show per-statement timing summary after execution |
|
|
225
228
|
| `--progress` | Show a progress bar for long-running IMPORT operations |
|
|
226
229
|
| `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
|
|
227
230
|
| `--dump-keywords` | Print metacommand keywords as JSON and exit |
|
|
@@ -298,7 +301,7 @@ execsql-format --check scripts/
|
|
|
298
301
|
```yaml
|
|
299
302
|
repos:
|
|
300
303
|
- repo: https://github.com/geocoug/execsql
|
|
301
|
-
rev: v2.
|
|
304
|
+
rev: v2.11.0
|
|
302
305
|
hooks:
|
|
303
306
|
- id: execsql-format
|
|
304
307
|
args: [--in-place]
|
|
@@ -110,8 +110,11 @@ execsql script.sql # read connection from config file
|
|
|
110
110
|
| `-v {0,1,2,3}` | GUI level (0=none, 1=password, 2=selection, 3=full) |
|
|
111
111
|
| `-w` | Skip password prompt when a username is supplied |
|
|
112
112
|
| `--dsn URL` | Connection string (e.g. `postgresql://user:pass@host/db`) |
|
|
113
|
+
| `--output-dir DIR` | Default base directory for EXPORT output files |
|
|
113
114
|
| `--dry-run` | Parse the script and report commands without executing |
|
|
114
115
|
| `--lint` | Static analysis: check structure and warn on issues (no DB) |
|
|
116
|
+
| `--ping` | Test database connectivity and exit |
|
|
117
|
+
| `--profile` | Show per-statement timing summary after execution |
|
|
115
118
|
| `--progress` | Show a progress bar for long-running IMPORT operations |
|
|
116
119
|
| `--debug` | Start in step-through debug mode (REPL pauses before each stmt) |
|
|
117
120
|
| `--dump-keywords` | Print metacommand keywords as JSON and exit |
|
|
@@ -188,7 +191,7 @@ execsql-format --check scripts/
|
|
|
188
191
|
```yaml
|
|
189
192
|
repos:
|
|
190
193
|
- repo: https://github.com/geocoug/execsql
|
|
191
|
-
rev: v2.
|
|
194
|
+
rev: v2.11.0
|
|
192
195
|
hooks:
|
|
193
196
|
- id: execsql-format
|
|
194
197
|
args: [--in-place]
|
|
@@ -33,7 +33,7 @@ ______________________________________________________________________
|
|
|
33
33
|
| Format | Description |
|
|
34
34
|
| ----------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
35
35
|
| `PARQUET` | Export query or table results to Apache Parquet via `polars`. |
|
|
36
|
-
| `FEATHER` | Export to Apache Feather/IPC via `polars`
|
|
36
|
+
| `FEATHER` | Export to Apache Feather/IPC via `polars` (upstream used `pandas` + `pyarrow`). |
|
|
37
37
|
| `YAML` | Export query or table results as a YAML sequence of mappings via `PyYAML`. |
|
|
38
38
|
| `MARKDOWN` / `MD` | Export query or table results as a GitHub-Flavored Markdown (GFM) pipe table. Pure Python, no optional dependencies. |
|
|
39
39
|
| `XLSX` | Export query or table results to an Excel XLSX workbook via `openpyxl` (single or multi-sheet). |
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execsql2"
|
|
7
|
-
version = "2.11.
|
|
7
|
+
version = "2.11.1"
|
|
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" }
|
|
@@ -158,7 +158,7 @@ skip-magic-trailing-comma = false
|
|
|
158
158
|
line-ending = "auto"
|
|
159
159
|
|
|
160
160
|
[tool.bumpversion]
|
|
161
|
-
current_version = "2.11.
|
|
161
|
+
current_version = "2.11.1"
|
|
162
162
|
commit = true
|
|
163
163
|
commit_args = "--no-verify"
|
|
164
164
|
tag = true
|
|
@@ -194,7 +194,7 @@ def _lint_cmdlist(
|
|
|
194
194
|
for cmd in cmdlist.cmdlist:
|
|
195
195
|
src = cmd.source
|
|
196
196
|
lno = cmd.line_no
|
|
197
|
-
stmt = cmd.command.statement
|
|
197
|
+
stmt = cmd.command.statement
|
|
198
198
|
|
|
199
199
|
if cmd.command_type == "sql":
|
|
200
200
|
# SQL statements: check for variable references only
|
|
@@ -8,6 +8,7 @@ and drives the main execution loop. Separated from argument parsing
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
10
|
import atexit
|
|
11
|
+
from typing import Any
|
|
11
12
|
import datetime
|
|
12
13
|
import getpass
|
|
13
14
|
import os
|
|
@@ -128,7 +129,7 @@ def _print_profile(profile_data: list[tuple]) -> None:
|
|
|
128
129
|
# ---------------------------------------------------------------------------
|
|
129
130
|
|
|
130
131
|
|
|
131
|
-
def _ping_db(db) -> None:
|
|
132
|
+
def _ping_db(db: Any) -> None:
|
|
132
133
|
"""Test connectivity for *db*, print connection details, and exit.
|
|
133
134
|
|
|
134
135
|
Attempts to execute ``SELECT version()`` (or ``SELECT sqlite_version()``
|
|
@@ -156,7 +157,7 @@ def _ping_db(db) -> None:
|
|
|
156
157
|
curs.close()
|
|
157
158
|
if row and row[0]:
|
|
158
159
|
version_str = str(row[0]).split("\n")[0].strip()
|
|
159
|
-
|
|
160
|
+
break
|
|
160
161
|
except Exception:
|
|
161
162
|
continue
|
|
162
163
|
|
|
@@ -178,6 +178,11 @@ def write_query_to_xlsx(
|
|
|
178
178
|
wb.save(outfile)
|
|
179
179
|
wb.close()
|
|
180
180
|
|
|
181
|
+
if _state.export_metadata is not None:
|
|
182
|
+
_state.export_metadata.add(
|
|
183
|
+
ExportRecord(queryname=select_stmt, outfile=outfile, zipfile=None, description=desc),
|
|
184
|
+
)
|
|
185
|
+
|
|
181
186
|
|
|
182
187
|
def write_queries_to_xlsx(
|
|
183
188
|
table_list: str,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from execsql.exceptions import ErrInfo
|
|
3
2
|
|
|
4
3
|
"""
|
|
5
4
|
Control-flow metacommand handlers for execsql.
|
|
@@ -18,6 +17,8 @@ Implements the imperative ``x_*`` functions for script flow control:
|
|
|
18
17
|
"""
|
|
19
18
|
|
|
20
19
|
import time
|
|
20
|
+
|
|
21
|
+
from execsql.exceptions import ErrInfo
|
|
21
22
|
from typing import Any
|
|
22
23
|
|
|
23
24
|
import execsql.state as _state
|
|
@@ -62,7 +63,8 @@ def x_assert(**kwargs: Any) -> None:
|
|
|
62
63
|
|
|
63
64
|
result = _state.xcmd_test(condition)
|
|
64
65
|
if result:
|
|
65
|
-
_state.exec_log
|
|
66
|
+
if _state.exec_log is not None:
|
|
67
|
+
_state.exec_log.log_user_msg(f"ASSERT passed: {condition}")
|
|
66
68
|
else:
|
|
67
69
|
raise ErrInfo(type="cmd", other_msg=message)
|
|
68
70
|
|
|
@@ -134,14 +136,6 @@ def x_loop(**kwargs: Any) -> None:
|
|
|
134
136
|
)
|
|
135
137
|
|
|
136
138
|
|
|
137
|
-
def endloop() -> None:
|
|
138
|
-
if len(_state.loopcommandstack) == 0:
|
|
139
|
-
raise ErrInfo("error", other_msg="END LOOP metacommand without a matching preceding LOOP metacommand.")
|
|
140
|
-
_state.compiling_loop = False
|
|
141
|
-
_state.commandliststack.append(_state.loopcommandstack[-1])
|
|
142
|
-
_state.loopcommandstack.pop()
|
|
143
|
-
|
|
144
|
-
|
|
145
139
|
def x_halt(**kwargs: Any) -> None:
|
|
146
140
|
errmsg = kwargs["errmsg"]
|
|
147
141
|
tee = kwargs["tee"]
|
|
@@ -74,7 +74,7 @@ def x_debug_log_subvars(**kwargs: Any) -> None:
|
|
|
74
74
|
local = kwargs["local"]
|
|
75
75
|
user = kwargs["user"]
|
|
76
76
|
for s in _state.commandliststack[-1].localvars.substitutions:
|
|
77
|
-
_state.exec_log.log_status_info(f"Substitution [{s}] = [{s}]")
|
|
77
|
+
_state.exec_log.log_status_info(f"Substitution [{s[0]}] = [{s[1]}]")
|
|
78
78
|
if local is None:
|
|
79
79
|
for s in _state.subvars.substitutions:
|
|
80
80
|
if user is None or s[0][0].isalnum() or s[0][0] == "_":
|
|
@@ -98,13 +98,14 @@ def _debug_repl() -> None:
|
|
|
98
98
|
|
|
99
99
|
# Dot-prefixed → REPL command
|
|
100
100
|
if line.startswith("."):
|
|
101
|
+
cmd = line[1:].strip().lower()
|
|
101
102
|
_handle_dot_command(line)
|
|
102
|
-
if
|
|
103
|
+
if cmd in ("continue", "c"):
|
|
103
104
|
return
|
|
104
|
-
if
|
|
105
|
+
if cmd in ("abort", "q", "quit"):
|
|
105
106
|
# _handle_dot_command already raised SystemExit, but guard anyway
|
|
106
107
|
return
|
|
107
|
-
if
|
|
108
|
+
if cmd in ("next", "n"):
|
|
108
109
|
return
|
|
109
110
|
continue
|
|
110
111
|
|
|
@@ -194,7 +194,7 @@ class MetaCommandList:
|
|
|
194
194
|
patterns; each compiles into a separate :class:`MetaCommand` prepended to
|
|
195
195
|
the dispatch list so that later registrations take priority.
|
|
196
196
|
"""
|
|
197
|
-
if
|
|
197
|
+
if isinstance(matching_regexes, (tuple, list)):
|
|
198
198
|
raw_patterns = list(matching_regexes)
|
|
199
199
|
regexes = [re.compile(rx, re.I) for rx in raw_patterns]
|
|
200
200
|
else:
|
|
@@ -305,9 +305,14 @@ class SqlStmt:
|
|
|
305
305
|
except Exception:
|
|
306
306
|
e = ErrInfo(type="exception", exception_msg=exception_desc())
|
|
307
307
|
if e:
|
|
308
|
+
from execsql.utils.errors import stamp_errinfo
|
|
309
|
+
|
|
310
|
+
stamp_errinfo(e)
|
|
308
311
|
_state.subvars.add_substitution("$LAST_ERROR", cmd)
|
|
309
|
-
_state.subvars.add_substitution("$ERROR_MESSAGE",
|
|
312
|
+
_state.subvars.add_substitution("$ERROR_MESSAGE", e.errmsg())
|
|
310
313
|
_state.status.sql_error = True
|
|
314
|
+
if _state.exec_log is not None:
|
|
315
|
+
_state.exec_log.log_status_info(f"SQL error: {e.errmsg()}")
|
|
311
316
|
if _state.status.halt_on_err:
|
|
312
317
|
from execsql.utils.errors import exit_now
|
|
313
318
|
|
|
@@ -349,9 +354,14 @@ class MetacommandStmt:
|
|
|
349
354
|
except Exception:
|
|
350
355
|
e = ErrInfo(type="exception", exception_msg=exception_desc())
|
|
351
356
|
if e:
|
|
357
|
+
from execsql.utils.errors import stamp_errinfo
|
|
358
|
+
|
|
359
|
+
stamp_errinfo(e)
|
|
352
360
|
_state.status.metacommand_error = True
|
|
353
361
|
_state.subvars.add_substitution("$LAST_ERROR", cmd)
|
|
354
|
-
_state.subvars.add_substitution("$ERROR_MESSAGE",
|
|
362
|
+
_state.subvars.add_substitution("$ERROR_MESSAGE", e.errmsg())
|
|
363
|
+
if _state.exec_log is not None:
|
|
364
|
+
_state.exec_log.log_status_info(f"Metacommand error: {e.errmsg()}")
|
|
355
365
|
if _state.status.halt_on_metacommand_err:
|
|
356
366
|
# Re-raise the original ErrInfo so its message is preserved, not
|
|
357
367
|
# replaced with the generic "Unknown metacommand" text.
|
|
@@ -336,8 +336,7 @@ class _StateModule(types.ModuleType):
|
|
|
336
336
|
# via setattr (local) or delattr (non-local). Since context
|
|
337
337
|
# attrs live on _ctx, not __dict__, patch takes the delattr
|
|
338
338
|
# path. We reset to the default rather than truly deleting.
|
|
339
|
-
|
|
340
|
-
setattr(self.__dict__["_ctx"], name, getattr(_defaults, name))
|
|
339
|
+
setattr(self.__dict__["_ctx"], name, getattr(_DEFAULT_CTX, name))
|
|
341
340
|
else:
|
|
342
341
|
super().__delattr__(name)
|
|
343
342
|
|
|
@@ -468,4 +467,5 @@ def initialize(
|
|
|
468
467
|
# ---------------------------------------------------------------------------
|
|
469
468
|
|
|
470
469
|
_ctx = RuntimeContext()
|
|
470
|
+
_DEFAULT_CTX = RuntimeContext() # Cached defaults for __delattr__ reset
|
|
471
471
|
sys.modules[__name__].__class__ = _StateModule
|
|
@@ -358,13 +358,35 @@ def gui_console_wait_user(message: str = "") -> None:
|
|
|
358
358
|
print(message, file=sys.stderr)
|
|
359
359
|
|
|
360
360
|
|
|
361
|
-
def gui_console_width() -> int:
|
|
362
|
-
"""
|
|
361
|
+
def gui_console_width(width: int | None = None) -> int:
|
|
362
|
+
"""Get or set the console width in characters.
|
|
363
|
+
|
|
364
|
+
When *width* is provided, updates the active GUI console (if any).
|
|
365
|
+
Always returns the current width.
|
|
366
|
+
"""
|
|
367
|
+
global _console_width
|
|
368
|
+
if width is not None:
|
|
369
|
+
import execsql.state as _state
|
|
370
|
+
|
|
371
|
+
_console_width = int(width)
|
|
372
|
+
if _state.gui_console is not None and hasattr(_state.gui_console, "set_width"):
|
|
373
|
+
_state.gui_console.set_width(_console_width)
|
|
363
374
|
return _console_width
|
|
364
375
|
|
|
365
376
|
|
|
366
|
-
def gui_console_height() -> int:
|
|
367
|
-
"""
|
|
377
|
+
def gui_console_height(height: int | None = None) -> int:
|
|
378
|
+
"""Get or set the console height in lines.
|
|
379
|
+
|
|
380
|
+
When *height* is provided, updates the active GUI console (if any).
|
|
381
|
+
Always returns the current height.
|
|
382
|
+
"""
|
|
383
|
+
global _console_height
|
|
384
|
+
if height is not None:
|
|
385
|
+
import execsql.state as _state
|
|
386
|
+
|
|
387
|
+
_console_height = int(height)
|
|
388
|
+
if _state.gui_console is not None and hasattr(_state.gui_console, "set_height"):
|
|
389
|
+
_state.gui_console.set_height(_console_height)
|
|
368
390
|
return _console_height
|
|
369
391
|
|
|
370
392
|
|
|
@@ -866,11 +866,9 @@ class TestControlHandlers:
|
|
|
866
866
|
assert len(_state.loopcommandstack) == 1
|
|
867
867
|
|
|
868
868
|
def test_endloop_without_loop_raises(self):
|
|
869
|
-
from execsql.metacommands.control import endloop
|
|
870
|
-
|
|
871
869
|
_state.loopcommandstack = []
|
|
872
870
|
with pytest.raises(ErrInfo):
|
|
873
|
-
endloop()
|
|
871
|
+
_state.endloop()
|
|
874
872
|
|
|
875
873
|
|
|
876
874
|
# ---------------------------------------------------------------------------
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|