Skip to content

Commit 5711ad4

Browse files
author
=
committed
Fix tests and add docstrings
1 parent 8276283 commit 5711ad4

File tree

4 files changed

+34
-18
lines changed

4 files changed

+34
-18
lines changed

ci/deps/actions-310.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dependencies:
3636
- lxml>=4.9.2
3737
- matplotlib>=3.6.3
3838
- numba>=0.56.4
39-
- bodo>=2025.1 # [not win]
39+
# - bodo>=2025.1 # [not win]
4040
- numexpr>=2.8.4
4141
- odfpy>=1.4.1
4242
- qtpy>=2.3.0

pandas/core/frame.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10316,7 +10316,18 @@ def apply(
1031610316
<https://numba.pydata.org/numba-doc/dev/reference/numpysupported.html>`_
1031710317
in numba to learn what you can or cannot use in the passed function.
1031810318
10319-
TODO: describe bodo
10319+
The bodo engine will attempt to JIT compile the passed function, spawn
10320+
multiple workers and apply the function in parallel over the Dataframe,
10321+
which may result in a speedup for large DataFrames.
10322+
10323+
Bodo supports a subset of valid Python, numpy, pandas and sci-kit learn.
10324+
Please refer to the `bodo documentation
10325+
<https://docs.bodo.ai/latest/api_docs/>`_ to learn more about which
10326+
operations and APIs are supported inside JIT compiled functions.
10327+
10328+
Code that does not have JIT support yet can still utilize Bodo's parallel
10329+
constructs by decorating the function with `@wrap_python
10330+
<https://docs.bodo.ai/latest/objmode/?h=wrap_py>`_.
1032010331
1032110332
.. versionadded:: 2.2.0
1032210333

pandas/tests/apply/test_bodo.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
import numpy as np
22
import pytest
33

4-
import pandas.util._test_decorators as td
5-
64
import pandas as pd
75
import pandas._testing as tm
86

97
pytestmark = [pytest.mark.single_cpu, pytest.mark.bodo_udf_engine]
108

119

12-
@pytest.fixture
13-
def skip_if_no_bodo():
14-
"""Avoid using in test decorator which will cause bodo import immediately."""
15-
td.skip_if_no("bodo")
10+
@pytest.fixture(params=["bodo"])
11+
def engine(request):
12+
"""Test bodo engine by itself to avoid extensions conflicting with numba.
13+
14+
Note: Using a fixture here to avoid importing at the start of the session.
15+
"""
16+
if request.param == "bodo":
17+
pytest.importorskip("bodo")
18+
return request.param
1619

1720

18-
def test_bodo_vs_python_indexing(skip_if_no_bodo):
21+
def test_bodo_vs_python_indexing(engine):
1922
frame = pd.DataFrame(
2023
{"a": [1, 2, 3], "b": [4, 5, 6], "c": [7.0, 8.0, 9.0]},
2124
)
@@ -33,14 +36,14 @@ def f(a):
3336
"reduction",
3437
[lambda x: x.mean(), lambda x: x.min(), lambda x: x.max(), lambda x: x.sum()],
3538
)
36-
def test_bodo_vs_python_reductions(reduction, skip_if_no_bodo):
39+
def test_bodo_vs_python_reductions(reduction, engine):
3740
df = pd.DataFrame(np.ones((4, 4), dtype=np.float64))
3841
result = df.apply(reduction, engine="bodo", axis=1)
3942
expected = df.apply(reduction, engine="python", axis=1)
4043
tm.assert_series_equal(result, expected, check_series_type=False)
4144

4245

43-
def test_bodo_vs_python_df_output(skip_if_no_bodo):
46+
def test_bodo_vs_python_df_output(engine):
4447
df = pd.DataFrame({"A": np.arange(20), "B": ["hi", "there"] * 10})
4548

4649
def f(a):
@@ -52,7 +55,7 @@ def f(a):
5255
tm.assert_frame_equal(result, expected, check_frame_type=False, check_dtype=False)
5356

5457

55-
def test_bodo_vs_python_args(skip_if_no_bodo):
58+
def test_bodo_vs_python_args(engine):
5659
msg = (
5760
"the 'bodo' engine does not support passing additional args/kwargs "
5861
"to apply function yet."
@@ -71,7 +74,7 @@ def f(x, y):
7174

7275

7376
@pytest.mark.parametrize("axis", [0, 1])
74-
def test_bodo_vs_python_str_apply(axis, skip_if_no_bodo):
77+
def test_bodo_vs_python_str_apply(axis, engine):
7578
df = pd.DataFrame({"A": np.arange(20)})
7679

7780
func = "mean"
@@ -82,7 +85,7 @@ def test_bodo_vs_python_str_apply(axis, skip_if_no_bodo):
8285
tm.assert_series_equal(result, expected, check_series_type=False)
8386

8487

85-
def test_bodo_unsupported_axis(skip_if_no_bodo):
88+
def test_bodo_unsupported_axis(engine):
8689
"""Tests that a BodoError is raised when trying to apply UDF column-wise"""
8790
frame = pd.DataFrame(
8891
{"a": [1, 2, 3]},
@@ -98,7 +101,7 @@ def f(a):
98101
frame.apply(f, engine="bodo", axis=0)
99102

100103

101-
def test_bodo_raw_unsupported(skip_if_no_bodo):
104+
def test_bodo_raw_unsupported(engine):
102105
"""Tests that error gets raised when using raw=True"""
103106
frame = pd.DataFrame(
104107
{"a": [1, 2, 3]},
@@ -113,7 +116,7 @@ def f(a):
113116
frame.apply(f, engine="bodo", raw=True, axis=1)
114117

115118

116-
def test_bodo_result_type_unsupported(skip_if_no_bodo):
119+
def test_bodo_result_type_unsupported(engine):
117120
"""Tests that error gets raised when passing any value to result_type"""
118121
frame = pd.DataFrame(
119122
{"a": [1, 2, 3]},

pandas/tests/util/test_bodo.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99

1010
def test_bodo_not_installed_df_apply():
1111
"Test that importing bodo when not installed results in ImportError."
12-
td.skip_if_installed("bodo")
12+
bodo_installed = bool(td.import_optional_dependency("bodo", errors="ignore"))
13+
if bodo_installed:
14+
pytest.skip("bodo is installed.")
1315

1416
df = DataFrame({"A": [1, 2, 3, 4, 5]})
1517

1618
def f(x):
1719
return 1
1820

1921
with pytest.raises(ImportError, match="Missing optional"):
20-
df.apply(f, engine="bodo")
22+
df.apply(f, engine="bodo", axis=1)

0 commit comments

Comments
 (0)