nlp2sql 0.2.0rc14__tar.gz → 0.2.0rc16__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.
- nlp2sql-0.2.0rc16/.github/scripts/verify_release_tag.py +48 -0
- nlp2sql-0.2.0rc16/.github/workflows/ci.yml +136 -0
- nlp2sql-0.2.0rc16/.github/workflows/publish-pypi.yml +115 -0
- nlp2sql-0.2.0rc16/.github/workflows/publish-testpypi.yml +90 -0
- nlp2sql-0.2.0rc16/CHANGELOG.md +132 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/CONTRIBUTING.md +16 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/PKG-INFO +13 -12
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/README.md +6 -6
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docs/API.md +1 -1
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/advanced/test_multiple_providers.py +11 -11
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/getting_started/simple_demo.py +1 -1
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/mcp_server/__init__.py +1 -1
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/mcp_server/pyproject.toml +2 -2
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/pyproject.toml +7 -6
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/__init__.py +9 -8
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/anthropic_adapter.py +65 -22
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/gemini_adapter.py +97 -22
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/openai_adapter.py +159 -34
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/cli.py +21 -28
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/client.py +50 -20
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/config/settings.py +7 -4
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/provider_config.py +6 -3
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/sql_safety.py +29 -4
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_service.py +16 -1
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/semantic_validation_service.py +24 -10
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/conftest.py +20 -0
- nlp2sql-0.2.0rc16/tests/data/gold_questions.json +58 -0
- nlp2sql-0.2.0rc16/tests/fakes/__init__.py +1 -0
- nlp2sql-0.2.0rc16/tests/fakes/fake_openai.py +132 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_basic.py +15 -12
- nlp2sql-0.2.0rc16/tests/test_cli_setup.py +35 -0
- nlp2sql-0.2.0rc16/tests/test_connect_embeddings.py +120 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_dsl_integration.py +1 -1
- nlp2sql-0.2.0rc16/tests/test_false_invalid_regression.py +36 -0
- nlp2sql-0.2.0rc16/tests/test_first_run.py +56 -0
- nlp2sql-0.2.0rc16/tests/test_model_defaults.py +284 -0
- nlp2sql-0.2.0rc16/tests/test_provider_compat_llm.py +240 -0
- nlp2sql-0.2.0rc16/tests/test_query_service_contract.py +87 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_retrieval_pipeline.py +55 -0
- nlp2sql-0.2.0rc16/tests/test_sql_safety.py +40 -0
- nlp2sql-0.2.0rc16/tests/test_version_consistency.py +60 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/uv.lock +8 -6
- nlp2sql-0.2.0rc14/.github/workflows/ci.yml +0 -84
- nlp2sql-0.2.0rc14/.github/workflows/publish-pypi.yml +0 -88
- nlp2sql-0.2.0rc14/.github/workflows/publish-testpypi.yml +0 -72
- nlp2sql-0.2.0rc14/CHANGELOG.md +0 -43
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/commands/db.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/commands/quality.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/commands/test.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/rules/adapters.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/rules/architecture.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/rules/python-style.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/rules/testing.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.claude/settings.json +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.gitignore +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.mcp.json.example +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/.python-version +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/CLAUDE.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/LICENSE +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/SECURITY.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/assets/nlp2sql-logo.png +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/benchmarks/enterprise_benchmark_results.json +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/.env.example +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/README.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/docker-compose.yml +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/get-db-urls.sh +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/init-schema.sql +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/large-schema.sql +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/localstack-init.sh +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docker/test-redshift.sh +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docs/ARCHITECTURE.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docs/CONFIGURATION.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docs/ENTERPRISE.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/docs/Redshift.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/README.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/advanced/test_simple_api.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/database_specific/test_odoo_integration.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/default_examples.json +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/documentation/real_world_example.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/getting_started/basic_usage.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/getting_started/test_api_setup.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/schema_management/test_auto_schema.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/schema_management/test_schema_filters_comprehensive.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/.dockerignore +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/.env.example +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_README.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_SETUP.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_TESTING_SUMMARY.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/Dockerfile +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/INDEX.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/README.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/docker/init-ecommerce-schema.sql +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/docker-compose.yml +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/main.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/pyproject.toml +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/test-docker-endpoints.sh +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/install-dev.sh +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/mcp_server/README.md +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/mcp_server/example_config.json +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/mcp_server/server.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/default_error_classifier.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/default_repair_policy.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/dict_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/file_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/local_embedding_adapter.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/noop_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/noop_semantic_validator.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/openai_embedding_adapter.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/pgvector_example_repository.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/postgres_repository.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/redshift_adapter.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/regex_query_validator.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/schema_repository_execution_adapter.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/config/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/database_prompts.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/entities.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/result.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/runtime.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/sql_keywords.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/exceptions/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/factories/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/factories/repository_factory.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/ai_provider.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/cache.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/embedding_provider.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/error_classifier.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/example_repository.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_execution.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_optimizer.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_safety.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_validator.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/repair_policy.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/schema_repository.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/schema_strategy.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/semantic_validator.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/analyzer.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/embedding_manager.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/example_loader.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/example_store.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/manager.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/example_selection_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/prompt_assembly_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_analysis_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_repair_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/semantic_resolution_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/sql_intent_planning_service.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/artifact_loader.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/helpers.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/semantic_prompt.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/storage.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/test_tmp/.gitignore +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/mcp/__init__.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/mcp/test_sql_security.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_artifact_loader.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_batch_scoring.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_cli_semantic_support.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_client_hooks.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_column_validation.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_database_prompts.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_embedding_manager.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_integration.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_pgvector_example_repository.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_postgres_integration.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_redshift_integration.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_repository_cache.py +0 -0
- {nlp2sql-0.2.0rc14 → nlp2sql-0.2.0rc16}/tests/test_repository_factory.py +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Check that a release tag matches the package version before publishing.
|
|
2
|
+
|
|
3
|
+
The publish workflows run this before building, so a package is only ever
|
|
4
|
+
published from a tag named ``v`` + the ``[project].version`` of pyproject.toml.
|
|
5
|
+
|
|
6
|
+
Usage: python .github/scripts/verify_release_tag.py v0.2.0rc16
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import re
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
import tomllib
|
|
16
|
+
|
|
17
|
+
TAG_PATTERN = re.compile(r"v\d+\.\d+\.\d+(?:(?:a|b|rc)\d+)?")
|
|
18
|
+
PYPROJECT = Path(__file__).resolve().parents[2] / "pyproject.toml"
|
|
19
|
+
SEE_DOCS = "See 'Releasing (maintainers)' in CONTRIBUTING.md."
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def fail(message: str) -> int:
|
|
23
|
+
print(f"::error title=Release tag check failed::{message} {SEE_DOCS}")
|
|
24
|
+
return 1
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def main(argv: Optional[list[str]] = None) -> int:
|
|
28
|
+
parser = argparse.ArgumentParser(description="Check that a release tag matches the version in pyproject.toml.")
|
|
29
|
+
parser.add_argument("tag", help="release tag, for example v0.2.0rc16")
|
|
30
|
+
tag = parser.parse_args(argv).tag
|
|
31
|
+
|
|
32
|
+
if not TAG_PATTERN.fullmatch(tag):
|
|
33
|
+
return fail(f"'{tag}' is not a release tag: expected vX.Y.Z, optionally followed by aN, bN or rcN.")
|
|
34
|
+
|
|
35
|
+
with PYPROJECT.open("rb") as file:
|
|
36
|
+
version = tomllib.load(file)["project"]["version"]
|
|
37
|
+
if tag != f"v{version}":
|
|
38
|
+
return fail(
|
|
39
|
+
f"Tag {tag} does not match the pyproject.toml version ({version}) of the checked-out commit. "
|
|
40
|
+
"Was the release created before the version bump was pushed?"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
print(f"Tag {tag} matches the pyproject.toml version {version}.")
|
|
44
|
+
return 0
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
sys.exit(main())
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, develop]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, develop]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-24.04
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v7
|
|
19
|
+
|
|
20
|
+
- name: Set up Python 3.12
|
|
21
|
+
uses: actions/setup-python@v7
|
|
22
|
+
with:
|
|
23
|
+
python-version: '3.12'
|
|
24
|
+
|
|
25
|
+
- name: Install uv
|
|
26
|
+
run: python -m pip install uv
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: |
|
|
30
|
+
uv pip install --system .
|
|
31
|
+
uv pip install --system ".[dev]"
|
|
32
|
+
|
|
33
|
+
- name: Unit tests
|
|
34
|
+
env:
|
|
35
|
+
PYTHONPATH: src
|
|
36
|
+
run: pytest -m "not integration and not llm" -q
|
|
37
|
+
|
|
38
|
+
pgvector-integration:
|
|
39
|
+
runs-on: ubuntu-24.04
|
|
40
|
+
|
|
41
|
+
services:
|
|
42
|
+
postgres:
|
|
43
|
+
image: pgvector/pgvector:pg16
|
|
44
|
+
env:
|
|
45
|
+
POSTGRES_USER: testuser
|
|
46
|
+
POSTGRES_PASSWORD: testpass
|
|
47
|
+
POSTGRES_DB: testdb
|
|
48
|
+
ports:
|
|
49
|
+
- 5432:5432
|
|
50
|
+
options: >-
|
|
51
|
+
--health-cmd "pg_isready -U testuser -d testdb"
|
|
52
|
+
--health-interval 10s
|
|
53
|
+
--health-timeout 5s
|
|
54
|
+
--health-retries 5
|
|
55
|
+
|
|
56
|
+
steps:
|
|
57
|
+
- name: Checkout
|
|
58
|
+
uses: actions/checkout@v7
|
|
59
|
+
|
|
60
|
+
- name: Set up Python 3.12
|
|
61
|
+
uses: actions/setup-python@v7
|
|
62
|
+
with:
|
|
63
|
+
python-version: '3.12'
|
|
64
|
+
|
|
65
|
+
- name: Install uv
|
|
66
|
+
run: python -m pip install uv
|
|
67
|
+
|
|
68
|
+
- name: Install dependencies (with pgvector extra)
|
|
69
|
+
run: |
|
|
70
|
+
uv pip install --system ".[dev]"
|
|
71
|
+
uv pip install --system ".[pgvector]"
|
|
72
|
+
|
|
73
|
+
- name: Load the e-commerce test schema
|
|
74
|
+
env:
|
|
75
|
+
PGPASSWORD: testpass
|
|
76
|
+
run: psql -h localhost -U testuser -d testdb -v ON_ERROR_STOP=1 -q -f docker/init-schema.sql
|
|
77
|
+
|
|
78
|
+
# Scoped suites so the job stays self-contained (the broader integration
|
|
79
|
+
# suite also needs LocalStack Redshift, out of scope here).
|
|
80
|
+
# NLP2SQL_REQUIRE_INTEGRATION makes the fixtures FAIL instead of skip, so a
|
|
81
|
+
# misconfigured service goes red rather than green-via-skip.
|
|
82
|
+
- name: pgvector integration tests
|
|
83
|
+
env:
|
|
84
|
+
PYTHONPATH: src
|
|
85
|
+
NLP2SQL_REQUIRE_INTEGRATION: "1"
|
|
86
|
+
NLP2SQL_TEST_POSTGRES_HOST: localhost
|
|
87
|
+
NLP2SQL_TEST_POSTGRES_PORT: "5432"
|
|
88
|
+
NLP2SQL_TEST_POSTGRES_USER: testuser
|
|
89
|
+
NLP2SQL_TEST_POSTGRES_PASS: testpass
|
|
90
|
+
NLP2SQL_TEST_POSTGRES_DB: testdb
|
|
91
|
+
run: pytest tests/test_pgvector_example_repository.py -m integration -q
|
|
92
|
+
|
|
93
|
+
# README Quick Start per provider and the false-invalid gold set, with the
|
|
94
|
+
# OpenAI SDK pointed at tests/fakes/fake_openai.py (no keys, no cost).
|
|
95
|
+
- name: First-run regression tests
|
|
96
|
+
env:
|
|
97
|
+
PYTHONPATH: src
|
|
98
|
+
NLP2SQL_REQUIRE_INTEGRATION: "1"
|
|
99
|
+
NLP2SQL_TEST_POSTGRES_HOST: localhost
|
|
100
|
+
NLP2SQL_TEST_POSTGRES_PORT: "5432"
|
|
101
|
+
NLP2SQL_TEST_POSTGRES_USER: testuser
|
|
102
|
+
NLP2SQL_TEST_POSTGRES_PASS: testpass
|
|
103
|
+
NLP2SQL_TEST_POSTGRES_DB: testdb
|
|
104
|
+
run: pytest tests/test_first_run.py tests/test_false_invalid_regression.py -m integration -q
|
|
105
|
+
|
|
106
|
+
# Installs the built wheel the way a user does: fresh environment, no lock
|
|
107
|
+
# file, latest dependency versions. Catches undeclared dependencies (rc13-rc15
|
|
108
|
+
# could not be imported without pyyaml) that the locked dev environment hides.
|
|
109
|
+
clean-install:
|
|
110
|
+
runs-on: ubuntu-24.04
|
|
111
|
+
|
|
112
|
+
steps:
|
|
113
|
+
- name: Checkout
|
|
114
|
+
uses: actions/checkout@v7
|
|
115
|
+
|
|
116
|
+
- name: Set up Python 3.12
|
|
117
|
+
uses: actions/setup-python@v7
|
|
118
|
+
with:
|
|
119
|
+
python-version: '3.12'
|
|
120
|
+
|
|
121
|
+
- name: Build the wheel
|
|
122
|
+
run: |
|
|
123
|
+
python -m pip install build
|
|
124
|
+
python -m build --wheel
|
|
125
|
+
|
|
126
|
+
- name: Install the wheel in a fresh environment
|
|
127
|
+
run: |
|
|
128
|
+
python -m venv "$RUNNER_TEMP/clean"
|
|
129
|
+
"$RUNNER_TEMP/clean/bin/pip" install dist/*.whl
|
|
130
|
+
"$RUNNER_TEMP/clean/bin/pip" list | grep -iE "^(openai|anthropic|google-generativeai|pyyaml) "
|
|
131
|
+
|
|
132
|
+
- name: Import the package and run the CLI
|
|
133
|
+
working-directory: ${{ runner.temp }}
|
|
134
|
+
run: |
|
|
135
|
+
"$RUNNER_TEMP/clean/bin/python" -c "import nlp2sql; print('nlp2sql', nlp2sql.__version__)"
|
|
136
|
+
"$RUNNER_TEMP/clean/bin/nlp2sql" --help
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
name: Publish Python Package to PyPI
|
|
2
|
+
|
|
3
|
+
# Production releases are decided by a tag: run this workflow from the release
|
|
4
|
+
# tag (Run workflow -> Use workflow from -> Tags -> vX.Y.Z). A run from a branch
|
|
5
|
+
# fails before anything is checked out. See "Releasing (maintainers)" in
|
|
6
|
+
# CONTRIBUTING.md.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
inputs:
|
|
11
|
+
confirm_production:
|
|
12
|
+
description: 'Type "PRODUCTION" to confirm publishing to live PyPI'
|
|
13
|
+
required: true
|
|
14
|
+
default: ''
|
|
15
|
+
|
|
16
|
+
permissions: {}
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-24.04
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- name: Require a tag ref
|
|
26
|
+
run: |
|
|
27
|
+
if [ "$GITHUB_REF_TYPE" != "tag" ]; then
|
|
28
|
+
echo "::error title=Not a tag::Run this workflow from a release tag (Use workflow from -> Tags), not from '$GITHUB_REF_NAME'."
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
- name: Validate production confirmation
|
|
33
|
+
env:
|
|
34
|
+
CONFIRM_PRODUCTION: ${{ inputs.confirm_production }}
|
|
35
|
+
run: |
|
|
36
|
+
if [ "$CONFIRM_PRODUCTION" != "PRODUCTION" ]; then
|
|
37
|
+
echo "::error::Production confirmation required. Type PRODUCTION to confirm."
|
|
38
|
+
exit 1
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
- name: Require a published GitHub Release for the tag
|
|
42
|
+
env:
|
|
43
|
+
GH_TOKEN: ${{ github.token }}
|
|
44
|
+
run: |
|
|
45
|
+
is_draft=$(gh release view "$GITHUB_REF_NAME" -R "$GITHUB_REPOSITORY" --json isDraft -q .isDraft) || {
|
|
46
|
+
echo "::error::No GitHub Release found for $GITHUB_REF_NAME. Create and publish the release first."
|
|
47
|
+
exit 1
|
|
48
|
+
}
|
|
49
|
+
if [ "$is_draft" != "false" ]; then
|
|
50
|
+
echo "::error::The GitHub Release for $GITHUB_REF_NAME is still a draft."
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
- name: Checkout the tag
|
|
55
|
+
uses: actions/checkout@v7
|
|
56
|
+
with:
|
|
57
|
+
persist-credentials: false
|
|
58
|
+
|
|
59
|
+
- name: Set up Python 3.12
|
|
60
|
+
uses: actions/setup-python@v7
|
|
61
|
+
with:
|
|
62
|
+
python-version: '3.12'
|
|
63
|
+
|
|
64
|
+
- name: Verify the tag matches the package version
|
|
65
|
+
run: |
|
|
66
|
+
echo "Tag: $GITHUB_REF_NAME, commit: $GITHUB_SHA"
|
|
67
|
+
python .github/scripts/verify_release_tag.py "$GITHUB_REF_NAME"
|
|
68
|
+
|
|
69
|
+
- name: Install uv
|
|
70
|
+
run: python -m pip install uv
|
|
71
|
+
|
|
72
|
+
- name: Install project dependencies with uv
|
|
73
|
+
run: |
|
|
74
|
+
uv pip install --system .
|
|
75
|
+
uv pip install --system ".[dev]"
|
|
76
|
+
|
|
77
|
+
- name: Install build
|
|
78
|
+
run: python -m pip install build
|
|
79
|
+
|
|
80
|
+
- name: Run tests
|
|
81
|
+
env:
|
|
82
|
+
PYTHONPATH: src
|
|
83
|
+
run: pytest
|
|
84
|
+
|
|
85
|
+
- name: Build package
|
|
86
|
+
run: python -m build
|
|
87
|
+
|
|
88
|
+
- name: Upload distributions
|
|
89
|
+
uses: actions/upload-artifact@v7
|
|
90
|
+
with:
|
|
91
|
+
name: dist
|
|
92
|
+
path: dist/
|
|
93
|
+
if-no-files-found: error
|
|
94
|
+
|
|
95
|
+
publish:
|
|
96
|
+
needs: build
|
|
97
|
+
runs-on: ubuntu-24.04
|
|
98
|
+
environment: pypi
|
|
99
|
+
|
|
100
|
+
# Only this job can request a PyPI token (Trusted Publishing via OIDC), and
|
|
101
|
+
# it runs no project or third-party Python code.
|
|
102
|
+
permissions:
|
|
103
|
+
id-token: write
|
|
104
|
+
|
|
105
|
+
steps:
|
|
106
|
+
- name: Download distributions
|
|
107
|
+
uses: actions/download-artifact@v8
|
|
108
|
+
with:
|
|
109
|
+
name: dist
|
|
110
|
+
path: dist/
|
|
111
|
+
|
|
112
|
+
- name: Publish to PyPI
|
|
113
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
114
|
+
with:
|
|
115
|
+
repository-url: https://upload.pypi.org/legacy/
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
name: Publish Python Package to Test PyPI
|
|
2
|
+
|
|
3
|
+
# Runs automatically on the release tag when a GitHub Release is published, and
|
|
4
|
+
# can be re-run manually from a tag (Use workflow from -> Tags -> vX.Y.Z). A run
|
|
5
|
+
# from a branch fails before anything is checked out. See "Releasing
|
|
6
|
+
# (maintainers)" in CONTRIBUTING.md.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions: {}
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
runs-on: ubuntu-24.04
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- name: Require a tag ref
|
|
23
|
+
run: |
|
|
24
|
+
if [ "$GITHUB_REF_TYPE" != "tag" ]; then
|
|
25
|
+
echo "::error title=Not a tag::Run this workflow from a release tag (Use workflow from -> Tags), not from '$GITHUB_REF_NAME'."
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
- name: Checkout the tag
|
|
30
|
+
uses: actions/checkout@v7
|
|
31
|
+
with:
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
|
|
34
|
+
- name: Set up Python 3.12
|
|
35
|
+
uses: actions/setup-python@v7
|
|
36
|
+
with:
|
|
37
|
+
python-version: '3.12'
|
|
38
|
+
|
|
39
|
+
- name: Verify the tag matches the package version
|
|
40
|
+
run: |
|
|
41
|
+
echo "Tag: $GITHUB_REF_NAME, commit: $GITHUB_SHA"
|
|
42
|
+
python .github/scripts/verify_release_tag.py "$GITHUB_REF_NAME"
|
|
43
|
+
|
|
44
|
+
- name: Install uv
|
|
45
|
+
run: python -m pip install uv
|
|
46
|
+
|
|
47
|
+
- name: Install project dependencies with uv
|
|
48
|
+
run: |
|
|
49
|
+
uv pip install --system .
|
|
50
|
+
uv pip install --system ".[dev]"
|
|
51
|
+
|
|
52
|
+
- name: Install build
|
|
53
|
+
run: python -m pip install build
|
|
54
|
+
|
|
55
|
+
- name: Run tests
|
|
56
|
+
env:
|
|
57
|
+
PYTHONPATH: src
|
|
58
|
+
run: pytest
|
|
59
|
+
|
|
60
|
+
- name: Build package
|
|
61
|
+
run: python -m build
|
|
62
|
+
|
|
63
|
+
- name: Upload distributions
|
|
64
|
+
uses: actions/upload-artifact@v7
|
|
65
|
+
with:
|
|
66
|
+
name: dist
|
|
67
|
+
path: dist/
|
|
68
|
+
if-no-files-found: error
|
|
69
|
+
|
|
70
|
+
publish:
|
|
71
|
+
needs: build
|
|
72
|
+
runs-on: ubuntu-24.04
|
|
73
|
+
environment: testpypi
|
|
74
|
+
|
|
75
|
+
# Only this job can request a Test PyPI token (Trusted Publishing via OIDC),
|
|
76
|
+
# and it runs no project or third-party Python code.
|
|
77
|
+
permissions:
|
|
78
|
+
id-token: write
|
|
79
|
+
|
|
80
|
+
steps:
|
|
81
|
+
- name: Download distributions
|
|
82
|
+
uses: actions/download-artifact@v8
|
|
83
|
+
with:
|
|
84
|
+
name: dist
|
|
85
|
+
path: dist/
|
|
86
|
+
|
|
87
|
+
- name: Publish to Test PyPI
|
|
88
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
89
|
+
with:
|
|
90
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## Versioning policy
|
|
9
|
+
|
|
10
|
+
- **MAJOR** — incompatible public API changes (removing/renaming a public symbol
|
|
11
|
+
or changing a port/ABC contract in a non-backward-compatible way).
|
|
12
|
+
- **MINOR** — backward-compatible functionality (new adapters, new optional
|
|
13
|
+
parameters, new optional extras).
|
|
14
|
+
- **PATCH** — backward-compatible bug fixes.
|
|
15
|
+
|
|
16
|
+
Pre-1.0 the project ships release candidates (e.g. `0.2.0rcN`). Public surface
|
|
17
|
+
changes — moving/renaming exported symbols, or adding methods to a published
|
|
18
|
+
port such as `ExampleRepositoryPort` — MUST be recorded under `Unreleased`
|
|
19
|
+
before release and called out as **Breaking** if they affect external
|
|
20
|
+
implementers. Backward-compatible shims are preferred over hard breaks while
|
|
21
|
+
pre-1.0.
|
|
22
|
+
|
|
23
|
+
## [Unreleased]
|
|
24
|
+
|
|
25
|
+
## [0.2.0rc16] - 2026-10-19
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- Release: packages are published to PyPI only from a release tag whose name
|
|
29
|
+
matches the `pyproject.toml` version and that has a published GitHub Release.
|
|
30
|
+
The publish workflows build in one job and upload from another, so only the
|
|
31
|
+
upload job can request a PyPI token.
|
|
32
|
+
- CI: runs on `ubuntu-24.04` with the Node 24 versions of `actions/checkout` and
|
|
33
|
+
`actions/setup-python`, and fails when any copy of the package version is out
|
|
34
|
+
of sync with `pyproject.toml`.
|
|
35
|
+
- CI: a `clean-install` job installs the built wheel in a fresh environment
|
|
36
|
+
without the lock file, and the integration lane runs the README Quick Start
|
|
37
|
+
and a false-invalid regression set against a local fake of the OpenAI API.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
- `import nlp2sql` failed on a plain `pip install nlp2sql` since 0.2.0rc13
|
|
41
|
+
(`No module named 'yaml'`): `pyyaml` is now a declared dependency.
|
|
42
|
+
- `connect()` raised `Unknown embedding provider` with
|
|
43
|
+
`ProviderConfig(provider="anthropic")` or `"gemini"`, and with OpenAI failed
|
|
44
|
+
unless `OPENAI_API_KEY` was exported, because the `ProviderConfig` key never
|
|
45
|
+
reached the embedding adapter. Without an explicit embedding provider,
|
|
46
|
+
OpenAI chat now uses OpenAI embeddings with the same key; other providers use
|
|
47
|
+
local embeddings when `nlp2sql[embeddings-local]` is installed and no
|
|
48
|
+
embeddings otherwise. Few-shot examples share that provider, and are skipped
|
|
49
|
+
with a warning when there is none.
|
|
50
|
+
- Correct queries came back with `is_valid=False` when they did not use the
|
|
51
|
+
table the heuristic intent plan guessed from the question (4 of 14 in a
|
|
52
|
+
sample of realistic questions), even with no semantic layer. Plan-derived
|
|
53
|
+
expectations are now warnings; rules from a semantic layer are still errors.
|
|
54
|
+
- `is_valid` was `True` for queries that write (`DELETE ...` in the default
|
|
55
|
+
`generate_only` mode) and for queries whose execution failed. Both are now
|
|
56
|
+
invalid, with the reason in the validation errors.
|
|
57
|
+
- The read-only check rejected valid queries with keywords inside string
|
|
58
|
+
literals (`WHERE name = 'Gift Set'`), and allowed functions with side effects
|
|
59
|
+
such as `pg_terminate_backend`, `set_config`, `nextval` or `dblink`. It now
|
|
60
|
+
ignores literals and rejects those functions.
|
|
61
|
+
- `generate_sql(max_tokens=...)` and the CLI `--max-tokens` (default 1000) also
|
|
62
|
+
capped the schema context sent to the model; the schema budget is now always
|
|
63
|
+
`NLP2SQL_MAX_SCHEMA_TOKENS`.
|
|
64
|
+
- `nlp2sql setup` crashed when configuring a database (it called the
|
|
65
|
+
nonexistent `click.choice`), and offered MySQL and SQLite, which have no
|
|
66
|
+
adapter. It now offers PostgreSQL and Redshift.
|
|
67
|
+
|
|
68
|
+
## [0.2.0rc15] - 2026-09-18
|
|
69
|
+
|
|
70
|
+
### Changed
|
|
71
|
+
- Default chat models refreshed to current, non-retired IDs. **User-visible: cost,
|
|
72
|
+
latency and SQL style change for anyone who does not pin `model`.**
|
|
73
|
+
- OpenAI: `gpt-4o-mini` -> `gpt-5.6-luna` (1.05M context, 922K input, 128K output).
|
|
74
|
+
`gpt-4o-mini` remains callable; pin it with `ProviderConfig(model="gpt-4o-mini")`.
|
|
75
|
+
- Anthropic: `claude-sonnet-4-20250514` (retired by Anthropic on 2026-06-15) ->
|
|
76
|
+
`claude-sonnet-5` (1M context, 128K output).
|
|
77
|
+
- Gemini: `gemini-2.0-flash` (shut down by Google on 2026-06-01) ->
|
|
78
|
+
`gemini-3.6-flash` (1,048,576 context, 65,536 output).
|
|
79
|
+
- `ProviderConfig.DEFAULT_MODELS` is now the single source of truth for provider
|
|
80
|
+
defaults; the adapters, `Settings.get_provider_config()` and `nlp2sql providers list`
|
|
81
|
+
read from it.
|
|
82
|
+
- `AnthropicAdapter` no longer sends `temperature` to the Messages API: Claude 4.7+
|
|
83
|
+
models reject non-default sampling parameters (HTTP 400) and the `anthropic` SDK
|
|
84
|
+
removes the keyword in 1.0. `ProviderConfig(temperature=...)` is still accepted for
|
|
85
|
+
Anthropic but ignored (logged at INFO); explicitly pinned older Claude models now run
|
|
86
|
+
at the API default temperature.
|
|
87
|
+
- `OpenAIAdapter` sends `max_completion_tokens` instead of the deprecated `max_tokens`.
|
|
88
|
+
For reasoning models (every model outside the `gpt-3.5`, `gpt-4` and `chatgpt-4o`
|
|
89
|
+
families, including `gpt-5.6-*`) it sets `reasoning_effort` (default `low`, new
|
|
90
|
+
`reasoning_effort` constructor argument) and omits `temperature`; `gpt-4o`/`gpt-4.1`
|
|
91
|
+
keep receiving `temperature`. Response metadata gains `reasoning_effort` and
|
|
92
|
+
`reasoning_tokens`.
|
|
93
|
+
- Unknown model IDs no longer fall back to crippling context limits (OpenAI 8,192,
|
|
94
|
+
Gemini 30,720, Anthropic 100,000). They resolve by model family where possible and
|
|
95
|
+
otherwise fall back to 128,000 / 1,048,576 (Gemini family) / 200,000, logging a
|
|
96
|
+
warning when the adapter is constructed.
|
|
97
|
+
- `OpenAIAdapter` token counting maps the `gpt-5`, `gpt-4.1`, `gpt-4o` and `o1`-`o4`
|
|
98
|
+
families to `o200k_base` (tiktoken has no entry for `gpt-5.6-*`) and falls back to
|
|
99
|
+
`o200k_base`, never `cl100k_base`, for unknown IDs.
|
|
100
|
+
- `GeminiAdapter` reads token usage from `usage_metadata` instead of issuing extra
|
|
101
|
+
`count_tokens` calls after each response.
|
|
102
|
+
- Minimum dependency versions raised: `openai>=1.58.0` (`reasoning_effort`),
|
|
103
|
+
`tiktoken>=0.7.0` (`o200k_base`), `google-generativeai>=0.8.5` (`usage_metadata`).
|
|
104
|
+
|
|
105
|
+
### Fixed
|
|
106
|
+
- `connect()` / `ask()` failed out of the box for Anthropic and Gemini because their
|
|
107
|
+
default model IDs had been retired by the providers.
|
|
108
|
+
- Reasoning/thinking models that exhaust `max_tokens` before emitting content now raise
|
|
109
|
+
an actionable `ProviderException` instead of "Invalid JSON response" or
|
|
110
|
+
"Failed to parse response".
|
|
111
|
+
- `AnthropicAdapter` and `GeminiAdapter` re-raise `ProviderException` after exhausting
|
|
112
|
+
retries instead of surfacing `tenacity.RetryError`.
|
|
113
|
+
|
|
114
|
+
## [0.2.0rc14] - 2026-09-16
|
|
115
|
+
|
|
116
|
+
### Added
|
|
117
|
+
- `PgvectorExampleRepository`: a Postgres + `pgvector` implementation of
|
|
118
|
+
`ExampleRepositoryPort`, an alternative to the on-disk FAISS `ExampleStore`
|
|
119
|
+
for storing and semantically searching few-shot examples. Stores examples in
|
|
120
|
+
a single table with a `namespace` column (per-database isolation via
|
|
121
|
+
`md5(database_url:schema_name)`, byte-identical to `ExampleStore`), cosine
|
|
122
|
+
distance search over an HNSW index, and idempotent `auto_migrate` DDL.
|
|
123
|
+
- Optional `pgvector` extra: `pip install 'nlp2sql[pgvector]'`.
|
|
124
|
+
- CI: a `pgvector-integration` job that runs the adapter's integration tests
|
|
125
|
+
against a `pgvector/pgvector:pg16` service. The job fails (rather than skips)
|
|
126
|
+
when the database or `vector` extension is unavailable
|
|
127
|
+
(`NLP2SQL_REQUIRE_INTEGRATION`).
|
|
128
|
+
|
|
129
|
+
### Changed
|
|
130
|
+
- `docker/docker-compose.yml`: the `postgres` service image is now
|
|
131
|
+
`pgvector/pgvector:pg16` (drop-in replacement for `postgres:16`, adds the
|
|
132
|
+
`vector` extension) so integration tests run out of the box.
|
|
@@ -233,6 +233,22 @@ Brief description of changes and why they're needed.
|
|
|
233
233
|
4. **Documentation review** for user-facing changes
|
|
234
234
|
5. **Merge** after approval
|
|
235
235
|
|
|
236
|
+
## Releasing (maintainers)
|
|
237
|
+
|
|
238
|
+
Packages are published only from a release tag. Both publish workflows refuse to run from a branch and check that the tag name is `v` followed by the `version` in `pyproject.toml`, so the latest commit on `main` never goes to PyPI by accident.
|
|
239
|
+
|
|
240
|
+
1. **Bump the version** in every copy and move the `CHANGELOG.md` entries from `[Unreleased]` to a new `## [X.Y.Z] - YYYY-MM-DD` section. The copies are `pyproject.toml`, `src/nlp2sql/__init__.py`, `src/nlp2sql/config/settings.py`, `mcp_server/pyproject.toml` (`[project]` and `[tool.mcp]`), `mcp_server/__init__.py` and `uv.lock` (run `uv lock`). `tests/test_version_consistency.py` fails if any of them is out of sync.
|
|
241
|
+
2. **Push the bump to `main` before creating the release.** The new tag points to whatever `main` is at that moment. To check a tag name against the current version, run `python .github/scripts/verify_release_tag.py vX.Y.Z`.
|
|
242
|
+
3. **Create the GitHub Release** with a new tag `vX.Y.Z` targeting `main`. Publishing the release runs "Publish Python Package to Test PyPI" on that tag automatically.
|
|
243
|
+
4. **Run the integration tests locally** on the tagged commit, with the test databases running (see [Development Setup](#development-setup)).
|
|
244
|
+
5. **Publish to PyPI**: in **Actions**, open **Publish Python Package to PyPI**, click **Run workflow**, pick the tag under **Use workflow from** (Tags tab) and type `PRODUCTION`. From the command line:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
gh workflow run publish-pypi.yml --ref vX.Y.Z -f confirm_production=PRODUCTION
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The PyPI workflow stops before building if the run is not on a tag, if the tag has no published GitHub Release, or if the tag does not match the package version. Only its final job, which runs no project code, can request a PyPI token.
|
|
251
|
+
|
|
236
252
|
## Enterprise Contribution Guidelines
|
|
237
253
|
|
|
238
254
|
### Performance Considerations
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nlp2sql
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.0rc16
|
|
4
4
|
Summary: Enterprise-ready Natural Language to SQL converter with multi-provider support. Built for production scale (1000+ tables) with Clean Architecture.
|
|
5
5
|
Project-URL: Homepage, https://github.com/luiscarbonel1991/nlp2sql
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/luiscarbonel1991/nlp2sql/issues
|
|
@@ -26,28 +26,29 @@ Requires-Dist: azure-identity>=1.15.0
|
|
|
26
26
|
Requires-Dist: boto3>=1.34.0
|
|
27
27
|
Requires-Dist: click>=8.0.0
|
|
28
28
|
Requires-Dist: faiss-cpu>=1.7.4
|
|
29
|
-
Requires-Dist: google-generativeai>=0.
|
|
29
|
+
Requires-Dist: google-generativeai>=0.8.5
|
|
30
30
|
Requires-Dist: greenlet>=3.2.3
|
|
31
31
|
Requires-Dist: httpx>=0.25.0
|
|
32
32
|
Requires-Dist: numpy>=1.24.0
|
|
33
|
-
Requires-Dist: openai>=1.
|
|
33
|
+
Requires-Dist: openai>=1.58.0
|
|
34
34
|
Requires-Dist: pandas>=2.0.0
|
|
35
35
|
Requires-Dist: psycopg2-binary>=2.9.0
|
|
36
36
|
Requires-Dist: psycopg[binary]>=3.2.13
|
|
37
37
|
Requires-Dist: pydantic-settings>=2.0.0
|
|
38
38
|
Requires-Dist: pydantic>=2.5.0
|
|
39
|
+
Requires-Dist: pyyaml>=6.0
|
|
39
40
|
Requires-Dist: redis>=5.0.0
|
|
40
41
|
Requires-Dist: scikit-learn>=1.3.0
|
|
41
42
|
Requires-Dist: sqlalchemy-redshift>=0.7.0
|
|
42
43
|
Requires-Dist: sqlalchemy>=2.0.0
|
|
43
44
|
Requires-Dist: structlog>=24.1.0
|
|
44
45
|
Requires-Dist: tenacity>=8.2.0
|
|
45
|
-
Requires-Dist: tiktoken>=0.
|
|
46
|
+
Requires-Dist: tiktoken>=0.7.0
|
|
46
47
|
Provides-Extra: all-embeddings
|
|
47
48
|
Requires-Dist: sentence-transformers>=2.5.0; extra == 'all-embeddings'
|
|
48
49
|
Provides-Extra: all-providers
|
|
49
50
|
Requires-Dist: anthropic>=0.18.0; extra == 'all-providers'
|
|
50
|
-
Requires-Dist: google-generativeai>=0.
|
|
51
|
+
Requires-Dist: google-generativeai>=0.8.5; extra == 'all-providers'
|
|
51
52
|
Provides-Extra: anthropic
|
|
52
53
|
Requires-Dist: anthropic>=0.18.0; extra == 'anthropic'
|
|
53
54
|
Provides-Extra: dev
|
|
@@ -66,7 +67,7 @@ Provides-Extra: embeddings-local
|
|
|
66
67
|
Requires-Dist: sentence-transformers>=2.5.0; extra == 'embeddings-local'
|
|
67
68
|
Provides-Extra: embeddings-openai
|
|
68
69
|
Provides-Extra: gemini
|
|
69
|
-
Requires-Dist: google-generativeai>=0.
|
|
70
|
+
Requires-Dist: google-generativeai>=0.8.5; extra == 'gemini'
|
|
70
71
|
Provides-Extra: mssql
|
|
71
72
|
Requires-Dist: pymssql>=2.2.0; extra == 'mssql'
|
|
72
73
|
Provides-Extra: mysql
|
|
@@ -344,13 +345,13 @@ postgresql://testuser:testpass@localhost:5432/testdb
|
|
|
344
345
|
|
|
345
346
|
## Provider Comparison
|
|
346
347
|
|
|
347
|
-
| Provider | Default Model | Context Size | Best For |
|
|
348
|
-
|
|
349
|
-
| OpenAI | `gpt-
|
|
350
|
-
| Anthropic | `claude-sonnet-
|
|
351
|
-
| Gemini | `gemini-
|
|
348
|
+
| Provider | Default Model | Context Size | Max Output | Best For |
|
|
349
|
+
|----------|---------------|--------------|------------|----------|
|
|
350
|
+
| OpenAI | `gpt-5.6-luna` | 1.05M (922K input) | 128K | Fast, low-cost general purpose usage |
|
|
351
|
+
| Anthropic | `claude-sonnet-5` | 1M | 128K | Larger schemas and long prompts |
|
|
352
|
+
| Gemini | `gemini-3.6-flash` | 1M | 64K | High-volume and very large contexts |
|
|
352
353
|
|
|
353
|
-
|
|
354
|
+
Defaults are pinned snapshot IDs, not floating aliases. Override any of them through `ProviderConfig(model=...)`; for example `gpt-5.6-terra` is the higher-quality OpenAI option.
|
|
354
355
|
|
|
355
356
|
## Lower-Level API
|
|
356
357
|
|
|
@@ -264,13 +264,13 @@ postgresql://testuser:testpass@localhost:5432/testdb
|
|
|
264
264
|
|
|
265
265
|
## Provider Comparison
|
|
266
266
|
|
|
267
|
-
| Provider | Default Model | Context Size | Best For |
|
|
268
|
-
|
|
269
|
-
| OpenAI | `gpt-
|
|
270
|
-
| Anthropic | `claude-sonnet-
|
|
271
|
-
| Gemini | `gemini-
|
|
267
|
+
| Provider | Default Model | Context Size | Max Output | Best For |
|
|
268
|
+
|----------|---------------|--------------|------------|----------|
|
|
269
|
+
| OpenAI | `gpt-5.6-luna` | 1.05M (922K input) | 128K | Fast, low-cost general purpose usage |
|
|
270
|
+
| Anthropic | `claude-sonnet-5` | 1M | 128K | Larger schemas and long prompts |
|
|
271
|
+
| Gemini | `gemini-3.6-flash` | 1M | 64K | High-volume and very large contexts |
|
|
272
272
|
|
|
273
|
-
|
|
273
|
+
Defaults are pinned snapshot IDs, not floating aliases. Override any of them through `ProviderConfig(model=...)`; for example `gpt-5.6-terra` is the higher-quality OpenAI option.
|
|
274
274
|
|
|
275
275
|
## Lower-Level API
|
|
276
276
|
|