nlp2sql 0.2.0rc15__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.0rc15 → nlp2sql-0.2.0rc16}/CHANGELOG.md +43 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/CONTRIBUTING.md +16 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/PKG-INFO +2 -1
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/mcp_server/__init__.py +1 -1
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/mcp_server/pyproject.toml +2 -2
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/pyproject.toml +2 -1
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/__init__.py +3 -2
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/cli.py +9 -21
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/client.py +50 -20
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/config/settings.py +1 -1
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/sql_safety.py +29 -4
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_service.py +16 -1
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/semantic_validation_service.py +24 -10
- {nlp2sql-0.2.0rc15 → 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.0rc16/tests/test_cli_setup.py +35 -0
- nlp2sql-0.2.0rc16/tests/test_connect_embeddings.py +120 -0
- 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_query_service_contract.py +87 -0
- {nlp2sql-0.2.0rc15 → 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.0rc15 → nlp2sql-0.2.0rc16}/uv.lock +3 -1
- nlp2sql-0.2.0rc15/.github/workflows/ci.yml +0 -84
- nlp2sql-0.2.0rc15/.github/workflows/publish-pypi.yml +0 -88
- nlp2sql-0.2.0rc15/.github/workflows/publish-testpypi.yml +0 -72
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/commands/db.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/commands/quality.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/commands/test.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/rules/adapters.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/rules/architecture.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/rules/python-style.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/rules/testing.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.claude/settings.json +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.gitignore +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.mcp.json.example +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/.python-version +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/CLAUDE.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/LICENSE +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/SECURITY.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/assets/nlp2sql-logo.png +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/benchmarks/enterprise_benchmark_results.json +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/.env.example +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/docker-compose.yml +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/get-db-urls.sh +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/init-schema.sql +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/large-schema.sql +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/localstack-init.sh +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docker/test-redshift.sh +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docs/API.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docs/ARCHITECTURE.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docs/CONFIGURATION.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docs/ENTERPRISE.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/docs/Redshift.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/advanced/test_multiple_providers.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/advanced/test_simple_api.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/database_specific/test_odoo_integration.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/default_examples.json +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/documentation/real_world_example.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/getting_started/basic_usage.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/getting_started/simple_demo.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/getting_started/test_api_setup.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/schema_management/test_auto_schema.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/schema_management/test_schema_filters_comprehensive.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/.dockerignore +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/.env.example +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_SETUP.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/DOCKER_TESTING_SUMMARY.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/Dockerfile +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/INDEX.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/docker/init-ecommerce-schema.sql +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/docker-compose.yml +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/main.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/pyproject.toml +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/examples/strands-fastapi-agent/test-docker-endpoints.sh +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/install-dev.sh +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/mcp_server/README.md +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/mcp_server/example_config.json +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/mcp_server/server.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/anthropic_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/default_error_classifier.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/default_repair_policy.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/dict_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/file_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/gemini_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/local_embedding_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/noop_semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/noop_semantic_validator.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/openai_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/openai_embedding_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/pgvector_example_repository.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/postgres_repository.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/redshift_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/regex_query_validator.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/adapters/schema_repository_execution_adapter.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/config/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/database_prompts.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/entities.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/provider_config.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/result.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/runtime.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/core/sql_keywords.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/exceptions/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/factories/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/factories/repository_factory.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/ai_provider.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/cache.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/embedding_provider.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/error_classifier.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/example_repository.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_execution.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_optimizer.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_safety.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/query_validator.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/repair_policy.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/schema_repository.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/schema_strategy.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/semantic_resolver.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/ports/semantic_validator.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/analyzer.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/embedding_manager.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/example_loader.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/example_store.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/schema/manager.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/example_selection_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/prompt_assembly_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_analysis_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/query_repair_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/semantic_resolution_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/services/sql_intent_planning_service.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/artifact_loader.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/helpers.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/semantic_prompt.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/src/nlp2sql/utils/storage.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/test_tmp/.gitignore +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/mcp/__init__.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/mcp/test_sql_security.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_artifact_loader.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_basic.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_batch_scoring.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_cli_semantic_support.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_client_hooks.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_column_validation.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_database_prompts.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_dsl_integration.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_embedding_manager.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_integration.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_model_defaults.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_pgvector_example_repository.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_postgres_integration.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_provider_compat_llm.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_redshift_integration.py +0 -0
- {nlp2sql-0.2.0rc15 → nlp2sql-0.2.0rc16}/tests/test_repository_cache.py +0 -0
- {nlp2sql-0.2.0rc15 → 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/
|
|
@@ -22,6 +22,49 @@ pre-1.0.
|
|
|
22
22
|
|
|
23
23
|
## [Unreleased]
|
|
24
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
|
+
|
|
25
68
|
## [0.2.0rc15] - 2026-09-18
|
|
26
69
|
|
|
27
70
|
### Changed
|
|
@@ -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
|
|
@@ -36,6 +36,7 @@ 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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nlp2sql-mcp"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.0rc16"
|
|
4
4
|
description = "MCP server for nlp2sql - Natural Language to SQL conversion"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.9"
|
|
@@ -21,4 +21,4 @@ build-backend = "hatchling.build"
|
|
|
21
21
|
[tool.mcp]
|
|
22
22
|
name = "nlp2sql"
|
|
23
23
|
description = "Convert natural language queries to SQL using multiple AI providers"
|
|
24
|
-
version = "0.2.
|
|
24
|
+
version = "0.2.0rc16"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "nlp2sql"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.0rc16"
|
|
4
4
|
description = "Enterprise-ready Natural Language to SQL converter with multi-provider support. Built for production scale (1000+ tables) with Clean Architecture."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {text = "MIT"}
|
|
@@ -43,6 +43,7 @@ dependencies = [
|
|
|
43
43
|
"pandas>=2.0.0",
|
|
44
44
|
"greenlet>=3.2.3",
|
|
45
45
|
"click>=8.0.0",
|
|
46
|
+
"pyyaml>=6.0",
|
|
46
47
|
"psycopg[binary]>=3.2.13",
|
|
47
48
|
"sqlalchemy-redshift>=0.7.0",
|
|
48
49
|
]
|
|
@@ -46,7 +46,7 @@ from .ports.semantic_validator import SemanticValidatorPort
|
|
|
46
46
|
from .schema.example_store import ExampleStore
|
|
47
47
|
from .services.query_service import QueryGenerationService
|
|
48
48
|
|
|
49
|
-
__version__ = "0.2.
|
|
49
|
+
__version__ = "0.2.0rc16"
|
|
50
50
|
__author__ = "Luis Carbonel"
|
|
51
51
|
__email__ = "devhighlevel@gmail.com"
|
|
52
52
|
|
|
@@ -303,9 +303,10 @@ def create_query_service(
|
|
|
303
303
|
if embedding_provider is None:
|
|
304
304
|
if embedding_provider_type is not None:
|
|
305
305
|
# Explicit provider requested - raise error if dependencies missing
|
|
306
|
+
# Reuse the chat key (from api_key or provider_config) only when chat is also OpenAI
|
|
306
307
|
embedding_provider = create_embedding_provider(
|
|
307
308
|
provider=embedding_provider_type,
|
|
308
|
-
api_key=
|
|
309
|
+
api_key=_api_key if embedding_provider_type == "openai" and _provider_name == "openai" else None,
|
|
309
310
|
)
|
|
310
311
|
else:
|
|
311
312
|
# No explicit provider - try local silently, fallback to None if deps missing
|
|
@@ -602,29 +602,17 @@ def _setup_database():
|
|
|
602
602
|
click.echo("\n[STATS] Database Configuration")
|
|
603
603
|
click.echo("-" * 30)
|
|
604
604
|
|
|
605
|
-
|
|
605
|
+
# Only the databases nlp2sql has adapters for
|
|
606
|
+
db_type = click.prompt("Select database type", type=click.Choice(["postgresql", "redshift"]), default="postgresql")
|
|
607
|
+
default_port = "5432" if db_type == "postgresql" else "5439"
|
|
606
608
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
database = click.prompt("Database name")
|
|
609
|
+
host = click.prompt("Host", default="localhost")
|
|
610
|
+
port = click.prompt("Port", default=default_port)
|
|
611
|
+
username = click.prompt("Username")
|
|
612
|
+
password = click.prompt("Password", hide_input=True)
|
|
613
|
+
database = click.prompt("Database name")
|
|
613
614
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
elif db_type == "mysql":
|
|
617
|
-
host = click.prompt("Host", default="localhost")
|
|
618
|
-
port = click.prompt("Port", default="3306")
|
|
619
|
-
username = click.prompt("Username")
|
|
620
|
-
password = click.prompt("Password", hide_input=True)
|
|
621
|
-
database = click.prompt("Database name")
|
|
622
|
-
|
|
623
|
-
db_url = f"mysql://{username}:{password}@{host}:{port}/{database}"
|
|
624
|
-
|
|
625
|
-
else: # sqlite
|
|
626
|
-
db_path = click.prompt("Database file path")
|
|
627
|
-
db_url = f"sqlite:///{db_path}"
|
|
615
|
+
db_url = f"{db_type}://{username}:{password}@{host}:{port}/{database}"
|
|
628
616
|
|
|
629
617
|
click.echo(f"\nNote: Connection string: {db_url}")
|
|
630
618
|
click.echo("Hint: Save this to your environment:")
|