From c78773947bcf4053dee67848a6436490969d642f Mon Sep 17 00:00:00 2001 From: ya7010 Date: Wed, 11 Mar 2026 13:25:56 +0900 Subject: [PATCH 1/3] refactor: remove SlideBuilder.tap --- src/tppt/pptx/slide.py | 5 ---- tests/test_slide.py | 40 +++++++------------------------ tests/test_table.py | 53 +----------------------------------------- 3 files changed, 9 insertions(+), 89 deletions(-) diff --git a/src/tppt/pptx/slide.py b/src/tppt/pptx/slide.py index 4f875b6..99025cf 100644 --- a/src/tppt/pptx/slide.py +++ b/src/tppt/pptx/slide.py @@ -481,11 +481,6 @@ def _register(slide: Slide) -> None: self._shape_registry.append(_register) return self - def tap(self, callback: Callable[[Slide], None]) -> Self: - """Register a callback for direct slide access.""" - self._shape_registry.append(callback) - return self - def _build(self, slide: PptxSlide) -> Slide: tppt_slide = Slide(slide) diff --git a/tests/test_slide.py b/tests/test_slide.py index 6a27ac1..af11ce8 100644 --- a/tests/test_slide.py +++ b/tests/test_slide.py @@ -81,15 +81,14 @@ def test_slide_layout_placeholders() -> None: assert pptx_placeholder is not None -def test_slide_builder_tap(output) -> None: - """Test that tap() invokes the callback with a tppt Slide wrapper.""" +def test_slide_builder_customize(output) -> None: + """Test that customize() invokes the callback with the raw slide in chain.""" callback_called = False - def my_callback(slide: tppt.pptx.slide.Slide) -> None: + def my_callback(slide: PptxSlide) -> None: nonlocal callback_called callback_called = True - assert isinstance(slide, tppt.pptx.slide.Slide) - assert slide.to_pptx() is not None + assert isinstance(slide, PptxSlide) presentation = ( tppt.Presentation.builder() @@ -97,15 +96,15 @@ def my_callback(slide: tppt.pptx.slide.Slide) -> None: lambda slide: slide.BlankLayout() .builder() .text( - "Before tap", + "Before customize", left=(100, "pt"), top=(100, "pt"), width=(200, "pt"), height=(50, "pt"), ) - .tap(my_callback) + .customize(my_callback) .text( - "After tap", + "After customize", left=(100, "pt"), top=(200, "pt"), width=(200, "pt"), @@ -117,30 +116,7 @@ def my_callback(slide: tppt.pptx.slide.Slide) -> None: assert callback_called assert len(presentation.slides[0].shapes) >= 2 - presentation.save(output / "tap_test.pptx") - - -def test_slide_builder_tap_with_raw_pptx(output) -> None: - """Test that tap() can modify the slide via the raw python-pptx API.""" - from pptx.util import Inches - - def add_raw_textbox(slide: tppt.pptx.slide.Slide) -> None: - pptx_slide = slide.to_pptx() - txBox = pptx_slide.shapes.add_textbox( - Inches(1), Inches(1), Inches(3), Inches(1) - ) - txBox.text_frame.text = "Added via tap()" - - presentation = ( - tppt.Presentation.builder() - .slide(lambda slide: slide.BlankLayout().builder().tap(add_raw_textbox)) - .build() - ) - - slide = presentation.slides[0] - texts = [getattr(shape.to_pptx(), "text", "") for shape in slide.shapes] - assert any("Added via tap()" in t for t in texts) - presentation.save(output / "tap_raw_pptx_test.pptx") + presentation.save(output / "customize_test.pptx") def test_slide_builder_customize_with_raw_pptx(output) -> None: diff --git a/tests/test_table.py b/tests/test_table.py index 2da9ecd..75f7d2a 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -16,7 +16,7 @@ Dataclass, PydanticModel, ) -from tppt.pptx.table.table import Column, ColumnCollection, Row, RowCollection +from tppt.pptx.table.table import ColumnCollection, RowCollection def test_create_table_with_list_data(output: pathlib.Path) -> None: @@ -289,48 +289,6 @@ def test_table_rows_columns_banding(output) -> None: ["4", "5", "6"], ] - def customize_table( - table: tppt.pptx.table.Table, - ) -> tppt.pptx.table.Table: - # Test rows - rows = table.rows - assert isinstance(rows, RowCollection) - assert len(rows) == 3 - row = rows[0] - assert isinstance(row, Row) - cells = row.cells - assert len(cells) == 3 - - # Test columns - columns = table.columns - assert isinstance(columns, ColumnCollection) - assert len(columns) == 3 - col = columns[0] - assert isinstance(col, Column) - - # Test banding properties with chaining - result = ( - table.set_first_row(True) - .set_last_row(False) - .set_first_col(True) - .set_last_col(False) - .set_horz_banding(True) - .set_vert_banding(False) - ) - assert result is table - assert table.first_row is True - assert table.last_row is False - assert table.first_col is True - assert table.last_col is False - assert table.horz_banding is True - assert table.vert_banding is False - - # Test iter_cells - cell_count = sum(1 for _ in table.iter_cells()) - assert cell_count == 9 # 3x3 - - return table - presentation = ( tppt.Presentation.builder() .slide( @@ -343,15 +301,6 @@ def customize_table( width=(400, "pt"), height=(200, "pt"), ) - .tap( - lambda slide: customize_table( - tppt.pptx.table.Table(slide.to_pptx().slides[0].shapes[0].table) - if hasattr(slide.to_pptx(), "slides") - else None - ) - if False - else None - ) ) .build() ) From 2e88f1fbff3f9face654f076af557c88de02992a Mon Sep 17 00:00:00 2001 From: ya7010 Date: Wed, 11 Mar 2026 14:10:32 +0900 Subject: [PATCH 2/3] refactor: remove SlideBuilder.customize --- src/tppt/pptx/slide.py | 10 +++------- tests/test_slide.py | 42 ++++++++++++++++++++++-------------------- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/src/tppt/pptx/slide.py b/src/tppt/pptx/slide.py index 99025cf..119abd1 100644 --- a/src/tppt/pptx/slide.py +++ b/src/tppt/pptx/slide.py @@ -472,13 +472,9 @@ def _register(slide: Slide) -> Shape: self._shape_registry.append(_register) return self - def customize(self, callback: Callable[[PptxSlide], None]) -> Self: - """Register a callback for direct access to the python-pptx Slide object.""" - - def _register(slide: Slide) -> None: - callback(slide.to_pptx()) - - self._shape_registry.append(_register) + def tap(self, callback: Callable[[Slide], None]) -> Self: + """Register a callback for direct slide access.""" + self._shape_registry.append(callback) return self def _build(self, slide: PptxSlide) -> Slide: diff --git a/tests/test_slide.py b/tests/test_slide.py index af11ce8..7fec65a 100644 --- a/tests/test_slide.py +++ b/tests/test_slide.py @@ -2,7 +2,6 @@ from typing import cast -from pptx.slide import Slide as PptxSlide from pptx.shapes.autoshape import Shape as PptxShape from pptx.enum.dml import MSO_FILL_TYPE from pptx.enum.shapes import MSO_AUTO_SHAPE_TYPE @@ -81,14 +80,15 @@ def test_slide_layout_placeholders() -> None: assert pptx_placeholder is not None -def test_slide_builder_customize(output) -> None: - """Test that customize() invokes the callback with the raw slide in chain.""" +def test_slide_builder_tap(output) -> None: + """Test that tap() invokes the callback with a tppt Slide wrapper.""" callback_called = False - def my_callback(slide: PptxSlide) -> None: + def my_callback(slide: tppt.pptx.slide.Slide) -> None: nonlocal callback_called callback_called = True - assert isinstance(slide, PptxSlide) + assert isinstance(slide, tppt.pptx.slide.Slide) + assert slide.to_pptx() is not None presentation = ( tppt.Presentation.builder() @@ -96,15 +96,15 @@ def my_callback(slide: PptxSlide) -> None: lambda slide: slide.BlankLayout() .builder() .text( - "Before customize", + "Before tap", left=(100, "pt"), top=(100, "pt"), width=(200, "pt"), height=(50, "pt"), ) - .customize(my_callback) + .tap(my_callback) .text( - "After customize", + "After tap", left=(100, "pt"), top=(200, "pt"), width=(200, "pt"), @@ -116,28 +116,30 @@ def my_callback(slide: PptxSlide) -> None: assert callback_called assert len(presentation.slides[0].shapes) >= 2 - presentation.save(output / "customize_test.pptx") + presentation.save(output / "tap_test.pptx") -def test_slide_builder_customize_with_raw_pptx(output) -> None: - """Test that customize() invokes the callback with the raw python-pptx Slide.""" +def test_slide_builder_tap_with_raw_pptx(output) -> None: + """Test that tap() can modify the slide via the raw python-pptx API.""" from pptx.util import Inches - def add_raw_textbox(slide: PptxSlide) -> None: - tx_box = slide.shapes.add_textbox(Inches(1), Inches(1), Inches(3), Inches(1)) - tx_box.text_frame.text = "Added via customize()" + def add_raw_textbox(slide: tppt.pptx.slide.Slide) -> None: + pptx_slide = slide.to_pptx() + tx_box = pptx_slide.shapes.add_textbox( + Inches(1), Inches(1), Inches(3), Inches(1) + ) + tx_box.text_frame.text = "Added via tap()" presentation = ( tppt.Presentation.builder() - .slide(lambda slide: slide.BlankLayout().builder().customize(add_raw_textbox)) + .slide(lambda slide: slide.BlankLayout().builder().tap(add_raw_textbox)) .build() ) - texts = [ - getattr(shape, "text", "") for shape in presentation.to_pptx().slides[0].shapes - ] - assert any("Added via customize()" in text for text in texts) - presentation.save(output / "customize_raw_pptx_test.pptx") + slide = presentation.slides[0] + texts = [getattr(shape.to_pptx(), "text", "") for shape in slide.shapes] + assert any("Added via tap()" in text for text in texts) + presentation.save(output / "tap_raw_pptx_test.pptx") def test_add_shape_with_styling_options(output) -> None: From e13f950c0967999c103a687b482544affae1a0a1 Mon Sep 17 00:00:00 2001 From: ya7010 Date: Thu, 12 Mar 2026 13:33:52 +0900 Subject: [PATCH 3/3] test: use tap in table builder test --- tests/test_table.py | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/test_table.py b/tests/test_table.py index 75f7d2a..186ab68 100644 --- a/tests/test_table.py +++ b/tests/test_table.py @@ -288,6 +288,41 @@ def test_table_rows_columns_banding(output) -> None: ["1", "2", "3"], ["4", "5", "6"], ] + callback_called = False + + def inspect_table(slide) -> None: + nonlocal callback_called + callback_called = True + + pptx_table = cast(PptxGraphicFrame, slide.to_pptx().shapes[0]).table + table = tppt.pptx.table.Table(pptx_table) + + rows = table.rows + assert isinstance(rows, RowCollection) + assert len(rows) == 3 + + columns = table.columns + assert isinstance(columns, ColumnCollection) + assert len(columns) == 3 + + result = ( + table.set_first_row(True) + .set_last_row(False) + .set_first_col(True) + .set_last_col(False) + .set_horz_banding(True) + .set_vert_banding(False) + ) + assert result is table + assert table.first_row is True + assert table.last_row is False + assert table.first_col is True + assert table.last_col is False + assert table.horz_banding is True + assert table.vert_banding is False + + cell_count = sum(1 for _ in table.iter_cells()) + assert cell_count == 9 presentation = ( tppt.Presentation.builder() @@ -301,10 +336,13 @@ def test_table_rows_columns_banding(output) -> None: width=(400, "pt"), height=(200, "pt"), ) + .tap(inspect_table) ) .build() ) + assert callback_called + # Access table from the built presentation and test pptx_pres = presentation.to_pptx() pptx_table = cast(PptxGraphicFrame, pptx_pres.slides[0].shapes[0]).table @@ -318,9 +356,12 @@ def test_table_rows_columns_banding(output) -> None: assert isinstance(columns, ColumnCollection) assert len(columns) == 3 - table.set_first_row(True).set_horz_banding(True) assert table.first_row is True + assert table.last_row is False + assert table.first_col is True + assert table.last_col is False assert table.horz_banding is True + assert table.vert_banding is False cell_count = sum(1 for _ in table.iter_cells()) assert cell_count == 9