Skip to content

Commit 80497f9

Browse files
committed
refactor: remove redundant constructors in ColorFormat and FillFormat classes; add LineFormat class for line formatting
1 parent 15ea4cc commit 80497f9

File tree

10 files changed

+319
-188
lines changed

10 files changed

+319
-188
lines changed

src/tppt/pptx/dml/color.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ def to_pptx_theme_color(
7979

8080

8181
class ColorFormat(PptxConvertible[PptxColorFormat]):
82-
def __init__(self, pptx_obj: PptxColorFormat, /) -> None:
83-
super().__init__(pptx_obj)
84-
8582
@property
8683
def brightness(self) -> float:
8784
"""

src/tppt/pptx/dml/fill.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
class FillFormat(PptxConvertible[PptxFillFormat]):
2020
"""Fill format."""
2121

22-
def __init__(self, pptx_obj: PptxFillFormat, /) -> None:
23-
super().__init__(pptx_obj)
24-
2522
@property
2623
def fore_color(self) -> ColorFormat:
2724
"""Fore color."""
@@ -90,9 +87,6 @@ def gradient_stops(self) -> "GradientStops":
9087
class NoFill(Fill[PptxNoFill]):
9188
"""No fill."""
9289

93-
def __init__(self, pptx_obj: PptxNoFill) -> None:
94-
super().__init__(pptx_obj)
95-
9690

9791
class PattFill(Fill[PptxPattFill]):
9892
"""Pattern fill."""

src/tppt/pptx/dml/line.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from pptx.dml.line import LineFormat as _PptxLineFormat
2+
from pptx.enum.dml import MSO_LINE_DASH_STYLE
3+
from pptx.util import Emu as _PptxEmu
4+
5+
from tppt.pptx.converter import PptxConvertible
6+
from tppt.pptx.dml.color import ColorFormat
7+
from tppt.pptx.dml.fill import FillFormat
8+
from tppt.pptx.enum.dml import LiteralLineDashStyle, to_pptx_line_dash_style
9+
from tppt.types._length import EnglishMetricUnits, to_english_metric_units
10+
11+
12+
class LineFormat(PptxConvertible[_PptxLineFormat]):
13+
"""Line format."""
14+
15+
@property
16+
def color(self) -> ColorFormat:
17+
return ColorFormat(self._pptx.color)
18+
19+
@property
20+
def dash_style(self) -> MSO_LINE_DASH_STYLE | None:
21+
return self._pptx.dash_style
22+
23+
@dash_style.setter
24+
def dash_style(
25+
self, value: MSO_LINE_DASH_STYLE | LiteralLineDashStyle | None
26+
) -> None:
27+
self._pptx.dash_style = to_pptx_line_dash_style(value)
28+
29+
@property
30+
def fill(self) -> FillFormat:
31+
return FillFormat(self._pptx.fill)
32+
33+
@property
34+
def width(self) -> EnglishMetricUnits | None:
35+
return EnglishMetricUnits(self._pptx.width)
36+
37+
@width.setter
38+
def width(self, value: EnglishMetricUnits | _PptxEmu) -> None:
39+
self._pptx.width = to_english_metric_units(value)

src/tppt/pptx/enum/dml.py

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
1-
from typing import Literal, assert_never
1+
from typing import Literal, assert_never, overload
22

3-
from pptx.enum.dml import MSO_PATTERN_TYPE
3+
from pptx.enum.dml import MSO_LINE_DASH_STYLE, MSO_PATTERN_TYPE
4+
5+
LiteralLineDashStyle = Literal[
6+
"dash",
7+
"dash_dot",
8+
"dash_dot_dot",
9+
"long_dash",
10+
"long_dash_dot",
11+
"round_dot",
12+
"solid",
13+
"square_dot",
14+
"mixed",
15+
]
416

517
LiteralPatternType = Literal[
618
"cross",
@@ -60,6 +72,48 @@
6072
]
6173

6274

75+
@overload
76+
def to_pptx_line_dash_style(
77+
dash_style: LiteralLineDashStyle | MSO_LINE_DASH_STYLE,
78+
) -> MSO_LINE_DASH_STYLE: ...
79+
80+
81+
@overload
82+
def to_pptx_line_dash_style(
83+
dash_style: LiteralLineDashStyle | MSO_LINE_DASH_STYLE | None,
84+
) -> MSO_LINE_DASH_STYLE | None: ...
85+
86+
87+
def to_pptx_line_dash_style(
88+
dash_style: LiteralLineDashStyle | MSO_LINE_DASH_STYLE | None,
89+
) -> MSO_LINE_DASH_STYLE | None:
90+
match dash_style:
91+
case None:
92+
return None
93+
case MSO_LINE_DASH_STYLE():
94+
return dash_style
95+
case "dash":
96+
return MSO_LINE_DASH_STYLE.DASH
97+
case "dash_dot":
98+
return MSO_LINE_DASH_STYLE.DASH_DOT
99+
case "dash_dot_dot":
100+
return MSO_LINE_DASH_STYLE.DASH_DOT_DOT
101+
case "long_dash":
102+
return MSO_LINE_DASH_STYLE.LONG_DASH
103+
case "long_dash_dot":
104+
return MSO_LINE_DASH_STYLE.LONG_DASH_DOT
105+
case "round_dot":
106+
return MSO_LINE_DASH_STYLE.ROUND_DOT
107+
case "solid":
108+
return MSO_LINE_DASH_STYLE.SOLID
109+
case "square_dot":
110+
return MSO_LINE_DASH_STYLE.SQUARE_DOT
111+
case "mixed":
112+
return MSO_LINE_DASH_STYLE.DASH_STYLE_MIXED
113+
case _:
114+
assert_never(dash_style)
115+
116+
63117
def to_pptx_pattern_type(
64118
pattern_type: LiteralPatternType | MSO_PATTERN_TYPE,
65119
) -> MSO_PATTERN_TYPE:

src/tppt/pptx/presentation.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import os
44
from typing import IO, TYPE_CHECKING, Any, Callable, Generic, Self, cast, overload
55

6-
from pptx.presentation import Presentation as PptxPresentation
6+
from pptx.parts.coreprops import CorePropertiesPart as _PptxCorePropertiesPart
7+
from pptx.presentation import Presentation as _PptxPresentation
8+
from pptx.slide import NotesMaster as _PptxNotesMaster
9+
from pptx.slide import _BaseMaster as _PptxBaseMaster
710

811
from tppt.pptx.tree import ppt2tree
912
from tppt.template.default import DefaultSlideMaster
@@ -17,18 +20,20 @@
1720

1821
from .converter import PptxConvertible, to_pptx_length, to_tppt_length
1922
from .slide import SlideBuilder
20-
from .slide_master import SlideMaster
2123

2224
if TYPE_CHECKING:
25+
from tppt.pptx.shape.placeholder import MasterPlaceholder
2326
from tppt.pptx.slide import Slide
2427

28+
from .slide_master import SlideMaster
2529

26-
class Presentation(PptxConvertible[PptxPresentation]):
30+
31+
class Presentation(PptxConvertible[_PptxPresentation]):
2732
"""Presentation wrapper with type safety."""
2833

2934
def __init__(
3035
self,
31-
pptx: PptxPresentation | FilePath,
36+
pptx: _PptxPresentation | FilePath,
3237
) -> None:
3338
"""Initialize presentation."""
3439
if isinstance(pptx, (os.PathLike, str)):
@@ -37,6 +42,16 @@ def __init__(
3742
pptx = Presentation(os.fspath(pptx))
3843
self._pptx = pptx
3944

45+
@property
46+
def core_properties(self) -> _PptxCorePropertiesPart:
47+
"""Get the core properties."""
48+
return self._pptx.core_properties
49+
50+
@property
51+
def notes_master(self) -> "NotesMaster":
52+
"""Get the notes master."""
53+
return NotesMaster.from_pptx(self._pptx.notes_master)
54+
4055
@property
4156
def slides(self) -> "list[Slide]":
4257
"""Get the slides."""
@@ -45,12 +60,14 @@ def slides(self) -> "list[Slide]":
4560
return [Slide.from_pptx(slide) for slide in self._pptx.slides]
4661

4762
@property
48-
def slide_master(self) -> SlideMaster:
63+
def slide_master(self) -> "SlideMaster":
4964
"""
5065
Get the slide master.
5166
5267
This tool supports only one slide master.
5368
"""
69+
from .slide_master import SlideMaster
70+
5471
return SlideMaster.from_pptx(self._pptx.slide_masters[0])
5572

5673
@property
@@ -104,12 +121,12 @@ def save(self, file: FilePath | IO[bytes]) -> None:
104121
file = os.fspath(file)
105122
self._pptx.save(file)
106123

107-
def to_pptx(self) -> PptxPresentation:
124+
def to_pptx(self) -> _PptxPresentation:
108125
"""Convert to pptx presentation."""
109126
return self._pptx
110127

111128
@classmethod
112-
def from_pptx(cls, pptx_obj: PptxPresentation) -> Self:
129+
def from_pptx(cls, pptx_obj: _PptxPresentation) -> Self:
113130
"""Create from pptx presentation."""
114131
return cls(pptx_obj)
115132

@@ -177,3 +194,22 @@ def build(self) -> Presentation:
177194
def save(self, file: FilePath | IO[bytes]) -> None:
178195
"""Save the presentation to a file."""
179196
self.build().save(file)
197+
198+
199+
class _BaseMaster(PptxConvertible[_PptxBaseMaster]):
200+
@property
201+
def placeholders(self) -> "list[MasterPlaceholder]":
202+
"""Get the placeholders."""
203+
from tppt.pptx.shape.placeholder import MasterPlaceholder
204+
205+
return [
206+
MasterPlaceholder(placeholder) for placeholder in self._pptx.placeholders
207+
]
208+
209+
210+
class NotesMaster(_BaseMaster):
211+
"""Notes master."""
212+
213+
def __init__(self, pptx_obj: _PptxNotesMaster) -> None:
214+
"""Initialize the notes master."""
215+
super().__init__(pptx_obj)

src/tppt/pptx/shape/__init__.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing import TYPE_CHECKING, Self, TypedDict
44

5+
from pptx.enum.shapes import MSO_AUTO_SHAPE_TYPE
56
from pptx.opc.package import XmlPart
67
from pptx.shapes import Subshape as PptxSubshape
78
from pptx.shapes.autoshape import Shape as PptxShape
@@ -12,7 +13,10 @@
1213
from tppt.types._length import Length, LiteralLength
1314

1415
if TYPE_CHECKING:
15-
from ..text.text_frame import TextFrame
16+
from tppt.pptx.dml.fill import FillFormat
17+
from tppt.pptx.dml.line import LineFormat
18+
from tppt.pptx.text.text_frame import TextFrame
19+
1620

1721
GenericPptxBaseShape = TypeVar(
1822
"GenericPptxBaseShape",
@@ -40,8 +44,25 @@ def from_pptx(cls, pptx_obj: GenericPptxBaseShape) -> Self:
4044

4145

4246
class Shape(BaseShape[GenericPptxShape]):
43-
def __init__(self, pptx_shape: GenericPptxShape) -> None:
44-
self._pptx: GenericPptxShape = pptx_shape
47+
@property
48+
def adjustments(self) -> list[float]:
49+
return [self._pptx.adjustments[i] for i in range(len(self._pptx.adjustments))]
50+
51+
@property
52+
def auto_shape_type(self) -> MSO_AUTO_SHAPE_TYPE | None:
53+
return self._pptx.auto_shape_type
54+
55+
@property
56+
def fill(self) -> "FillFormat":
57+
from tppt.pptx.dml.fill import FillFormat
58+
59+
return FillFormat(self._pptx.fill)
60+
61+
@property
62+
def line(self) -> "LineFormat":
63+
from tppt.pptx.dml.line import LineFormat
64+
65+
return LineFormat(self._pptx.line)
4566

4667
@property
4768
def text(self) -> str:
@@ -53,7 +74,7 @@ def text(self, text: str) -> None:
5374

5475
@property
5576
def text_frame(self) -> "TextFrame":
56-
from ..text.text_frame import TextFrame
77+
from tppt.pptx.text.text_frame import TextFrame
5778

5879
return TextFrame(self._pptx.text_frame)
5980

src/tppt/pptx/shape/placeholder.py

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
from typing import Self
2-
3-
from pptx.shapes.placeholder import LayoutPlaceholder as PptxLayoutPlaceholder
4-
from pptx.shapes.placeholder import SlidePlaceholder as PptxSlidePlaceholder
1+
from pptx.shapes.placeholder import LayoutPlaceholder as _PptxLayoutPlaceholder
2+
from pptx.shapes.placeholder import MasterPlaceholder as _PptxMasterPlaceholder
3+
from pptx.shapes.placeholder import SlidePlaceholder as _PptxSlidePlaceholder
54

65
from tppt.pptx.converter import to_pptx_length, to_tppt_length
76
from tppt.pptx.presentation import PptxConvertible
@@ -10,10 +9,13 @@
109
from . import Shape
1110

1211

13-
class SlidePlaceholder(Shape[PptxSlidePlaceholder]):
14-
def __init__(self, pptx_obj: PptxSlidePlaceholder) -> None:
15-
self._pptx = pptx_obj
12+
class LayoutPlaceholder(PptxConvertible[_PptxLayoutPlaceholder]): ...
13+
14+
15+
class MasterPlaceholder(PptxConvertible[_PptxMasterPlaceholder]): ...
1616

17+
18+
class SlidePlaceholder(Shape[_PptxSlidePlaceholder]):
1719
@property
1820
def left(self) -> Length | None:
1921
return to_tppt_length(self._pptx.left)
@@ -45,22 +47,3 @@ def width(self) -> Length | None:
4547
@width.setter
4648
def width(self, value: Length | None) -> None:
4749
self._pptx.width = to_pptx_length(value)
48-
49-
def to_pptx(self) -> PptxSlidePlaceholder:
50-
return self._pptx
51-
52-
@classmethod
53-
def from_pptx(cls, pptx_obj: PptxSlidePlaceholder) -> Self:
54-
return cls(pptx_obj)
55-
56-
57-
class LayoutPlaceholder(PptxConvertible[PptxLayoutPlaceholder]):
58-
def __init__(self, pptx_obj: PptxLayoutPlaceholder) -> None:
59-
self._pptx = pptx_obj
60-
61-
def to_pptx(self) -> PptxLayoutPlaceholder:
62-
return self._pptx
63-
64-
@classmethod
65-
def from_pptx(cls, pptx_obj: PptxLayoutPlaceholder) -> Self:
66-
return cls(pptx_obj)

0 commit comments

Comments
 (0)