execsql2 2.15.4__tar.gz → 2.15.5__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.15.4 → execsql2-2.15.5}/CHANGELOG.md +8 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/PKG-INFO +1 -1
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/about/divergence.md +1 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/pyproject.toml +2 -2
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/datetime.py +12 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_datetime.py +15 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/uv.lock +1 -1
- {execsql2-2.15.4 → execsql2-2.15.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.github/workflows/ci-cd.yml +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.gitignore +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.pre-commit-config.yaml +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.pre-commit-hooks.yaml +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.python-version +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/.readthedocs.yaml +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/CONTRIBUTING.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/LICENSE.txt +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/NOTICE +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/README.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/SECURITY.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/about/contributors.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/about/copyright.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/cli.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/db.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/exporters.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/importers.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/index.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/api/metacommands.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/dev/adding_db_adapters.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/dev/adding_exporters.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/dev/adding_importers.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/dev/adding_metacommands.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/dev/architecture.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/getting-started/installation.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/getting-started/requirements.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/getting-started/syntax.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/debugging.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/documentation.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/encoding.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/examples.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/formatter.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/logging.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/sql_syntax.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/usage.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/guides/using_scripts.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/Compare_planets.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/actions.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/actions2.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/checkboxes.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/connect.b64 +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/connect.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/create_conf.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/data_error1_screenshot.jpg +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/entry_form.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/execsql_console.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/execsql_logo_01.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/fatals.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/logo_small.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/pause_terminal.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/pause_terminal_sm.b64 +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/pause_terminal_sm.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/prompt_compare.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/set_build_commands.jpg +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/unit_conversions.b64 +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/unit_conversions_029.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/unmatched.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/images/vim_execsql_highlight.png +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/index.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/reference/configuration.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/reference/metacommands.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/reference/security.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/docs/reference/substitution_vars.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/extras/vscode-execsql/README.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/extras/vscode-execsql/package.json +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/extras/vscode-execsql/syntaxes/execsql.tmLanguage.json +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/justfile +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/scripts/generate_vscode_grammar.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/__main__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/cli/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/cli/dsn.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/cli/help.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/cli/lint.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/cli/run.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/config.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/access.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/dsn.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/duckdb.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/factory.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/firebird.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/mysql.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/oracle.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/postgres.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/sqlite.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/db/sqlserver.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/debug/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/debug/repl.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exceptions.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/delimited.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/duckdb.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/feather.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/html.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/json.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/latex.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/markdown.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/ods.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/parquet.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/pretty.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/protocol.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/raw.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/sqlite.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/templates.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/values.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/xls.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/xlsx.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/xml.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/yaml.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/exporters/zip.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/format.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/gui/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/gui/base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/gui/console.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/gui/desktop.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/gui/tui.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/csv.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/feather.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/json.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/ods.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/importers/xls.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/conditions.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/connect.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/control.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/data.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/debug.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/dispatch.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/io.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/io_export.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/io_fileops.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/io_import.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/io_write.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/prompt.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/script_ext.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/system.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/metacommands/upsert.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/models.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/parser.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/py.typed +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/script/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/script/control.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/script/engine.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/script/variables.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/state.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/types.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/auth.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/crypto.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/errors.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/fileio.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/gui.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/mail.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/numeric.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/regex.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/strings.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/src/execsql/utils/timer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/README.md +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/config_settings.sqlite +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/example_config_prompt.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/execsql.conf +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/make_config_db.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/md_compare.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/md_glossary.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/md_upsert.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/pg_compare.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/pg_glossary.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/pg_upsert.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/script_template.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/ss_compare.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/ss_glossary.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/templates/ss_upsert.sql +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_cli.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_cli_e2e.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_cli_run.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_lint.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_ping.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/cli/test_profile.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/conftest.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_duckdb.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_factory.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_postgres.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_sqlite.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/db/test_sqlite_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_base.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_db.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_delimited.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_duckdb_exporter.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_exporters.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_feather.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_html_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_html_latex.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_json.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_json_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_latex_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_markdown.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_ods.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_parquet.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_pretty_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_raw_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_sqlite_exporter.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_templates.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_templates_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_values_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_xls_xlsx.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_xlsx.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_xml.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_yaml.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/exporters/test_zip.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/gui/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/gui/test_backends.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/gui/test_compare_stats.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/gui/test_compute_row_diffs.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_base_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_csv_edge_cases.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_csv_importer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_feather_importer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_json_importer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_ods_importer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/importers/test_xls_importer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/conftest.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/test_dsn.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/test_duckdb.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/test_mysql.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/test_postgres.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/integration/test_sqlite.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_assert.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_breakpoint.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_connect.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_io_export.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_io_import.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_connect.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_data.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_fileops_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_io.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_io_write_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_script_ext.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_system.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_metacommands_system_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_pg_upsert.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/metacommands/test_row_count.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_config.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_config_data.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_config_extended.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_debug_repl.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_engine.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_error_messages.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_exceptions.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_format.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_mail.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_models.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_package.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_parser.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_registry.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_script.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_state.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/test_types.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/__init__.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_auth.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_auth_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_crypto.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_errors.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_errors_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_fileio.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_fileio_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_numeric.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_regex.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_strings.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_timer.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/tests/utils/test_timer_extra.py +0 -0
- {execsql2-2.15.4 → execsql2-2.15.5}/zensical.toml +0 -0
|
@@ -13,6 +13,14 @@ ______________________________________________________________________
|
|
|
13
13
|
|
|
14
14
|
______________________________________________________________________
|
|
15
15
|
|
|
16
|
+
## [2.15.5] - 2026-04-15
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- `DT_Timestamp` type inference no longer claims time-only values (e.g. `13:15:45`). `dateutil.parser.parse()` silently fills in today's date for bare time strings, causing `DT_Timestamp` to match before `DT_Time` and generating PostgreSQL `InvalidDatetimeFormat` errors on CSV import. Time-only strings are now rejected by `parse_datetime()`.
|
|
21
|
+
|
|
22
|
+
______________________________________________________________________
|
|
23
|
+
|
|
16
24
|
## [2.15.4] - 2026-04-15
|
|
17
25
|
|
|
18
26
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: execsql2
|
|
3
|
-
Version: 2.15.
|
|
3
|
+
Version: 2.15.5
|
|
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
|
|
@@ -253,6 +253,7 @@ These are behavioral changes driven by security or correctness issues in the ups
|
|
|
253
253
|
| `WriteHooks.write_err()` crash on empty string | `strval[-1]` raised `IndexError` on empty input. Fixed to use `str.endswith()`. Inherited from upstream. |
|
|
254
254
|
| `NumericParser` division by zero | `NumericAstNode.eval()` raised unhandled `ZeroDivisionError`. Now raises `NumericParserError` with a clear message. Inherited from upstream. |
|
|
255
255
|
| `CondAstNode.eval()` could return `None` | Missing fallthrough for unknown node types silently returned `None`. Now raises `CondParserError`. Inherited from upstream. |
|
|
256
|
+
| `DT_Timestamp` claims time-only values | `dateutil.parser.parse()` silently fills in today's date for bare time strings like `"13:15:45"`, so `DT_Timestamp` matched before `DT_Time` in the inference order. `parse_datetime()` now rejects time-only strings. Inherited from upstream. |
|
|
256
257
|
|
|
257
258
|
______________________________________________________________________
|
|
258
259
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "execsql2"
|
|
7
|
-
version = "2.15.
|
|
7
|
+
version = "2.15.5"
|
|
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" }
|
|
@@ -164,7 +164,7 @@ skip-magic-trailing-comma = false
|
|
|
164
164
|
line-ending = "auto"
|
|
165
165
|
|
|
166
166
|
[tool.bumpversion]
|
|
167
|
-
current_version = "2.15.
|
|
167
|
+
current_version = "2.15.5"
|
|
168
168
|
commit = true
|
|
169
169
|
commit_args = "--no-verify"
|
|
170
170
|
tag = true
|
|
@@ -25,12 +25,22 @@ __all__ = ["parse_datetime", "parse_datetimetz"]
|
|
|
25
25
|
# misidentified as timestamps.
|
|
26
26
|
_NUMERIC_ONLY = re.compile(r"^[+-]?\d+\.?\d*$")
|
|
27
27
|
|
|
28
|
+
# Match time-only strings like "13:15:45", "9:30", "1:15:45.123", "09:30 AM".
|
|
29
|
+
# dateutil parses these by filling in today's date, which causes DT_Timestamp
|
|
30
|
+
# to claim the column before DT_Time gets a chance.
|
|
31
|
+
_TIME_ONLY = re.compile(r"^\d{1,2}:\d{2}(?::\d{2}(?:\.\d+)?)?\s*(?:[AaPp][Mm])?$")
|
|
32
|
+
|
|
28
33
|
|
|
29
34
|
def _looks_numeric(s: str) -> bool:
|
|
30
35
|
"""Return True if *s* is a bare number that should not be parsed as a date."""
|
|
31
36
|
return bool(_NUMERIC_ONLY.match(s.strip()))
|
|
32
37
|
|
|
33
38
|
|
|
39
|
+
def _looks_time_only(s: str) -> bool:
|
|
40
|
+
"""Return True if *s* is a time-only string (no date component)."""
|
|
41
|
+
return bool(_TIME_ONLY.match(s.strip()))
|
|
42
|
+
|
|
43
|
+
|
|
34
44
|
def parse_datetime(datestr: Any) -> datetime.datetime | None:
|
|
35
45
|
"""Parse a date/time string into a :class:`datetime.datetime`.
|
|
36
46
|
|
|
@@ -53,6 +63,8 @@ def parse_datetime(datestr: Any) -> datetime.datetime | None:
|
|
|
53
63
|
return None
|
|
54
64
|
if _looks_numeric(datestr):
|
|
55
65
|
return None
|
|
66
|
+
if _looks_time_only(datestr):
|
|
67
|
+
return None
|
|
56
68
|
try:
|
|
57
69
|
return _dateutil_parser.parse(datestr)
|
|
58
70
|
except (ValueError, OverflowError, TypeError):
|
|
@@ -124,6 +124,21 @@ class TestParseDatetimeExtended:
|
|
|
124
124
|
def test_empty_string_returns_none(self):
|
|
125
125
|
assert parse_datetime("") is None
|
|
126
126
|
|
|
127
|
+
def test_time_only_strings_rejected(self):
|
|
128
|
+
"""Time-only values must not be parsed as timestamps (GH: type inference bug)."""
|
|
129
|
+
assert parse_datetime("13:15:45") is None
|
|
130
|
+
assert parse_datetime("9:30") is None
|
|
131
|
+
assert parse_datetime("1:15:45.123") is None
|
|
132
|
+
assert parse_datetime("09:30 AM") is None
|
|
133
|
+
assert parse_datetime("11:00 pm") is None
|
|
134
|
+
|
|
135
|
+
def test_datetime_with_time_still_parses(self):
|
|
136
|
+
"""Strings with both date and time components must still work."""
|
|
137
|
+
result = parse_datetime("2026-02-25 13:15:45")
|
|
138
|
+
assert isinstance(result, datetime.datetime)
|
|
139
|
+
assert result.hour == 13
|
|
140
|
+
assert result.minute == 15
|
|
141
|
+
|
|
127
142
|
|
|
128
143
|
# ---------------------------------------------------------------------------
|
|
129
144
|
# parse_datetimetz
|
|
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
|
|
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
|
|
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
|