From 021d17a7baa9f68ad59aed952677f6b6ae2c818a Mon Sep 17 00:00:00 2001 From: Tyler Hoffman Date: Wed, 22 Apr 2026 10:41:13 -0400 Subject: [PATCH 1/4] Fix schema_name deprecation warning --- .../datasource/fluent/sql_datasource.py | 9 ++++-- pyproject.toml | 5 --- .../datasource/fluent/test_sql_datasources.py | 32 +++++++++++++++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/great_expectations/datasource/fluent/sql_datasource.py b/great_expectations/datasource/fluent/sql_datasource.py index 86ce699de110..bc4139e19ab4 100644 --- a/great_expectations/datasource/fluent/sql_datasource.py +++ b/great_expectations/datasource/fluent/sql_datasource.py @@ -1055,12 +1055,15 @@ class TableAsset(_SQLAsset): @pydantic.validator("schema_name", pre=True, always=True) @classmethod - def _schema_name_deprecation_warning(cls, v: str | Missing | None) -> str | Missing | None: - if v is MISSING: + def _schema_name_deprecation_warning( + cls, v: str | Missing | None, values: dict + ) -> str | Missing | None: + if v is MISSING or v is None: return v # deprecated-v1.14.0 + asset_name = values.get("name", "unknown") warnings.warn( - "`schema_name` is deprecated." + f"`schema_name` is deprecated on asset '{asset_name}'." " Pass the schema in your datasource's connection configuration instead.", category=DeprecationWarning, ) diff --git a/pyproject.toml b/pyproject.toml index 95b42e486479..a31e7b55a5e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -502,11 +502,6 @@ filterwarnings = [ # --------------------------------------- Great Expectations Deprecation Warnings ---------------------------------- "once:The condition_parser parameter is deprecated:DeprecationWarning", "once:Passing a string to the row_condition parameter is deprecated:DeprecationWarning", - # Existing cloud configs store "schema_name": null. During deserialization, Pydantic passes - # None to the validator which triggers the deprecation warning. The TableAsset.dict() override - # strips schema_name from new serializations, so these will clean up over time. - 'once:The `schema_name` argument is deprecated:DeprecationWarning', - 'once:`schema_name` is deprecated:DeprecationWarning', # --------------------------------------- TEMPORARY IGNORES -------------------------------------------------------- # The warnings in this section should be addressed (fixed or ignored) but are ignored here temporarily to help allow diff --git a/tests/datasource/fluent/test_sql_datasources.py b/tests/datasource/fluent/test_sql_datasources.py index f3d0b773a9ac..c0d6ebc0bc6f 100644 --- a/tests/datasource/fluent/test_sql_datasources.py +++ b/tests/datasource/fluent/test_sql_datasources.py @@ -13,6 +13,7 @@ from great_expectations.datasource.fluent import GxDatasourceWarning, SQLDatasource from great_expectations.datasource.fluent.sql_datasource import ( DEFAULT_INITIAL_QUOTE_CHARACTERS, + MISSING, TableAsset, to_lower_if_not_quoted, ) @@ -473,5 +474,36 @@ def test_table_name_serialization_preserves_quotes( assert serialized["table_name"] == serialized_name + @pytest.mark.parametrize( + "schema_name,expect_warning", + [ + pytest.param(MISSING, False, id="MISSING-no-warning"), + pytest.param(None, False, id="None-no-warning"), + pytest.param("public", True, id="string-warns"), + ], + ) + def test_schema_name_deprecation_warning_only_fires_for_user_provided_values( + self, + schema_name: str | None, + expect_warning: bool, + ) -> None: + with warnings.catch_warnings(record=True) as caught: + warnings.simplefilter("always") + TableAsset(name="my_asset", table_name="my_table", schema_name=schema_name) + + deprecation_warnings = [ + w for w in caught if issubclass(w.category, DeprecationWarning) and "schema_name" in str(w.message) + ] + if expect_warning: + assert len(deprecation_warnings) == 1 + assert "my_asset" in str(deprecation_warnings[0].message) + else: + assert len(deprecation_warnings) == 0 + + def test_schema_name_deprecation_warning_includes_asset_name(self) -> None: + with pytest.warns(DeprecationWarning, match=r"my_special_asset"): + TableAsset(name="my_special_asset", table_name="t", schema_name="public") + + if __name__ == "__main__": pytest.main([__file__, "-vv"]) From cbb8f5991c00af4c0e76effda7433f77f4c9c329 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:44:50 +0000 Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/datasource/fluent/test_sql_datasources.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/datasource/fluent/test_sql_datasources.py b/tests/datasource/fluent/test_sql_datasources.py index c0d6ebc0bc6f..9cfb9d498015 100644 --- a/tests/datasource/fluent/test_sql_datasources.py +++ b/tests/datasource/fluent/test_sql_datasources.py @@ -473,7 +473,6 @@ def test_table_name_serialization_preserves_quotes( serialized = table_asset.dict() assert serialized["table_name"] == serialized_name - @pytest.mark.parametrize( "schema_name,expect_warning", [ @@ -492,7 +491,9 @@ def test_schema_name_deprecation_warning_only_fires_for_user_provided_values( TableAsset(name="my_asset", table_name="my_table", schema_name=schema_name) deprecation_warnings = [ - w for w in caught if issubclass(w.category, DeprecationWarning) and "schema_name" in str(w.message) + w + for w in caught + if issubclass(w.category, DeprecationWarning) and "schema_name" in str(w.message) ] if expect_warning: assert len(deprecation_warnings) == 1 From 1cb33b4e0c280d164de1f8d0fa73ab865715d720 Mon Sep 17 00:00:00 2001 From: Tyler Hoffman Date: Wed, 22 Apr 2026 10:46:59 -0400 Subject: [PATCH 3/4] Return MISSING if schema_name is None --- great_expectations/datasource/fluent/sql_datasource.py | 2 +- tests/datasource/fluent/test_sql_datasources.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/great_expectations/datasource/fluent/sql_datasource.py b/great_expectations/datasource/fluent/sql_datasource.py index bc4139e19ab4..3ca0f29234d7 100644 --- a/great_expectations/datasource/fluent/sql_datasource.py +++ b/great_expectations/datasource/fluent/sql_datasource.py @@ -1059,7 +1059,7 @@ def _schema_name_deprecation_warning( cls, v: str | Missing | None, values: dict ) -> str | Missing | None: if v is MISSING or v is None: - return v + return MISSING # deprecated-v1.14.0 asset_name = values.get("name", "unknown") warnings.warn( diff --git a/tests/datasource/fluent/test_sql_datasources.py b/tests/datasource/fluent/test_sql_datasources.py index 9cfb9d498015..6a4f08426b3e 100644 --- a/tests/datasource/fluent/test_sql_datasources.py +++ b/tests/datasource/fluent/test_sql_datasources.py @@ -501,6 +501,12 @@ def test_schema_name_deprecation_warning_only_fires_for_user_provided_values( else: assert len(deprecation_warnings) == 0 + def test_schema_name_none_is_normalized_to_missing(self) -> None: + """Cloud configs store schema_name: null. Validator should normalize + None to MISSING so datasource-level schema fallback is preserved.""" + asset = TableAsset(name="my_asset", table_name="my_table", schema_name=None) + assert asset.schema_name is MISSING + def test_schema_name_deprecation_warning_includes_asset_name(self) -> None: with pytest.warns(DeprecationWarning, match=r"my_special_asset"): TableAsset(name="my_special_asset", table_name="t", schema_name="public") From 0bb5d5c635e1f739834c8bccff85f585b7e68014 Mon Sep 17 00:00:00 2001 From: Tyler Hoffman Date: Wed, 22 Apr 2026 10:51:27 -0400 Subject: [PATCH 4/4] Refactor test --- .../datasource/fluent/test_sql_datasources.py | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/tests/datasource/fluent/test_sql_datasources.py b/tests/datasource/fluent/test_sql_datasources.py index 6a4f08426b3e..8c0d6a70c271 100644 --- a/tests/datasource/fluent/test_sql_datasources.py +++ b/tests/datasource/fluent/test_sql_datasources.py @@ -14,6 +14,7 @@ from great_expectations.datasource.fluent.sql_datasource import ( DEFAULT_INITIAL_QUOTE_CHARACTERS, MISSING, + Missing, TableAsset, to_lower_if_not_quoted, ) @@ -474,42 +475,33 @@ def test_table_name_serialization_preserves_quotes( assert serialized["table_name"] == serialized_name @pytest.mark.parametrize( - "schema_name,expect_warning", + "schema_name", [ - pytest.param(MISSING, False, id="MISSING-no-warning"), - pytest.param(None, False, id="None-no-warning"), - pytest.param("public", True, id="string-warns"), + pytest.param(MISSING, id="MISSING"), + pytest.param(None, id="None"), ], ) - def test_schema_name_deprecation_warning_only_fires_for_user_provided_values( + def test_schema_name_non_string_values_normalize_to_missing_without_warning( self, - schema_name: str | None, - expect_warning: bool, + schema_name: Missing | None, ) -> None: with warnings.catch_warnings(record=True) as caught: warnings.simplefilter("always") - TableAsset(name="my_asset", table_name="my_table", schema_name=schema_name) + asset = TableAsset(name="my_asset", table_name="my_table", schema_name=schema_name) deprecation_warnings = [ w for w in caught if issubclass(w.category, DeprecationWarning) and "schema_name" in str(w.message) ] - if expect_warning: - assert len(deprecation_warnings) == 1 - assert "my_asset" in str(deprecation_warnings[0].message) - else: - assert len(deprecation_warnings) == 0 - - def test_schema_name_none_is_normalized_to_missing(self) -> None: - """Cloud configs store schema_name: null. Validator should normalize - None to MISSING so datasource-level schema fallback is preserved.""" - asset = TableAsset(name="my_asset", table_name="my_table", schema_name=None) + assert len(deprecation_warnings) == 0 assert asset.schema_name is MISSING - def test_schema_name_deprecation_warning_includes_asset_name(self) -> None: - with pytest.warns(DeprecationWarning, match=r"my_special_asset"): - TableAsset(name="my_special_asset", table_name="t", schema_name="public") + def test_schema_name_string_value_emits_deprecation_warning_with_asset_name(self) -> None: + with pytest.warns(DeprecationWarning, match=r"my_asset"): + asset = TableAsset(name="my_asset", table_name="my_table", schema_name="public") + + assert asset.schema_name == "public" if __name__ == "__main__":