Skip to content

Commit 95d9278

Browse files
refactor: Emit FutureWarning on nullable primary key (#41)
1 parent 449f806 commit 95d9278

File tree

3 files changed

+59
-6
lines changed

3 files changed

+59
-6
lines changed

dataframely/_deprecation.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,14 @@ def warn_nullable_default_change() -> None:
3737
FutureWarning,
3838
stacklevel=4,
3939
)
40+
41+
42+
@skip_if(env="DATAFRAMELY_NO_FUTURE_WARNINGS")
43+
def warn_no_nullable_primary_keys() -> None:
44+
warnings.warn(
45+
"Nullable primary keys are not supported. "
46+
"Setting `nullable=True` on a primary key column is ignored "
47+
"and will raise an error in a future release.",
48+
FutureWarning,
49+
stacklevel=4,
50+
)

dataframely/columns/_base.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
import polars as pl
1212

1313
from dataframely._compat import pa, sa, sa_TypeEngine
14-
from dataframely._deprecation import warn_nullable_default_change
14+
from dataframely._deprecation import (
15+
warn_no_nullable_primary_keys,
16+
warn_nullable_default_change,
17+
)
1518
from dataframely._polars import PolarsDataType
1619
from dataframely.random import Generator
1720

@@ -67,6 +70,10 @@ def __init__(
6770
internally sets the alias to the column's name in the parent schema.
6871
metadata: A dictionary of metadata to attach to the column.
6972
"""
73+
74+
if nullable and primary_key:
75+
warn_no_nullable_primary_keys()
76+
7077
if nullable is None:
7178
warn_nullable_default_change()
7279
nullable = True

tests/test_deprecation.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,62 @@
22
# SPDX-License-Identifier: BSD-3-Clause
33

44
import warnings
5+
from collections.abc import Callable
56

67
import pytest
78

89
import dataframely as dy
910

11+
# --------------------- Nullability default change ------------------------------#
1012

11-
def test_column_constructor_warns_about_nullable(
13+
14+
def deprecated_default_nullable() -> None:
15+
"""This function causes a FutureWarning because no value is specified for the
16+
`nullable` argument to the Column constructor."""
17+
dy.Integer()
18+
19+
20+
def test_warning_deprecated_default_nullable(
1221
monkeypatch: pytest.MonkeyPatch,
1322
) -> None:
1423
monkeypatch.setenv("DATAFRAMELY_NO_FUTURE_WARNINGS", "")
1524
with pytest.warns(
1625
FutureWarning, match="The 'nullable' argument was not explicitly set"
1726
):
18-
dy.Integer()
27+
deprecated_default_nullable()
28+
29+
30+
# ------------------------- Nullable primary key ---------------------------------#
31+
32+
33+
def deprecated_nullable_primary_key() -> None:
34+
"""This function causes a FutureWarning because both `nullable` and `primary_key`
35+
are set to `True` in the Column constructor."""
36+
dy.Integer(primary_key=True, nullable=True)
37+
38+
39+
def test_warning_deprecated_nullable_primary_key(
40+
monkeypatch: pytest.MonkeyPatch,
41+
) -> None:
42+
monkeypatch.setenv("DATAFRAMELY_NO_FUTURE_WARNINGS", "")
43+
with pytest.warns(FutureWarning, match="Nullable primary keys are not supported"):
44+
deprecated_nullable_primary_key()
1945

2046

47+
# ------------------------- Common ---------------------------------#
48+
49+
50+
@pytest.mark.parametrize(
51+
"deprecated_behavior",
52+
[deprecated_default_nullable, deprecated_nullable_primary_key],
53+
)
2154
@pytest.mark.parametrize("env_var", ["1", "True", "true"])
22-
def test_future_warning_skip(monkeypatch: pytest.MonkeyPatch, env_var: str) -> None:
55+
def test_future_warning_skip(
56+
monkeypatch: pytest.MonkeyPatch, env_var: str, deprecated_behavior: Callable
57+
) -> None:
58+
"""FutureWarnings should be avoidable by setting an environment variable."""
2359
monkeypatch.setenv("DATAFRAMELY_NO_FUTURE_WARNINGS", env_var)
24-
2560
# Elevates FutureWarning to an exception
2661
with warnings.catch_warnings():
2762
warnings.simplefilter("error", FutureWarning)
28-
dy.Integer()
63+
deprecated_behavior()

0 commit comments

Comments
 (0)