sql-testing-library 0.10.0__tar.gz → 0.11.0__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.
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/CHANGELOG.md +12 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/PKG-INFO +70 -8
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/README.md +69 -7
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/pyproject.toml +1 -1
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/snowflake.py +31 -1
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_exceptions.py +14 -3
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_sql_utils.py +9 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/LICENSE +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/__init__.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/__init__.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/athena.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/base.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/bigquery.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/presto.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/redshift.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/trino.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_core.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_mock_table.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_pytest_plugin.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_sql_logger.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_types.py +0 -0
- {sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/py.typed +0 -0
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## 0.11.0 (2025-06-16)
|
|
9
|
+
|
|
10
|
+
### Feat
|
|
11
|
+
|
|
12
|
+
- **snowflake**: ad support for map datatype in snowflake (#101)
|
|
13
|
+
|
|
14
|
+
## 0.10.1 (2025-06-15)
|
|
15
|
+
|
|
16
|
+
### Fix
|
|
17
|
+
|
|
18
|
+
- run unittests against different os/python versions (#100)
|
|
19
|
+
|
|
8
20
|
## 0.10.0 (2025-06-15)
|
|
9
21
|
|
|
10
22
|
### Feat
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sql-testing-library
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: A powerful Python framework for unit testing SQL queries across BigQuery, Snowflake, Redshift, Athena, and Trino with mock data
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: sql,testing,unit-testing,mock-data,database-testing,bigquery,snowflake,redshift,athena,trino,data-engineering,etl-testing,sql-validation,query-testing
|
|
@@ -136,7 +136,7 @@ The library supports different data types across database engines. All checkmark
|
|
|
136
136
|
| **Integer Array** | `List[int]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
137
137
|
| **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
138
138
|
| **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
139
|
-
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ |
|
|
139
|
+
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
140
140
|
| **Struct/Record** | `dataclass` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
141
141
|
| **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
142
142
|
|
|
@@ -146,7 +146,7 @@ The library supports different data types across database engines. All checkmark
|
|
|
146
146
|
- **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax
|
|
147
147
|
- **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit
|
|
148
148
|
- **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays and maps
|
|
149
|
-
- **Snowflake**: Column names normalized to lowercase; 1MB query size limit
|
|
149
|
+
- **Snowflake**: Column names normalized to lowercase; 1MB query size limit; dict/map types implemented via VARIANT type (JSON parsing)
|
|
150
150
|
|
|
151
151
|
## Execution Modes Support
|
|
152
152
|
|
|
@@ -842,20 +842,83 @@ The adapter_type parameter will use the configuration from the corresponding sec
|
|
|
842
842
|
|
|
843
843
|
## Development Setup
|
|
844
844
|
|
|
845
|
+
### Quick Start with Make
|
|
846
|
+
|
|
847
|
+
The project includes a Makefile for common development tasks:
|
|
848
|
+
|
|
849
|
+
```bash
|
|
850
|
+
# Install all dependencies
|
|
851
|
+
make install
|
|
852
|
+
|
|
853
|
+
# Run unit tests
|
|
854
|
+
make test
|
|
855
|
+
|
|
856
|
+
# Run linting and type checking
|
|
857
|
+
make lint
|
|
858
|
+
|
|
859
|
+
# Format code
|
|
860
|
+
make format
|
|
861
|
+
|
|
862
|
+
# Run all checks (lint + format check + tests)
|
|
863
|
+
make check
|
|
864
|
+
|
|
865
|
+
# See all available commands
|
|
866
|
+
make help
|
|
867
|
+
```
|
|
868
|
+
|
|
869
|
+
### Available Make Commands
|
|
870
|
+
|
|
871
|
+
| Command | Description |
|
|
872
|
+
|---------|-------------|
|
|
873
|
+
| `make install` | Install all dependencies with poetry |
|
|
874
|
+
| `make test` | Run unit tests with coverage |
|
|
875
|
+
| `make test-unit` | Run unit tests (excludes integration tests) |
|
|
876
|
+
| `make test-integration` | Run integration tests (requires DB credentials) |
|
|
877
|
+
| `make test-all` | Run all tests (unit + integration) |
|
|
878
|
+
| `make test-tox` | Run tests across all Python versions (3.9-3.12) |
|
|
879
|
+
| `make lint` | Run ruff and mypy checks |
|
|
880
|
+
| `make format` | Format code with black and ruff |
|
|
881
|
+
| `make check` | Run all checks (lint + format + tests) |
|
|
882
|
+
| `make clean` | Remove build artifacts and cache files |
|
|
883
|
+
| `make build` | Build distribution packages |
|
|
884
|
+
| `make docs` | Build documentation |
|
|
885
|
+
|
|
886
|
+
### Testing Across Python Versions
|
|
887
|
+
|
|
888
|
+
The project supports Python 3.9-3.12. You can test across all versions using:
|
|
889
|
+
|
|
890
|
+
```bash
|
|
891
|
+
# Using tox (automatically tests all Python versions)
|
|
892
|
+
make test-tox
|
|
893
|
+
|
|
894
|
+
# Or directly with tox
|
|
895
|
+
tox
|
|
896
|
+
|
|
897
|
+
# Test specific Python version
|
|
898
|
+
tox -e py39 # Python 3.9
|
|
899
|
+
tox -e py310 # Python 3.10
|
|
900
|
+
tox -e py311 # Python 3.11
|
|
901
|
+
tox -e py312 # Python 3.12
|
|
902
|
+
```
|
|
903
|
+
|
|
845
904
|
### Code Quality
|
|
846
905
|
|
|
847
906
|
The project uses comprehensive tools to ensure code quality:
|
|
848
907
|
|
|
849
908
|
1. **Ruff** for linting and formatting
|
|
850
|
-
2. **
|
|
851
|
-
3. **
|
|
909
|
+
2. **Black** for code formatting
|
|
910
|
+
3. **Mypy** for static type checking
|
|
911
|
+
4. **Pre-commit hooks** for automated checks
|
|
852
912
|
|
|
853
913
|
To set up the development environment:
|
|
854
914
|
|
|
855
915
|
1. Install development dependencies:
|
|
856
916
|
```bash
|
|
857
|
-
#
|
|
858
|
-
|
|
917
|
+
# Using make
|
|
918
|
+
make install
|
|
919
|
+
|
|
920
|
+
# Or directly with poetry
|
|
921
|
+
poetry install --all-extras
|
|
859
922
|
```
|
|
860
923
|
|
|
861
924
|
2. Set up pre-commit hooks:
|
|
@@ -985,7 +1048,6 @@ The library has a few known limitations that are planned to be addressed in futu
|
|
|
985
1048
|
|
|
986
1049
|
### Snowflake Support
|
|
987
1050
|
- Physical table tests for Snowflake are currently skipped due to complex mocking requirements
|
|
988
|
-
- Need better support for Snowflake-specific data types (VARIANT, OBJECT, ARRAY)
|
|
989
1051
|
|
|
990
1052
|
### General Improvements
|
|
991
1053
|
- Add support for more SQL dialects
|
|
@@ -79,7 +79,7 @@ The library supports different data types across database engines. All checkmark
|
|
|
79
79
|
| **Integer Array** | `List[int]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
80
80
|
| **Decimal Array** | `List[Decimal]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
81
81
|
| **Optional Array** | `Optional[List[T]]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
82
|
-
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ |
|
|
82
|
+
| **Map/Dict** | `Dict[K, V]` | ✅ | ✅ | ✅ | ✅ | ✅ |
|
|
83
83
|
| **Struct/Record** | `dataclass` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
84
84
|
| **Nested Arrays** | `List[List[T]]` | ❌ | ❌ | ❌ | ❌ | ❌ |
|
|
85
85
|
|
|
@@ -89,7 +89,7 @@ The library supports different data types across database engines. All checkmark
|
|
|
89
89
|
- **Athena**: 256KB query size limit; supports arrays and maps using `ARRAY[]` and `MAP(ARRAY[], ARRAY[])` syntax
|
|
90
90
|
- **Redshift**: Arrays and maps implemented via SUPER type (JSON parsing); 16MB query size limit
|
|
91
91
|
- **Trino**: Memory catalog for testing; excellent decimal precision; supports arrays and maps
|
|
92
|
-
- **Snowflake**: Column names normalized to lowercase; 1MB query size limit
|
|
92
|
+
- **Snowflake**: Column names normalized to lowercase; 1MB query size limit; dict/map types implemented via VARIANT type (JSON parsing)
|
|
93
93
|
|
|
94
94
|
## Execution Modes Support
|
|
95
95
|
|
|
@@ -785,20 +785,83 @@ The adapter_type parameter will use the configuration from the corresponding sec
|
|
|
785
785
|
|
|
786
786
|
## Development Setup
|
|
787
787
|
|
|
788
|
+
### Quick Start with Make
|
|
789
|
+
|
|
790
|
+
The project includes a Makefile for common development tasks:
|
|
791
|
+
|
|
792
|
+
```bash
|
|
793
|
+
# Install all dependencies
|
|
794
|
+
make install
|
|
795
|
+
|
|
796
|
+
# Run unit tests
|
|
797
|
+
make test
|
|
798
|
+
|
|
799
|
+
# Run linting and type checking
|
|
800
|
+
make lint
|
|
801
|
+
|
|
802
|
+
# Format code
|
|
803
|
+
make format
|
|
804
|
+
|
|
805
|
+
# Run all checks (lint + format check + tests)
|
|
806
|
+
make check
|
|
807
|
+
|
|
808
|
+
# See all available commands
|
|
809
|
+
make help
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
### Available Make Commands
|
|
813
|
+
|
|
814
|
+
| Command | Description |
|
|
815
|
+
|---------|-------------|
|
|
816
|
+
| `make install` | Install all dependencies with poetry |
|
|
817
|
+
| `make test` | Run unit tests with coverage |
|
|
818
|
+
| `make test-unit` | Run unit tests (excludes integration tests) |
|
|
819
|
+
| `make test-integration` | Run integration tests (requires DB credentials) |
|
|
820
|
+
| `make test-all` | Run all tests (unit + integration) |
|
|
821
|
+
| `make test-tox` | Run tests across all Python versions (3.9-3.12) |
|
|
822
|
+
| `make lint` | Run ruff and mypy checks |
|
|
823
|
+
| `make format` | Format code with black and ruff |
|
|
824
|
+
| `make check` | Run all checks (lint + format + tests) |
|
|
825
|
+
| `make clean` | Remove build artifacts and cache files |
|
|
826
|
+
| `make build` | Build distribution packages |
|
|
827
|
+
| `make docs` | Build documentation |
|
|
828
|
+
|
|
829
|
+
### Testing Across Python Versions
|
|
830
|
+
|
|
831
|
+
The project supports Python 3.9-3.12. You can test across all versions using:
|
|
832
|
+
|
|
833
|
+
```bash
|
|
834
|
+
# Using tox (automatically tests all Python versions)
|
|
835
|
+
make test-tox
|
|
836
|
+
|
|
837
|
+
# Or directly with tox
|
|
838
|
+
tox
|
|
839
|
+
|
|
840
|
+
# Test specific Python version
|
|
841
|
+
tox -e py39 # Python 3.9
|
|
842
|
+
tox -e py310 # Python 3.10
|
|
843
|
+
tox -e py311 # Python 3.11
|
|
844
|
+
tox -e py312 # Python 3.12
|
|
845
|
+
```
|
|
846
|
+
|
|
788
847
|
### Code Quality
|
|
789
848
|
|
|
790
849
|
The project uses comprehensive tools to ensure code quality:
|
|
791
850
|
|
|
792
851
|
1. **Ruff** for linting and formatting
|
|
793
|
-
2. **
|
|
794
|
-
3. **
|
|
852
|
+
2. **Black** for code formatting
|
|
853
|
+
3. **Mypy** for static type checking
|
|
854
|
+
4. **Pre-commit hooks** for automated checks
|
|
795
855
|
|
|
796
856
|
To set up the development environment:
|
|
797
857
|
|
|
798
858
|
1. Install development dependencies:
|
|
799
859
|
```bash
|
|
800
|
-
#
|
|
801
|
-
|
|
860
|
+
# Using make
|
|
861
|
+
make install
|
|
862
|
+
|
|
863
|
+
# Or directly with poetry
|
|
864
|
+
poetry install --all-extras
|
|
802
865
|
```
|
|
803
866
|
|
|
804
867
|
2. Set up pre-commit hooks:
|
|
@@ -928,7 +991,6 @@ The library has a few known limitations that are planned to be addressed in futu
|
|
|
928
991
|
|
|
929
992
|
### Snowflake Support
|
|
930
993
|
- Physical table tests for Snowflake are currently skipped due to complex mocking requirements
|
|
931
|
-
- Need better support for Snowflake-specific data types (VARIANT, OBJECT, ARRAY)
|
|
932
994
|
|
|
933
995
|
### General Improvements
|
|
934
996
|
- Add support for more SQL dialects
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "sql-testing-library"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.11.0"
|
|
8
8
|
description = "A powerful Python framework for unit testing SQL queries across BigQuery, Snowflake, Redshift, Athena, and Trino with mock data"
|
|
9
9
|
authors = ["Gurmeet Saran <gurmeetx@gmail.com>", "Kushal Thakkar <kushal.thakkar@gmail.com>"]
|
|
10
10
|
maintainers = ["Gurmeet Saran <gurmeetx@gmail.com>", "Kushal Thakkar <kushal.thakkar@gmail.com>"]
|
|
@@ -30,6 +30,32 @@ class SnowflakeTypeConverter(BaseTypeConverter):
|
|
|
30
30
|
|
|
31
31
|
def convert(self, value: Any, target_type: Type) -> Any:
|
|
32
32
|
"""Convert Snowflake result value to target type."""
|
|
33
|
+
# Handle None/NULL values first
|
|
34
|
+
if value is None:
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
# Handle Optional types
|
|
38
|
+
if self.is_optional_type(target_type):
|
|
39
|
+
if value is None:
|
|
40
|
+
return None
|
|
41
|
+
target_type = self.get_optional_inner_type(target_type)
|
|
42
|
+
|
|
43
|
+
# Handle dict/map types from Snowflake VARIANT columns
|
|
44
|
+
if hasattr(target_type, "__origin__") and target_type.__origin__ is dict:
|
|
45
|
+
# Snowflake returns VARIANT types as Python dicts already
|
|
46
|
+
if isinstance(value, dict):
|
|
47
|
+
return value
|
|
48
|
+
# If it's a string, parse it
|
|
49
|
+
elif isinstance(value, str):
|
|
50
|
+
import json
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
return json.loads(value)
|
|
54
|
+
except json.JSONDecodeError:
|
|
55
|
+
return {}
|
|
56
|
+
else:
|
|
57
|
+
return {}
|
|
58
|
+
|
|
33
59
|
# Snowflake returns proper Python types in most cases, so use base converter
|
|
34
60
|
return super().convert(value, target_type)
|
|
35
61
|
|
|
@@ -248,7 +274,11 @@ class SnowflakeAdapter(DatabaseAdapter):
|
|
|
248
274
|
if non_none_types:
|
|
249
275
|
col_type = non_none_types[0]
|
|
250
276
|
|
|
251
|
-
|
|
277
|
+
# Handle dict/map types
|
|
278
|
+
if hasattr(col_type, "__origin__") and col_type.__origin__ is dict:
|
|
279
|
+
snowflake_type = "VARIANT"
|
|
280
|
+
else:
|
|
281
|
+
snowflake_type = type_mapping.get(col_type, "VARCHAR")
|
|
252
282
|
column_defs.append(f'"{col_name}" {snowflake_type}')
|
|
253
283
|
|
|
254
284
|
columns_sql = ",\n ".join(column_defs)
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_exceptions.py
RENAMED
|
@@ -50,6 +50,17 @@ class TypeConversionError(SQLTestingError):
|
|
|
50
50
|
self.value = value
|
|
51
51
|
self.target_type = target_type
|
|
52
52
|
self.column_name = column_name
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
|
|
54
|
+
# Handle type name extraction for various type forms
|
|
55
|
+
try:
|
|
56
|
+
type_name = target_type.__name__
|
|
57
|
+
except AttributeError:
|
|
58
|
+
# For types like Optional, Union, etc that don't have __name__
|
|
59
|
+
type_name = str(target_type)
|
|
60
|
+
|
|
61
|
+
if column_name:
|
|
62
|
+
message = f"Cannot convert '{value}' to {type_name} for column '{column_name}'"
|
|
63
|
+
else:
|
|
64
|
+
message = f"Cannot convert '{value}' to {type_name}"
|
|
65
|
+
|
|
66
|
+
super().__init__(message)
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_sql_utils.py
RENAMED
|
@@ -170,6 +170,9 @@ def format_sql_value(value: Any, column_type: Type, dialect: str = "standard") -
|
|
|
170
170
|
elif dialect == "bigquery":
|
|
171
171
|
# BigQuery JSON type handles NULL maps
|
|
172
172
|
return "NULL"
|
|
173
|
+
elif dialect == "snowflake":
|
|
174
|
+
# Snowflake VARIANT type handles NULL maps
|
|
175
|
+
return "NULL::VARIANT"
|
|
173
176
|
else:
|
|
174
177
|
return "NULL"
|
|
175
178
|
|
|
@@ -298,6 +301,12 @@ def format_sql_value(value: Any, column_type: Type, dialect: str = "standard") -
|
|
|
298
301
|
# Escape single quotes in JSON string for SQL
|
|
299
302
|
json_str = json_str.replace("'", "''")
|
|
300
303
|
return f"'{json_str}'"
|
|
304
|
+
elif dialect == "snowflake":
|
|
305
|
+
# Snowflake uses VARIANT type with PARSE_JSON function
|
|
306
|
+
json_str = json.dumps(value, cls=DecimalEncoder)
|
|
307
|
+
# Escape single quotes in JSON string for SQL
|
|
308
|
+
json_str = json_str.replace("'", "''")
|
|
309
|
+
return f"PARSE_JSON('{json_str}')"
|
|
301
310
|
else:
|
|
302
311
|
# Other databases don't have native map support yet
|
|
303
312
|
raise NotImplementedError(f"Map type not yet supported for dialect: {dialect}")
|
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_adapters/trino.py
RENAMED
|
File without changes
|
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_mock_table.py
RENAMED
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_pytest_plugin.py
RENAMED
|
File without changes
|
{sql_testing_library-0.10.0 → sql_testing_library-0.11.0}/src/sql_testing_library/_sql_logger.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|