Skip to content

Commit b2cda27

Browse files
committed
feat: add support for pandas and polars DataFrames in table data handling
1 parent 982c6dc commit b2cda27

File tree

4 files changed

+237
-5
lines changed

4 files changed

+237
-5
lines changed

pyproject.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@ dependencies = [
1111
"typing-extensions>=4.13.2",
1212
]
1313

14+
[project.optional-dependencies]
15+
pandas = ["pandas>=2.0.0"]
16+
polars = ["polars>=0.20.0"]
17+
1418
[dependency-groups]
19+
dataframes = [
20+
"pandas",
21+
"polars",
22+
]
1523
dev = [
1624
"mypy>=1.15.0",
1725
"pyright>=1.1.399",

src/pptxr/_features.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from typing import TypeVar
2+
3+
from typing_extensions import TypeAlias
4+
5+
T = TypeVar("T")
6+
7+
8+
class _NotSupportFeature:
9+
pass
10+
11+
12+
try:
13+
import pandas # type: ignore[import] # noqa: F401
14+
15+
USE_PANDAS = True
16+
PandasDataFrame: TypeAlias = pandas.DataFrame # type: ignore
17+
18+
19+
except ImportError:
20+
USE_PANDAS = False
21+
PandasDataFrame: TypeAlias = _NotSupportFeature # type: ignore
22+
23+
24+
try:
25+
import polars # type: ignore[import] # noqa: F401
26+
27+
USE_POLARS = True
28+
PolarsDataFrame: TypeAlias = polars.DataFrame # type: ignore
29+
PolarsLazyFrame: TypeAlias = polars.LazyFrame # type: ignore
30+
31+
32+
except ImportError:
33+
USE_POLARS = False
34+
PolarsDataFrame: TypeAlias = _NotSupportFeature # type: ignore
35+
PolarsLazyFrame: TypeAlias = _NotSupportFeature # type: ignore

src/pptxr/_pptx/shape/table.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
"""Table wrapper implementation."""
22

3-
from typing import Literal, NotRequired, Self, TypeAlias, TypedDict
3+
from typing import Literal, NotRequired, Self, TypeAlias, TypedDict, cast
44

55
from pptx.enum.text import MSO_VERTICAL_ANCHOR, PP_ALIGN
66
from pptx.shapes.graphfrm import GraphicFrame
77

8+
from pptxr._features import (
9+
USE_PANDAS,
10+
USE_POLARS,
11+
PandasDataFrame,
12+
PolarsDataFrame,
13+
PolarsLazyFrame,
14+
)
815
from pptxr.types._length import Length, LiteralLength, LiteralPoint, Point
916

1017
from ..converter import to_pptx_length
1118
from . import Shape
1219

13-
DataFrame: TypeAlias = list[list[str]]
20+
# Define DataFrame type alias
21+
DataFrame: TypeAlias = list[list[str]] | PandasDataFrame | PolarsDataFrame
1422

1523

1624
class TableCellStyle(TypedDict):
@@ -65,12 +73,28 @@ def __init__(
6573

6674
# Apply table data if provided
6775
if "data" in props:
68-
table_data = props["data"]
76+
data = props["data"]
77+
78+
# Convert different DataFrame types to list of lists
79+
if USE_POLARS and issubclass(
80+
data.__class__, (PolarsDataFrame, PolarsLazyFrame)
81+
):
82+
# Convert pandas DataFrame to list of lists
83+
data = cast(PandasDataFrame, data)
84+
table_data = [data.columns.tolist()] + data.values.tolist()
85+
elif USE_PANDAS and issubclass(data.__class__, PandasDataFrame): # type: ignore
86+
# Convert polars DataFrame to list of lists
87+
data = cast(PandasDataFrame, data)
88+
table_data = [data.columns] + data.to_numpy().tolist()
89+
else:
90+
table_data = data
91+
92+
# Now apply the data to the table
6993
for i, row in enumerate(table_data):
7094
if i < len(table.rows):
7195
for j, cell_text in enumerate(row):
7296
if j < len(table.columns):
73-
table.cell(i, j).text = cell_text
97+
table.cell(i, j).text = str(cell_text)
7498

7599
# Apply cell styles if provided
76100
if "cell_styles" in props:

0 commit comments

Comments
 (0)