python-pptx2 2.13.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pptx2/__init__.py +152 -0
- pptx2/_color.py +75 -0
- pptx2/_slide_importer.py +597 -0
- pptx2/_svg.py +155 -0
- pptx2/_template_applier.py +292 -0
- pptx2/_textstyle.py +187 -0
- pptx2/accessibility.py +365 -0
- pptx2/action.py +270 -0
- pptx2/animation.py +2237 -0
- pptx2/api.py +49 -0
- pptx2/audit.py +258 -0
- pptx2/chart/__init__.py +0 -0
- pptx2/chart/analytics.py +381 -0
- pptx2/chart/axis.py +543 -0
- pptx2/chart/category.py +200 -0
- pptx2/chart/chart.py +670 -0
- pptx2/chart/data.py +864 -0
- pptx2/chart/datalabel.py +406 -0
- pptx2/chart/legend.py +86 -0
- pptx2/chart/marker.py +70 -0
- pptx2/chart/palettes.py +129 -0
- pptx2/chart/plot.py +462 -0
- pptx2/chart/point.py +101 -0
- pptx2/chart/quick_layouts.py +325 -0
- pptx2/chart/series.py +334 -0
- pptx2/chart/xlsx.py +272 -0
- pptx2/chart/xmlwriter.py +1845 -0
- pptx2/compose/__init__.py +28 -0
- pptx2/compose/from_spec.py +1094 -0
- pptx2/design/__init__.py +8 -0
- pptx2/design/components.py +607 -0
- pptx2/design/figures.py +389 -0
- pptx2/design/layout.py +370 -0
- pptx2/design/recipes.py +1967 -0
- pptx2/design/style.py +209 -0
- pptx2/design/tokens.py +915 -0
- pptx2/diagrams.py +754 -0
- pptx2/dml/__init__.py +0 -0
- pptx2/dml/chtfmt.py +40 -0
- pptx2/dml/color.py +496 -0
- pptx2/dml/effect.py +909 -0
- pptx2/dml/fill.py +691 -0
- pptx2/dml/line.py +287 -0
- pptx2/dml/picture.py +212 -0
- pptx2/dml/three_d.py +381 -0
- pptx2/enum/__init__.py +0 -0
- pptx2/enum/action.py +71 -0
- pptx2/enum/animation.py +31 -0
- pptx2/enum/base.py +218 -0
- pptx2/enum/chart.py +574 -0
- pptx2/enum/dml.py +740 -0
- pptx2/enum/lang.py +685 -0
- pptx2/enum/presentation.py +133 -0
- pptx2/enum/shapes.py +1029 -0
- pptx2/enum/text.py +230 -0
- pptx2/exc.py +42 -0
- pptx2/formats.py +139 -0
- pptx2/geometry.py +420 -0
- pptx2/inherit.py +109 -0
- pptx2/lint.py +2256 -0
- pptx2/math.py +177 -0
- pptx2/media.py +197 -0
- pptx2/opc/__init__.py +0 -0
- pptx2/opc/constants.py +332 -0
- pptx2/opc/oxml.py +188 -0
- pptx2/opc/package.py +762 -0
- pptx2/opc/packuri.py +109 -0
- pptx2/opc/serialized.py +296 -0
- pptx2/opc/shared.py +20 -0
- pptx2/opc/spec.py +45 -0
- pptx2/oxml/__init__.py +555 -0
- pptx2/oxml/action.py +53 -0
- pptx2/oxml/chart/__init__.py +0 -0
- pptx2/oxml/chart/axis.py +337 -0
- pptx2/oxml/chart/chart.py +481 -0
- pptx2/oxml/chart/datalabel.py +253 -0
- pptx2/oxml/chart/legend.py +72 -0
- pptx2/oxml/chart/marker.py +61 -0
- pptx2/oxml/chart/plot.py +365 -0
- pptx2/oxml/chart/series.py +425 -0
- pptx2/oxml/chart/shared.py +220 -0
- pptx2/oxml/coreprops.py +288 -0
- pptx2/oxml/dml/__init__.py +0 -0
- pptx2/oxml/dml/color.py +135 -0
- pptx2/oxml/dml/effect.py +213 -0
- pptx2/oxml/dml/fill.py +316 -0
- pptx2/oxml/dml/line.py +12 -0
- pptx2/oxml/dml/three_d.py +110 -0
- pptx2/oxml/ns.py +135 -0
- pptx2/oxml/presentation.py +313 -0
- pptx2/oxml/shapes/__init__.py +19 -0
- pptx2/oxml/shapes/autoshape.py +467 -0
- pptx2/oxml/shapes/connector.py +107 -0
- pptx2/oxml/shapes/graphfrm.py +347 -0
- pptx2/oxml/shapes/groupshape.py +329 -0
- pptx2/oxml/shapes/picture.py +270 -0
- pptx2/oxml/shapes/shared.py +577 -0
- pptx2/oxml/simpletypes.py +1027 -0
- pptx2/oxml/slide.py +563 -0
- pptx2/oxml/table.py +650 -0
- pptx2/oxml/text.py +815 -0
- pptx2/oxml/theme.py +36 -0
- pptx2/oxml/xmlchemy.py +717 -0
- pptx2/package.py +222 -0
- pptx2/parts/__init__.py +0 -0
- pptx2/parts/chart.py +95 -0
- pptx2/parts/coreprops.py +167 -0
- pptx2/parts/diagram.py +37 -0
- pptx2/parts/embeddedpackage.py +93 -0
- pptx2/parts/image.py +275 -0
- pptx2/parts/media.py +37 -0
- pptx2/parts/presentation.py +136 -0
- pptx2/parts/slide.py +371 -0
- pptx2/presentation.py +408 -0
- pptx2/py.typed +0 -0
- pptx2/render.py +586 -0
- pptx2/section.py +272 -0
- pptx2/shapes/__init__.py +26 -0
- pptx2/shapes/autoshape.py +442 -0
- pptx2/shapes/base.py +1078 -0
- pptx2/shapes/connector.py +297 -0
- pptx2/shapes/freeform.py +337 -0
- pptx2/shapes/graphfrm.py +316 -0
- pptx2/shapes/group.py +264 -0
- pptx2/shapes/picture.py +422 -0
- pptx2/shapes/placeholder.py +468 -0
- pptx2/shapes/shapetree.py +2027 -0
- pptx2/shared.py +82 -0
- pptx2/skill/SKILL.md +450 -0
- pptx2/skill/__init__.py +78 -0
- pptx2/skill/__main__.py +64 -0
- pptx2/skill/references/animations.md +189 -0
- pptx2/skill/references/basics.md +421 -0
- pptx2/skill/references/charts.md +254 -0
- pptx2/skill/references/compose.md +234 -0
- pptx2/skill/references/design.md +366 -0
- pptx2/skill/references/effects.md +249 -0
- pptx2/skill/references/end-to-end-deck.md +231 -0
- pptx2/skill/references/geometry-and-arrows.md +334 -0
- pptx2/skill/references/lint.md +275 -0
- pptx2/skill/references/math.md +86 -0
- pptx2/skill/references/picture-effects.md +129 -0
- pptx2/skill/references/render.md +151 -0
- pptx2/skill/references/smart-art.md +75 -0
- pptx2/skill/references/space-aware-authoring.md +249 -0
- pptx2/skill/references/tables.md +244 -0
- pptx2/skill/references/theme.md +127 -0
- pptx2/skill/references/three-d.md +109 -0
- pptx2/skill/references/transitions.md +100 -0
- pptx2/slide.py +1244 -0
- pptx2/smart_art.py +220 -0
- pptx2/spec.py +633 -0
- pptx2/table.py +1181 -0
- pptx2/table_styles.py +184 -0
- pptx2/templates/default.pptx +0 -0
- pptx2/templates/docx-icon.emf +0 -0
- pptx2/templates/generic-icon.emf +0 -0
- pptx2/templates/notes.xml +23 -0
- pptx2/templates/notesMaster.xml +352 -0
- pptx2/templates/pptx-icon.emf +0 -0
- pptx2/templates/theme.xml +321 -0
- pptx2/templates/xlsx-icon.emf +0 -0
- pptx2/text/__init__.py +0 -0
- pptx2/text/fonts.py +482 -0
- pptx2/text/layout.py +374 -0
- pptx2/text/text.py +1272 -0
- pptx2/theme.py +721 -0
- pptx2/types.py +36 -0
- pptx2/util.py +263 -0
- python_pptx2-2.13.0.dist-info/METADATA +351 -0
- python_pptx2-2.13.0.dist-info/RECORD +175 -0
- python_pptx2-2.13.0.dist-info/WHEEL +5 -0
- python_pptx2-2.13.0.dist-info/entry_points.txt +3 -0
- python_pptx2-2.13.0.dist-info/licenses/LICENSE +22 -0
- python_pptx2-2.13.0.dist-info/top_level.txt +1 -0
pptx2/design/style.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""Token-resolving style facade for shapes.
|
|
2
|
+
|
|
3
|
+
:class:`ShapeStyle` is the high-level "design system" view of a shape:
|
|
4
|
+
callers assign whole tokens to ``shape.style.fill`` / ``shape.style.shadow``
|
|
5
|
+
/ etc., and the facade fans the assignment out into the underlying
|
|
6
|
+
:class:`~pptx2.dml.fill.FillFormat`, :class:`~pptx2.dml.line.LineFormat`,
|
|
7
|
+
and :class:`~pptx2.dml.effect.ShadowFormat` calls.
|
|
8
|
+
|
|
9
|
+
This is purely additive — the low-level fill/line/shadow APIs continue to
|
|
10
|
+
work and are the right tool when a caller needs fine-grained control.
|
|
11
|
+
``shape.style`` exists so recipe code stays declarative::
|
|
12
|
+
|
|
13
|
+
shape.style.fill = tokens.palette["primary"]
|
|
14
|
+
shape.style.line = tokens.palette["primary"]
|
|
15
|
+
shape.style.shadow = tokens.shadows["card"]
|
|
16
|
+
shape.style.text_color = tokens.palette["neutral"]
|
|
17
|
+
shape.style.font = tokens.typography["body"]
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from typing import TYPE_CHECKING, Optional, Tuple, Union
|
|
23
|
+
|
|
24
|
+
from pptx2.design.tokens import ShadowToken, TypographyToken
|
|
25
|
+
from pptx2.dml.color import RGBColor
|
|
26
|
+
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
from pptx2.shapes.base import BaseShape
|
|
29
|
+
|
|
30
|
+
#: Anything :func:`pptx2.design.tokens._coerce_color` can turn into an RGB
|
|
31
|
+
#: triple — an :class:`RGBColor`, a 6-digit hex string (with or without
|
|
32
|
+
#: a leading ``#``), or a 3-tuple of ints.
|
|
33
|
+
ColorLike = Union[RGBColor, str, Tuple[int, int, int]]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ShapeStyle:
|
|
37
|
+
"""Style facade that resolves design tokens onto the shape's low-level proxies.
|
|
38
|
+
|
|
39
|
+
Attribute *getters* are deliberately not implemented for token-shaped
|
|
40
|
+
properties: the underlying fill/line/shadow APIs are the source of
|
|
41
|
+
truth for what's actually set, and a getter that round-trips a token
|
|
42
|
+
through the shape's XML can't faithfully reconstruct the token's
|
|
43
|
+
name. Use ``shape.fill`` / ``shape.line`` / ``shape.shadow`` for
|
|
44
|
+
reads.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(self, shape: "BaseShape"):
|
|
48
|
+
self._shape = shape
|
|
49
|
+
|
|
50
|
+
# ------------------------------------------------------------------
|
|
51
|
+
# Fill
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def fill(self) -> None:
|
|
56
|
+
raise AttributeError(
|
|
57
|
+
"ShapeStyle.fill is write-only; read shape.fill for the underlying proxy"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
@fill.setter
|
|
61
|
+
def fill(self, value: Optional[ColorLike]) -> None:
|
|
62
|
+
"""Apply a solid fill in *value* to the shape.
|
|
63
|
+
|
|
64
|
+
Accepts an :class:`RGBColor` (hex string / 3-tuple are coerced
|
|
65
|
+
the same way as :class:`pptx2.design.tokens.DesignTokens`). Pass
|
|
66
|
+
``None`` to clear the fill (transparent).
|
|
67
|
+
"""
|
|
68
|
+
from pptx2.design.tokens import _coerce_color # noqa: PLC0415
|
|
69
|
+
|
|
70
|
+
fill = self._shape.fill # type: ignore[attr-defined]
|
|
71
|
+
if value is None:
|
|
72
|
+
fill.background()
|
|
73
|
+
return
|
|
74
|
+
rgb = _coerce_color(value)
|
|
75
|
+
fill.solid()
|
|
76
|
+
fill.fore_color.rgb = rgb
|
|
77
|
+
|
|
78
|
+
# ------------------------------------------------------------------
|
|
79
|
+
# Line
|
|
80
|
+
# ------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
@property
|
|
83
|
+
def line(self) -> None:
|
|
84
|
+
raise AttributeError(
|
|
85
|
+
"ShapeStyle.line is write-only; read shape.line for the underlying proxy"
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
@line.setter
|
|
89
|
+
def line(self, value: Optional[ColorLike]) -> None:
|
|
90
|
+
"""Apply a solid line color. ``None`` clears the line."""
|
|
91
|
+
from pptx2.design.tokens import _coerce_color # noqa: PLC0415
|
|
92
|
+
|
|
93
|
+
line = self._shape.line # type: ignore[attr-defined]
|
|
94
|
+
if value is None:
|
|
95
|
+
line.fill.background()
|
|
96
|
+
return
|
|
97
|
+
rgb = _coerce_color(value)
|
|
98
|
+
line.color.rgb = rgb
|
|
99
|
+
|
|
100
|
+
# ------------------------------------------------------------------
|
|
101
|
+
# Shadow
|
|
102
|
+
# ------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def shadow(self) -> None:
|
|
106
|
+
raise AttributeError(
|
|
107
|
+
"ShapeStyle.shadow is write-only; read shape.shadow for the underlying proxy"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
@shadow.setter
|
|
111
|
+
def shadow(self, value: Optional[ShadowToken]) -> None:
|
|
112
|
+
"""Apply a :class:`ShadowToken` to the shape's outer shadow.
|
|
113
|
+
|
|
114
|
+
Each unset token attribute is left untouched on the shape, so a
|
|
115
|
+
token that only specifies ``blur_radius`` won't blow away an
|
|
116
|
+
existing distance/direction. ``None`` clears the shadow entirely.
|
|
117
|
+
"""
|
|
118
|
+
shadow = self._shape.shadow
|
|
119
|
+
if value is None:
|
|
120
|
+
shadow.blur_radius = None
|
|
121
|
+
shadow.distance = None
|
|
122
|
+
shadow.direction = None
|
|
123
|
+
return
|
|
124
|
+
if not isinstance(value, ShadowToken):
|
|
125
|
+
value = ShadowToken.from_value(value)
|
|
126
|
+
if value.blur_radius is not None:
|
|
127
|
+
shadow.blur_radius = value.blur_radius
|
|
128
|
+
if value.distance is not None:
|
|
129
|
+
shadow.distance = value.distance
|
|
130
|
+
if value.direction is not None:
|
|
131
|
+
shadow.direction = value.direction
|
|
132
|
+
if value.color is not None:
|
|
133
|
+
shadow.color.rgb = value.color
|
|
134
|
+
if value.alpha is not None:
|
|
135
|
+
# Alpha requires an explicit color to attach to. If the
|
|
136
|
+
# token didn't set one and the shape's shadow has no color
|
|
137
|
+
# yet, leave alpha alone (the shadow keeps inheriting its
|
|
138
|
+
# color, including its alpha, from the theme).
|
|
139
|
+
try:
|
|
140
|
+
shadow.color.alpha = value.alpha
|
|
141
|
+
except ValueError:
|
|
142
|
+
pass
|
|
143
|
+
|
|
144
|
+
# ------------------------------------------------------------------
|
|
145
|
+
# Text color / font (for shapes with text frames)
|
|
146
|
+
# ------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
@property
|
|
149
|
+
def text_color(self) -> None:
|
|
150
|
+
raise AttributeError(
|
|
151
|
+
"ShapeStyle.text_color is write-only; iterate runs for reads"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
@text_color.setter
|
|
155
|
+
def text_color(self, value: Optional[ColorLike]) -> None:
|
|
156
|
+
"""Set every run's font color in this shape's text frame.
|
|
157
|
+
|
|
158
|
+
Silently no-ops on shapes that don't have a text frame.
|
|
159
|
+
"""
|
|
160
|
+
from pptx2.design.tokens import _coerce_color # noqa: PLC0415
|
|
161
|
+
|
|
162
|
+
text_frame = _text_frame(self._shape)
|
|
163
|
+
if text_frame is None:
|
|
164
|
+
return
|
|
165
|
+
rgb = None if value is None else _coerce_color(value)
|
|
166
|
+
for paragraph in text_frame.paragraphs:
|
|
167
|
+
for run in paragraph.runs:
|
|
168
|
+
if rgb is None:
|
|
169
|
+
# Best-effort clear: assigning None to font.color.rgb
|
|
170
|
+
# is a no-op upstream, so leave it untouched.
|
|
171
|
+
continue
|
|
172
|
+
run.font.color.rgb = rgb
|
|
173
|
+
|
|
174
|
+
@property
|
|
175
|
+
def font(self) -> None:
|
|
176
|
+
raise AttributeError(
|
|
177
|
+
"ShapeStyle.font is write-only; iterate runs for reads"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
@font.setter
|
|
181
|
+
def font(self, value: TypographyToken) -> None:
|
|
182
|
+
"""Apply a :class:`TypographyToken` to every run in the text frame.
|
|
183
|
+
|
|
184
|
+
Unset token attributes (``size`` / ``bold`` / ``italic`` /
|
|
185
|
+
``color``) leave the run's existing values alone.
|
|
186
|
+
"""
|
|
187
|
+
if not isinstance(value, TypographyToken):
|
|
188
|
+
value = TypographyToken.from_value(value)
|
|
189
|
+
text_frame = _text_frame(self._shape)
|
|
190
|
+
if text_frame is None:
|
|
191
|
+
return
|
|
192
|
+
for paragraph in text_frame.paragraphs:
|
|
193
|
+
for run in paragraph.runs:
|
|
194
|
+
font = run.font
|
|
195
|
+
font.name = value.family
|
|
196
|
+
if value.size is not None:
|
|
197
|
+
font.size = value.size
|
|
198
|
+
if value.bold is not None:
|
|
199
|
+
font.bold = value.bold
|
|
200
|
+
if value.italic is not None:
|
|
201
|
+
font.italic = value.italic
|
|
202
|
+
if value.color is not None:
|
|
203
|
+
font.color.rgb = value.color
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
def _text_frame(shape: "BaseShape"):
|
|
207
|
+
if getattr(shape, "has_text_frame", False):
|
|
208
|
+
return shape.text_frame # type: ignore[attr-defined]
|
|
209
|
+
return None
|