Skip to content

Commit c430e6d

Browse files
committed
feat: add presentation tree structure output functionality
1 parent 3400530 commit c430e6d

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

examples/presentation_tree.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Sample script to output the presentation tree structure."""
2+
3+
import json
4+
5+
import tppt
6+
7+
8+
def main() -> None:
9+
presentation = (
10+
tppt.Presentation.builder()
11+
.slide(
12+
tppt.SlideBuilder().text(
13+
"Hello, world!",
14+
left=(100, "pt"),
15+
top=(100, "pt"),
16+
width=(100, "pt"),
17+
height=(100, "pt"),
18+
)
19+
)
20+
.build()
21+
)
22+
23+
# Get and display the tree structure
24+
print(
25+
json.dumps(
26+
presentation.tree,
27+
indent=2,
28+
ensure_ascii=False,
29+
)
30+
)
31+
32+
33+
if __name__ == "__main__":
34+
main()

src/tppt/_pptx/presentation.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""Presentation wrapper implementation."""
22

33
import os
4-
from typing import IO, Generic, Self
4+
from typing import IO, Any, Generic, Self
55

66
from pptx.presentation import Presentation as PptxPresentation
77

8+
from tppt._pptx.tree import presentation_to_dict
89
from tppt._tppt.slide_master import GenerictpptSlideMaster
910
from tppt.types import FilePath
1011

@@ -32,6 +33,11 @@ def slide_master(self) -> SlideMaster:
3233
"""
3334
return SlideMaster.from_pptx(self._pptx.slide_masters[0])
3435

36+
@property
37+
def tree(self) -> dict[str, Any]:
38+
"""Get the node tree of the presentation."""
39+
return presentation_to_dict(self._pptx)
40+
3541
@classmethod
3642
def builder(
3743
cls, slide_master: GenerictpptSlideMaster | None = None

src/tppt/_pptx/tree.py

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
import os
44
from typing import Any, Dict
55

6-
from pptx import Presentation
76
from pptx.enum.shapes import MSO_SHAPE_TYPE
7+
from pptx.presentation import Presentation as PptxPresentation
88

99

1010
def color_format_to_dict(color_format: Any) -> Dict[str, Any]:
@@ -188,7 +188,7 @@ def slide_master_to_dict(slide_master: Any) -> Dict[str, Any]:
188188
for layout in slide_master.slide_layouts:
189189
layout_dict = slide_layout_to_dict(layout)
190190
if slide_layouts := master_data.get("slide_layouts"):
191-
slide_layouts.append(layout_dict)
191+
slide_layouts.append(layout_dict) # type: ignore
192192

193193
return master_data
194194

@@ -227,48 +227,45 @@ def slide_to_dict(slide: Any) -> Dict[str, Any]:
227227
return slide_data
228228

229229

230-
def presentation_to_dict(pptx_path: str) -> Dict[str, Any]:
230+
def presentation_to_dict(ppt: PptxPresentation) -> Dict[str, Any]:
231231
"""Convert presentation information to dictionary"""
232-
prs = Presentation(pptx_path)
233232

234233
# スライドのサイズを安全に取得
235234
slide_width = None
236235
slide_height = None
237236

238-
if hasattr(prs, "slide_width"):
239-
if hasattr(prs.slide_width, "pt"):
240-
slide_width = prs.slide_width.pt
237+
if slide_width := getattr(ppt, "slide_width"):
238+
if pt := getattr(slide_width, "pt"):
239+
slide_width = pt
241240
else:
242-
slide_width = prs.slide_width
241+
slide_width = slide_width
243242

244-
if hasattr(prs, "slide_height"):
245-
if hasattr(prs.slide_height, "pt"):
246-
slide_height = prs.slide_height.pt
243+
if slide_height := getattr(ppt, "slide_height"):
244+
if pt := getattr(slide_height, "pt"):
245+
slide_height = pt
247246
else:
248-
slide_height = prs.slide_height
247+
slide_height = ppt.slide_height
249248

250249
prs_data = {
251-
"file_path": pptx_path,
252-
"slides_count": len(prs.slides),
253-
"slide_masters_count": len(prs.slide_masters),
254-
"slide_layouts_count": len(prs.slide_layouts),
250+
"slides_count": len(ppt.slides),
251+
"slide_masters_count": len(ppt.slide_masters),
252+
"slide_layouts_count": len(ppt.slide_layouts),
255253
"slide_width": slide_width,
256254
"slide_height": slide_height,
257-
"slides": [slide_to_dict(slide) for slide in prs.slides],
258-
"slide_masters": [slide_master_to_dict(master) for master in prs.slide_masters],
255+
"slides": [slide_to_dict(slide) for slide in ppt.slides],
256+
"slide_masters": [slide_master_to_dict(master) for master in ppt.slide_masters],
259257
}
260258

261259
# ノートマスターの情報を追加
262-
if hasattr(prs, "notes_master") and prs.notes_master is not None:
260+
if notes_master := getattr(ppt, "notes_master"):
263261
notes_placeholders = []
264-
if hasattr(prs.notes_master, "placeholders"):
262+
if placeholders := getattr(notes_master, "placeholders"):
265263
notes_placeholders = [
266-
placeholder_to_dict(placeholder)
267-
for placeholder in prs.notes_master.placeholders
264+
placeholder_to_dict(placeholder) for placeholder in placeholders
268265
]
269266

270267
prs_data["notes_master"] = {
271-
"shapes": [shape_to_dict(shape) for shape in prs.notes_master.shapes],
268+
"shapes": [shape_to_dict(shape) for shape in ppt.notes_master.shapes],
272269
"placeholders": notes_placeholders,
273270
}
274271

@@ -305,7 +302,3 @@ def main():
305302
json.dump(prs_data, f, ensure_ascii=False, indent=args.indent)
306303

307304
print(f"Structure of '{args.pptx_file}' has been output to '{output_path}'.")
308-
309-
310-
if __name__ == "__main__":
311-
main()

0 commit comments

Comments
 (0)