Skip to content

Commit 7987954

Browse files
authored
Merge pull request #549 from jitseniesen/polars
PR: Support Polars dataframes
2 parents df33a02 + ea7df67 commit 7987954

File tree

7 files changed

+49
-5
lines changed

7 files changed

+49
-5
lines changed

requirements/tests.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ matplotlib
55
mock
66
numpy
77
pandas
8+
polars
9+
pyarrow
810
pytest
911
pytest-cov
1012
scipy

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ def get_version(module='spyder_kernels'):
5858
"mock",
5959
"numpy",
6060
"pandas",
61+
"polars",
62+
"pyarrow",
6163
"pytest",
6264
"pytest-cov",
6365
"scipy",

spyder_kernels/comms/commbase.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def to_json(self):
108108
"call_id": self.call_id,
109109
"etype": self.etype.__name__,
110110
"args": self.error.args,
111+
"error_name": getattr(self.error, "name", None),
111112
"tb": stacksummary_to_json(self.tb)
112113
}
113114

@@ -124,6 +125,8 @@ def from_json(cls, json_data):
124125
type(etype, (Exception,), {})
125126
)
126127
instance.error = instance.etype(*json_data["args"])
128+
if json_data["error_name"]:
129+
instance.error.name = json_data["error_name"]
127130
instance.tb = staksummary_from_json(json_data["tb"])
128131
return instance
129132

spyder_kernels/console/kernel.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,11 @@ def get_value(self, name, encoded=False):
375375
"""Get the value of a variable"""
376376
ns = self.shell._get_current_namespace()
377377
value = ns[name]
378+
379+
if str(type(value)) == "<class 'polars.dataframe.frame.DataFrame'>":
380+
# Convert polars dataframes to pandas
381+
value = value.to_pandas()
382+
378383
if encoded:
379384
# Encode with cloudpickle
380385
value = cloudpickle.dumps(value)

spyder_kernels/console/tests/test_console_kernel.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,17 @@ def test_get_value(kernel):
346346
assert kernel.get_value(name) == 124
347347

348348

349+
def test_get_value_with_polars(kernel):
350+
"""Test getting the value of a Polars DataFrame."""
351+
import pandas
352+
from pandas.testing import assert_frame_equal
353+
354+
command = "import polars; polars_df = polars.DataFrame({'a': [10]})"
355+
asyncio.run(kernel.do_execute(command, True))
356+
pandas_df = pandas.DataFrame({'a': [10]})
357+
assert_frame_equal(kernel.get_value('polars_df'), pandas_df)
358+
359+
349360
def test_set_value(kernel):
350361
"""Test setting the value of a variable."""
351362
name = 'a'

spyder_kernels/utils/nsview.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,10 @@ def value_to_display(value, minmax=False, level=0):
380380
display = '%s Mode: %s' % (address(value), value.mode)
381381
else:
382382
display = 'Image'
383-
elif isinstance(value, pd.DataFrame):
383+
elif (
384+
isinstance(value, pd.DataFrame)
385+
or str(type(value)) == "<class 'polars.dataframe.frame.DataFrame'>"
386+
):
384387
if level == 0:
385388
cols = value.columns
386389
cols = [str(c) for c in cols]
@@ -558,7 +561,10 @@ def get_human_readable_type(item):
558561
return "Image"
559562
else:
560563
text = get_type_string(item)
561-
return text[text.find('.')+1:]
564+
if text == 'polars.dataframe.frame.DataFrame':
565+
return 'Polars DataFrame'
566+
else:
567+
return text[text.find('.') + 1:]
562568
except Exception:
563569
return 'Unknown'
564570

spyder_kernels/utils/tests/test_nsview.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,16 @@
2525

2626
# Local imports
2727
from spyder_kernels.utils.nsview import (
28-
sort_against, is_supported, value_to_display, get_size,
29-
get_supported_types, get_type_string, get_numpy_type_string,
30-
is_editable_type)
28+
get_human_readable_type,
29+
get_numpy_type_string,
30+
get_size,
31+
get_supported_types,
32+
get_type_string,
33+
is_editable_type,
34+
is_supported,
35+
sort_against,
36+
value_to_display,
37+
)
3138

3239

3340
def generate_complex_object():
@@ -479,5 +486,13 @@ def test_get_numpy_type():
479486
assert get_numpy_type_string(df) == 'Unknown'
480487

481488

489+
def test_polars_dataframe():
490+
import polars
491+
df = polars.DataFrame({'name': ['Alice', 'Bob'], 'height': [1.77, 1.69]})
492+
assert value_to_display(df) == 'Column names: name, height'
493+
assert value_to_display(df, level=1) == 'Dataframe'
494+
assert get_human_readable_type(df) == 'Polars DataFrame'
495+
496+
482497
if __name__ == "__main__":
483498
pytest.main()

0 commit comments

Comments
 (0)