Skip to content

Commit

Permalink
chore(python): Add various unit tests (#9903)
Browse files Browse the repository at this point in the history
  • Loading branch information
zundertj authored Jul 15, 2023
1 parent fd871eb commit ed7724c
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 10 deletions.
2 changes: 1 addition & 1 deletion py-polars/polars/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@


# dummy func required (so docs build)
def _get_float_fmt() -> str:
def _get_float_fmt() -> str: # pragma: no cover
return "n/a"


Expand Down
2 changes: 1 addition & 1 deletion py-polars/polars/utils/show_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,6 @@ def _get_dependency_version(dep_name: str) -> str:
if hasattr(module, "__version__"):
module_version = module.__version__
else:
module_version = importlib.metadata.version(dep_name)
module_version = importlib.metadata.version(dep_name) # pragma: no cover

return module_version
6 changes: 0 additions & 6 deletions py-polars/polars/utils/various.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
Int64,
Time,
Utf8,
is_polars_dtype,
unpack_dtypes,
)
from polars.dependencies import _PYARROW_AVAILABLE
Expand Down Expand Up @@ -72,11 +71,6 @@ def is_bool_sequence(val: object) -> TypeGuard[Sequence[bool]]:
return isinstance(val, Sequence) and _is_iterable_of(val, bool)


def is_dtype_sequence(val: object) -> TypeGuard[Sequence[PolarsDataType]]:
"""Check whether the given object is a sequence of polars DataTypes."""
return isinstance(val, Sequence) and all(is_polars_dtype(x) for x in val)


def is_int_sequence(val: object) -> TypeGuard[Sequence[int]]:
"""Check whether the given sequence is a sequence of integers."""
return isinstance(val, Sequence) and _is_iterable_of(val, int)
Expand Down
11 changes: 11 additions & 0 deletions py-polars/tests/unit/namespaces/test_array.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np

import polars as pl
from polars.testing import assert_frame_equal


def test_arr_min_max() -> None:
Expand All @@ -14,6 +15,16 @@ def test_arr_sum() -> None:
assert s.arr.sum().to_list() == [3, 7]


def test_arr_unique() -> None:
df = pl.DataFrame(
{"a": pl.Series("a", [[1, 1], [4, 3]], dtype=pl.Array(width=2, inner=pl.Int64))}
)

out = df.select(pl.col("a").arr.unique(maintain_order=True))
expected = pl.DataFrame({"a": [[1], [4, 3]]})
assert_frame_equal(out, expected)


def test_array_to_numpy() -> None:
s = pl.Series([[1, 2], [3, 4], [5, 6]], dtype=pl.Array(width=2, inner=pl.Int64))
assert (s.to_numpy() == np.array([[1, 2], [3, 4], [5, 6]])).all()
2 changes: 2 additions & 0 deletions py-polars/tests/unit/namespaces/test_struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def test_struct_various() -> None:
assert s[1] == {"int": 2, "str": "b", "bool": None, "list": [3]}
assert s.struct.field("list").to_list() == [[1, 2], [3]]
assert s.struct.field("int").to_list() == [1, 2]
assert s.struct["list"].to_list() == [[1, 2], [3]]
assert s.struct["int"].to_list() == [1, 2]

assert_frame_equal(df.to_struct("my_struct").struct.unnest(), df)
assert s.struct._ipython_key_completions_() == s.struct.fields
Expand Down
25 changes: 25 additions & 0 deletions py-polars/tests/unit/test_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from __future__ import annotations

import pytest

import polars as pl
from polars.testing import assert_frame_equal

Expand Down Expand Up @@ -137,3 +139,26 @@ def test_class_namespaces_are_registered() -> None:
assert (
ns in namespaces
), f"{ns!r} should be registered in {pcls.__name__}._accessors"


def test_namespace_cannot_override_builtin() -> None:
with pytest.raises(AttributeError):

@pl.api.register_dataframe_namespace("dt")
class CustomDt:
def __init__(self, df: pl.DataFrame):
self._df = df


def test_namespace_warning_on_override() -> None:
@pl.api.register_dataframe_namespace("math")
class CustomMath:
def __init__(self, df: pl.DataFrame):
self._df = df

with pytest.raises(UserWarning):

@pl.api.register_dataframe_namespace("math")
class CustomMath2:
def __init__(self, df: pl.DataFrame):
self._df = df
43 changes: 42 additions & 1 deletion py-polars/tests/unit/test_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ def test_string_cache() -> None:

@pytest.mark.write_disk()
def test_config_load_save(tmp_path: Path) -> None:
for file in (None, tmp_path / "polars.config"):
for file in (None, tmp_path / "polars.config", str(tmp_path / "polars.config")):
# set some config options...
pl.Config.set_tbl_cols(12)
pl.Config.set_verbose(True)
Expand Down Expand Up @@ -577,3 +577,44 @@ def test_config_scope() -> None:

# expect scope-exit to restore original state
assert pl.Config.state() == initial_state


def test_config_raise_error_if_not_exist() -> None:
with pytest.raises(AttributeError), pl.Config(i_do_not_exist=True):
pass


def test_config_state_env_only() -> None:
pl.Config.set_verbose(False)
pl.Config.set_fmt_float("full")

state_all = pl.Config.state(env_only=False)
state_env_only = pl.Config.state(env_only=True)
assert len(state_env_only) < len(state_all)
assert "set_fmt_float" in state_all
assert "set_fmt_float" not in state_env_only


def test_activate_decimals() -> None:
with pl.Config() as cfg:
cfg.activate_decimals(True)
assert os.environ.get("POLARS_ACTIVATE_DECIMAL") == "1"
cfg.activate_decimals(False)
assert "POLARS_ACTIVATE_DECIMAL" not in os.environ


def test_set_streaming_chunk_size() -> None:
with pl.Config() as cfg:
cfg.set_streaming_chunk_size(8)
assert os.environ.get("POLARS_STREAMING_CHUNK_SIZE") == "8"

with pytest.raises(ValueError), pl.Config() as cfg:
cfg.set_streaming_chunk_size(0)


def test_set_fmt_str_lengths_invalid_length() -> None:
with pl.Config() as cfg:
with pytest.raises(ValueError):
cfg.set_fmt_str_lengths(0)
with pytest.raises(ValueError):
cfg.set_fmt_str_lengths(-2)
15 changes: 15 additions & 0 deletions py-polars/tests/unit/test_show_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import polars as pl


def test_show_graph() -> None:
# only test raw output, otherwise we need graphviz and matplotlib
ldf = pl.LazyFrame(
{
"a": ["a", "b", "a", "b", "b", "c"],
"b": [1, 2, 3, 4, 5, 6],
"c": [6, 5, 4, 3, 2, 1],
}
)
query = ldf.groupby("a", maintain_order=True).agg(pl.all().sum()).sort("a")
out = query.show_graph(raw_output=True)
assert isinstance(out, str)
8 changes: 8 additions & 0 deletions py-polars/tests/unit/utils/test_parse_expr_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,11 @@ def test_parse_as_expression_structify() -> None:
result = wrap_expr(parse_as_expression(pl.col("a", "b"), structify=True))
expected = pl.struct("a", "b")
assert_expr_equal(result, expected)


def test_parse_as_expression_structify_multiple_outputs() -> None:
# note: this only works because assert_expr_equal evaluates on a dataframe with
# columns "a" and "b"
result = wrap_expr(parse_as_expression(pl.col("*"), structify=True))
expected = pl.struct("a", "b")
assert_expr_equal(result, expected)
13 changes: 12 additions & 1 deletion py-polars/tests/unit/utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
_timedelta_to_pl_timedelta,
)
from polars.utils.decorators import deprecate_nonkeyword_arguments, redirect
from polars.utils.various import parse_version
from polars.utils.meta import get_idx_type
from polars.utils.various import _in_notebook, parse_version

if TYPE_CHECKING:
from polars.type_aliases import TimeUnit
Expand Down Expand Up @@ -158,3 +159,13 @@ def bar(self, upper: bool = False) -> str:
return "BAZ" if upper else "baz"

assert DemoClass2().foo() == "BAZ" # type: ignore[attr-defined]


def test_get_idx_type_deprecation() -> None:
with pytest.deprecated_call():
get_idx_type()


def test_in_notebook() -> None:
# private function, but easier to test this separately and mock it in the callers
assert not _in_notebook()

0 comments on commit ed7724c

Please sign in to comment.