Skip to content

Commit 8100cb9

Browse files
authored
fix compatibility with pandas 3 (#747)
Co-authored-by: Christopher Rowley <github.com/cjdoris>
1 parent ef6c404 commit 8100cb9

File tree

6 files changed

+51
-33
lines changed

6 files changed

+51
-33
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44
* Added `juliacall.TypeValue.__numpy_dtype__` attribute to allow converting Julia types
55
to the corresponding NumPy dtype, like `numpy.dtype(jl.Int)`.
6+
* Bug fixes.
67

78
## 0.9.31 (2025-12-17)
89
* Restore support for Python 3.14+.

CondaPkg.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ version = ">=3.10,!=3.14.0,!=3.14.1,<4"
1616
matplotlib = ""
1717
numpy = ""
1818
pyside6 = ""
19+
pandas = ""

src/Wrap/Wrap.jl

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,18 +55,22 @@ function __init__()
5555
pyconvert_add_rule("collections.abc:Mapping", PyDict, pyconvert_rule_mapping, priority)
5656
pyconvert_add_rule("io:IOBase", PyIO, pyconvert_rule_io, priority)
5757
pyconvert_add_rule("_io:_IOBase", PyIO, pyconvert_rule_io, priority)
58-
pyconvert_add_rule(
59-
"pandas.core.frame:DataFrame",
60-
PyPandasDataFrame,
61-
pyconvert_rule_pandasdataframe,
62-
priority,
63-
)
64-
pyconvert_add_rule(
65-
"pandas.core.arrays.base:ExtensionArray",
66-
PyList,
67-
pyconvert_rule_sequence,
68-
priority,
69-
)
58+
for typename in ["pandas.core.frame:DataFrame", "pandas:DataFrame"]
59+
pyconvert_add_rule(
60+
typename,
61+
PyPandasDataFrame,
62+
pyconvert_rule_pandasdataframe,
63+
priority,
64+
)
65+
end
66+
for typename in ["pandas.core.arrays.base:ExtensionArray", "pandas.api.extensions:ExtensionArray"]
67+
pyconvert_add_rule(
68+
typename,
69+
PyList,
70+
pyconvert_rule_sequence,
71+
priority,
72+
)
73+
end
7074

7175
priority = PYCONVERT_PRIORITY_NORMAL
7276
pyconvert_add_rule("<arraystruct>", Array, pyconvert_rule_array, priority)

test/Compat.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,14 @@ end
104104
end
105105
end
106106

107-
@testitem "Tables.jl" begin
107+
@testitem "Tables.jl" setup=[Setup] begin
108108
@testset "pytable" begin
109109
x = (x = [1, 2, 3], y = ["a", "b", "c"])
110110
# pandas
111-
# TODO: install pandas and test properly
112-
@test_throws PyException pytable(x, :pandas)
111+
if Setup.devdeps
112+
y = pytable(x, :pandas)
113+
@test pyeq(Bool, pytype(y), pyimport("pandas").DataFrame)
114+
end
113115
# columns
114116
y = pytable(x, :columns)
115117
@test pyeq(Bool, y, pydict(x = [1, 2, 3], y = ["a", "b", "c"]))

test/Convert.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,19 @@ end
305305
@test_throws Exception pyconvert(Second, td(microseconds = 1000))
306306
end
307307

308+
@testitem "pandas.DataFrame → PyPandasDataFrame" setup=[Setup] begin
309+
if Setup.devdeps
310+
pd = pyimport("pandas")
311+
df = pd.DataFrame()
312+
df2 = pyconvert(PyPandasDataFrame, df)
313+
@test df2 isa PyPandasDataFrame
314+
@test pyis(df2, df)
315+
df3 = pyconvert(PyTable, df)
316+
@test df3 isa PyPandasDataFrame
317+
@test pyis(df3, df)
318+
end
319+
end
320+
308321
@testitem "pyconvert_add_rule (#364)" begin
309322
id = string(rand(UInt128), base = 16)
310323
pyexec(

test/Wrap.jl

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -458,26 +458,23 @@ end
458458
end
459459
end
460460

461-
@testitem "PyPandasDataFrame" begin
461+
@testitem "PyPandasDataFrame" setup=[Setup] begin
462462
using Tables
463463
@test PyPandasDataFrame isa Type
464-
# TODO: figure out how to get pandas into the test environment
465-
# for now use some dummy type and take advantage of the fact that the code doesn't actually check it's a real dataframe
466-
@pyexec """
467-
class DataFrame:
468-
def __init__(self, **kw):
469-
self.__dict__.update(kw)
470-
""" => DataFrame
471-
df = DataFrame(shape = (4, 3), columns = pylist(["foo", "bar", "baz"]))
472-
x = PyPandasDataFrame(df)
473-
@test ispy(x)
474-
@test Py(x) === df
475-
@test Tables.istable(x)
476-
@test Tables.columnaccess(x)
477-
@test_throws Exception Tables.columns(x)
478-
@test_throws Exception pyconvert(PyPandasDataFrame, 1)
479-
str = sprint(show, MIME("text/plain"), x)
480-
@test occursin(r"4×3 .*PyPandasDataFrame", str)
464+
if Setup.devdeps
465+
pd = pyimport("pandas")
466+
df = pd.DataFrame(pydict(foo=pylist([1,2,3,4]), bar=pylist([2,3,4,5]), baz=pylist([3,4,5,6])))
467+
x = PyPandasDataFrame(df)
468+
@test ispy(x)
469+
@test Py(x) === df
470+
@test Tables.istable(x)
471+
@test Tables.columnaccess(x)
472+
# TODO: test the tables interface more fully
473+
Tables.columns(x)
474+
@test_throws Exception pyconvert(PyPandasDataFrame, 1)
475+
str = sprint(show, MIME("text/plain"), x)
476+
@test occursin(r"4×3 .*PyPandasDataFrame", str)
477+
end
481478
end
482479

483480
@testitem "PySet" begin

0 commit comments

Comments
 (0)