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/oxml/coreprops.py
ADDED
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""lxml custom element classes for core properties-related XML elements."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import datetime as dt
|
|
6
|
+
import re
|
|
7
|
+
from typing import Callable, cast
|
|
8
|
+
|
|
9
|
+
from lxml.etree import _Element # pyright: ignore[reportPrivateUsage]
|
|
10
|
+
|
|
11
|
+
from pptx2.oxml import parse_xml
|
|
12
|
+
from pptx2.oxml.ns import nsdecls, qn
|
|
13
|
+
from pptx2.oxml.xmlchemy import BaseOxmlElement, ZeroOrOne
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CT_CoreProperties(BaseOxmlElement):
|
|
17
|
+
"""`cp:coreProperties` element.
|
|
18
|
+
|
|
19
|
+
The root element of the Core Properties part stored as `/docProps/core.xml`. Implements many
|
|
20
|
+
of the Dublin Core document metadata elements. String elements resolve to an empty string ('')
|
|
21
|
+
if the element is not present in the XML. String elements are limited in length to 255 unicode
|
|
22
|
+
characters.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
get_or_add_revision: Callable[[], _Element]
|
|
26
|
+
|
|
27
|
+
category = ZeroOrOne("cp:category", successors=())
|
|
28
|
+
contentStatus = ZeroOrOne("cp:contentStatus", successors=())
|
|
29
|
+
created = ZeroOrOne("dcterms:created", successors=())
|
|
30
|
+
creator = ZeroOrOne("dc:creator", successors=())
|
|
31
|
+
description = ZeroOrOne("dc:description", successors=())
|
|
32
|
+
identifier = ZeroOrOne("dc:identifier", successors=())
|
|
33
|
+
keywords = ZeroOrOne("cp:keywords", successors=())
|
|
34
|
+
language = ZeroOrOne("dc:language", successors=())
|
|
35
|
+
lastModifiedBy = ZeroOrOne("cp:lastModifiedBy", successors=())
|
|
36
|
+
lastPrinted = ZeroOrOne("cp:lastPrinted", successors=())
|
|
37
|
+
modified = ZeroOrOne("dcterms:modified", successors=())
|
|
38
|
+
revision: _Element | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
39
|
+
"cp:revision", successors=()
|
|
40
|
+
)
|
|
41
|
+
subject = ZeroOrOne("dc:subject", successors=())
|
|
42
|
+
title = ZeroOrOne("dc:title", successors=())
|
|
43
|
+
version = ZeroOrOne("cp:version", successors=())
|
|
44
|
+
|
|
45
|
+
_coreProperties_tmpl = "<cp:coreProperties %s/>\n" % nsdecls("cp", "dc", "dcterms")
|
|
46
|
+
|
|
47
|
+
@staticmethod
|
|
48
|
+
def new_coreProperties() -> CT_CoreProperties:
|
|
49
|
+
"""Return a new `cp:coreProperties` element"""
|
|
50
|
+
return cast(CT_CoreProperties, parse_xml(CT_CoreProperties._coreProperties_tmpl))
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def author_text(self) -> str:
|
|
54
|
+
return self._text_of_element("creator")
|
|
55
|
+
|
|
56
|
+
@author_text.setter
|
|
57
|
+
def author_text(self, value: str):
|
|
58
|
+
self._set_element_text("creator", value)
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def category_text(self) -> str:
|
|
62
|
+
return self._text_of_element("category")
|
|
63
|
+
|
|
64
|
+
@category_text.setter
|
|
65
|
+
def category_text(self, value: str):
|
|
66
|
+
self._set_element_text("category", value)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def comments_text(self) -> str:
|
|
70
|
+
return self._text_of_element("description")
|
|
71
|
+
|
|
72
|
+
@comments_text.setter
|
|
73
|
+
def comments_text(self, value: str):
|
|
74
|
+
self._set_element_text("description", value)
|
|
75
|
+
|
|
76
|
+
@property
|
|
77
|
+
def contentStatus_text(self) -> str:
|
|
78
|
+
return self._text_of_element("contentStatus")
|
|
79
|
+
|
|
80
|
+
@contentStatus_text.setter
|
|
81
|
+
def contentStatus_text(self, value: str):
|
|
82
|
+
self._set_element_text("contentStatus", value)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def created_datetime(self):
|
|
86
|
+
return self._datetime_of_element("created")
|
|
87
|
+
|
|
88
|
+
@created_datetime.setter
|
|
89
|
+
def created_datetime(self, value: dt.datetime):
|
|
90
|
+
self._set_element_datetime("created", value)
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def identifier_text(self) -> str:
|
|
94
|
+
return self._text_of_element("identifier")
|
|
95
|
+
|
|
96
|
+
@identifier_text.setter
|
|
97
|
+
def identifier_text(self, value: str):
|
|
98
|
+
self._set_element_text("identifier", value)
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def keywords_text(self) -> str:
|
|
102
|
+
return self._text_of_element("keywords")
|
|
103
|
+
|
|
104
|
+
@keywords_text.setter
|
|
105
|
+
def keywords_text(self, value: str):
|
|
106
|
+
self._set_element_text("keywords", value)
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def language_text(self) -> str:
|
|
110
|
+
return self._text_of_element("language")
|
|
111
|
+
|
|
112
|
+
@language_text.setter
|
|
113
|
+
def language_text(self, value: str):
|
|
114
|
+
self._set_element_text("language", value)
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def lastModifiedBy_text(self) -> str:
|
|
118
|
+
return self._text_of_element("lastModifiedBy")
|
|
119
|
+
|
|
120
|
+
@lastModifiedBy_text.setter
|
|
121
|
+
def lastModifiedBy_text(self, value: str):
|
|
122
|
+
self._set_element_text("lastModifiedBy", value)
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def lastPrinted_datetime(self):
|
|
126
|
+
return self._datetime_of_element("lastPrinted")
|
|
127
|
+
|
|
128
|
+
@lastPrinted_datetime.setter
|
|
129
|
+
def lastPrinted_datetime(self, value: dt.datetime):
|
|
130
|
+
self._set_element_datetime("lastPrinted", value)
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def modified_datetime(self):
|
|
134
|
+
return self._datetime_of_element("modified")
|
|
135
|
+
|
|
136
|
+
@modified_datetime.setter
|
|
137
|
+
def modified_datetime(self, value: dt.datetime):
|
|
138
|
+
self._set_element_datetime("modified", value)
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def revision_number(self) -> int:
|
|
142
|
+
"""Integer value of revision property."""
|
|
143
|
+
revision = self.revision
|
|
144
|
+
if revision is None:
|
|
145
|
+
return 0
|
|
146
|
+
revision_str = revision.text
|
|
147
|
+
if revision_str is None:
|
|
148
|
+
return 0
|
|
149
|
+
try:
|
|
150
|
+
revision = int(revision_str)
|
|
151
|
+
except ValueError:
|
|
152
|
+
# -- non-integer revision strings also resolve to 0 --
|
|
153
|
+
return 0
|
|
154
|
+
# -- as do negative integers --
|
|
155
|
+
if revision < 0:
|
|
156
|
+
return 0
|
|
157
|
+
return revision
|
|
158
|
+
|
|
159
|
+
@revision_number.setter
|
|
160
|
+
def revision_number(self, value: int):
|
|
161
|
+
"""Set revision property to string value of integer `value`."""
|
|
162
|
+
if not isinstance(value, int) or value < 1: # pyright: ignore[reportUnnecessaryIsInstance]
|
|
163
|
+
tmpl = "revision property requires positive int, got '%s'"
|
|
164
|
+
raise ValueError(tmpl % value)
|
|
165
|
+
revision = self.get_or_add_revision()
|
|
166
|
+
revision.text = str(value)
|
|
167
|
+
|
|
168
|
+
@property
|
|
169
|
+
def subject_text(self) -> str:
|
|
170
|
+
return self._text_of_element("subject")
|
|
171
|
+
|
|
172
|
+
@subject_text.setter
|
|
173
|
+
def subject_text(self, value: str):
|
|
174
|
+
self._set_element_text("subject", value)
|
|
175
|
+
|
|
176
|
+
@property
|
|
177
|
+
def title_text(self) -> str:
|
|
178
|
+
return self._text_of_element("title")
|
|
179
|
+
|
|
180
|
+
@title_text.setter
|
|
181
|
+
def title_text(self, value: str):
|
|
182
|
+
self._set_element_text("title", value)
|
|
183
|
+
|
|
184
|
+
@property
|
|
185
|
+
def version_text(self) -> str:
|
|
186
|
+
return self._text_of_element("version")
|
|
187
|
+
|
|
188
|
+
@version_text.setter
|
|
189
|
+
def version_text(self, value: str):
|
|
190
|
+
self._set_element_text("version", value)
|
|
191
|
+
|
|
192
|
+
def _datetime_of_element(self, property_name: str) -> dt.datetime | None:
|
|
193
|
+
element = cast("_Element | None", getattr(self, property_name))
|
|
194
|
+
if element is None:
|
|
195
|
+
return None
|
|
196
|
+
datetime_str = element.text
|
|
197
|
+
if datetime_str is None:
|
|
198
|
+
return None
|
|
199
|
+
try:
|
|
200
|
+
return self._parse_W3CDTF_to_datetime(datetime_str)
|
|
201
|
+
except ValueError:
|
|
202
|
+
# invalid datetime strings are ignored
|
|
203
|
+
return None
|
|
204
|
+
|
|
205
|
+
def _get_or_add(self, prop_name: str):
|
|
206
|
+
"""Return element returned by 'get_or_add_' method for `prop_name`."""
|
|
207
|
+
get_or_add_method_name = "get_or_add_%s" % prop_name
|
|
208
|
+
get_or_add_method = getattr(self, get_or_add_method_name)
|
|
209
|
+
element = get_or_add_method()
|
|
210
|
+
return element
|
|
211
|
+
|
|
212
|
+
@classmethod
|
|
213
|
+
def _offset_dt(cls, datetime: dt.datetime, offset_str: str):
|
|
214
|
+
"""Return |datetime| instance offset from `datetime` by offset specified in `offset_str`.
|
|
215
|
+
|
|
216
|
+
`offset_str` is a string like `'-07:00'`.
|
|
217
|
+
"""
|
|
218
|
+
match = cls._offset_pattern.match(offset_str)
|
|
219
|
+
if match is None:
|
|
220
|
+
raise ValueError(f"{repr(offset_str)} is not a valid offset string")
|
|
221
|
+
sign, hours_str, minutes_str = match.groups()
|
|
222
|
+
sign_factor = -1 if sign == "+" else 1
|
|
223
|
+
hours = int(hours_str) * sign_factor
|
|
224
|
+
minutes = int(minutes_str) * sign_factor
|
|
225
|
+
td = dt.timedelta(hours=hours, minutes=minutes)
|
|
226
|
+
return datetime + td
|
|
227
|
+
|
|
228
|
+
_offset_pattern = re.compile(r"([+-])(\d\d):(\d\d)")
|
|
229
|
+
|
|
230
|
+
@classmethod
|
|
231
|
+
def _parse_W3CDTF_to_datetime(cls, w3cdtf_str: str) -> dt.datetime:
|
|
232
|
+
# valid W3CDTF date cases:
|
|
233
|
+
# yyyy e.g. '2003'
|
|
234
|
+
# yyyy-mm e.g. '2003-12'
|
|
235
|
+
# yyyy-mm-dd e.g. '2003-12-31'
|
|
236
|
+
# UTC timezone e.g. '2003-12-31T10:14:55Z'
|
|
237
|
+
# numeric timezone e.g. '2003-12-31T10:14:55-08:00'
|
|
238
|
+
templates = ("%Y-%m-%dT%H:%M:%S", "%Y-%m-%d", "%Y-%m", "%Y")
|
|
239
|
+
# strptime isn't smart enough to parse literal timezone offsets like
|
|
240
|
+
# '-07:30', so we have to do it ourselves
|
|
241
|
+
parseable_part = w3cdtf_str[:19]
|
|
242
|
+
offset_str = w3cdtf_str[19:]
|
|
243
|
+
timestamp = None
|
|
244
|
+
for tmpl in templates:
|
|
245
|
+
try:
|
|
246
|
+
timestamp = dt.datetime.strptime(parseable_part, tmpl)
|
|
247
|
+
except ValueError:
|
|
248
|
+
continue
|
|
249
|
+
if timestamp is None:
|
|
250
|
+
tmpl = "could not parse W3CDTF datetime string '%s'"
|
|
251
|
+
raise ValueError(tmpl % w3cdtf_str)
|
|
252
|
+
if len(offset_str) == 6:
|
|
253
|
+
return cls._offset_dt(timestamp, offset_str)
|
|
254
|
+
return timestamp
|
|
255
|
+
|
|
256
|
+
def _set_element_datetime(self, prop_name: str, value: dt.datetime) -> None:
|
|
257
|
+
"""Set date/time value of child element having `prop_name` to `value`."""
|
|
258
|
+
if not isinstance(value, dt.datetime): # pyright: ignore[reportUnnecessaryIsInstance]
|
|
259
|
+
tmpl = "property requires <type 'datetime.datetime'> object, got %s"
|
|
260
|
+
raise ValueError(tmpl % type(value))
|
|
261
|
+
element = self._get_or_add(prop_name)
|
|
262
|
+
dt_str = value.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
263
|
+
element.text = dt_str
|
|
264
|
+
if prop_name in ("created", "modified"):
|
|
265
|
+
# These two require an explicit 'xsi:type="dcterms:W3CDTF"'
|
|
266
|
+
# attribute. The first and last line are a hack required to add
|
|
267
|
+
# the xsi namespace to the root element rather than each child
|
|
268
|
+
# element in which it is referenced
|
|
269
|
+
self.set(qn("xsi:foo"), "bar")
|
|
270
|
+
element.set(qn("xsi:type"), "dcterms:W3CDTF")
|
|
271
|
+
del self.attrib[qn("xsi:foo")]
|
|
272
|
+
|
|
273
|
+
def _set_element_text(self, prop_name: str, value: str) -> None:
|
|
274
|
+
"""Set string value of `name` property to `value`."""
|
|
275
|
+
value = str(value)
|
|
276
|
+
if len(value) > 255:
|
|
277
|
+
tmpl = "exceeded 255 char limit for property, got:\n\n'%s'"
|
|
278
|
+
raise ValueError(tmpl % value)
|
|
279
|
+
element = self._get_or_add(prop_name)
|
|
280
|
+
element.text = value
|
|
281
|
+
|
|
282
|
+
def _text_of_element(self, property_name: str) -> str:
|
|
283
|
+
element = getattr(self, property_name)
|
|
284
|
+
if element is None:
|
|
285
|
+
return ""
|
|
286
|
+
if element.text is None:
|
|
287
|
+
return ""
|
|
288
|
+
return element.text
|
|
File without changes
|
pptx2/oxml/dml/color.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""lxml custom element classes for DrawingML-related XML elements."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pptx2.enum.dml import MSO_THEME_COLOR
|
|
6
|
+
from pptx2.oxml.simpletypes import ST_HexColorRGB, ST_Percentage, ST_PositiveFixedPercentage
|
|
7
|
+
from pptx2.oxml.xmlchemy import (
|
|
8
|
+
BaseOxmlElement,
|
|
9
|
+
Choice,
|
|
10
|
+
RequiredAttribute,
|
|
11
|
+
ZeroOrOne,
|
|
12
|
+
ZeroOrOneChoice,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class _BaseColorElement(BaseOxmlElement):
|
|
17
|
+
"""
|
|
18
|
+
Base class for <a:srgbClr> and <a:schemeClr> elements.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
lumMod = ZeroOrOne("a:lumMod")
|
|
22
|
+
lumOff = ZeroOrOne("a:lumOff")
|
|
23
|
+
alpha = ZeroOrOne("a:alpha")
|
|
24
|
+
|
|
25
|
+
def add_lumMod(self, value):
|
|
26
|
+
"""
|
|
27
|
+
Return a newly added <a:lumMod> child element.
|
|
28
|
+
"""
|
|
29
|
+
lumMod = self._add_lumMod()
|
|
30
|
+
lumMod.val = value
|
|
31
|
+
return lumMod
|
|
32
|
+
|
|
33
|
+
def add_lumOff(self, value):
|
|
34
|
+
"""
|
|
35
|
+
Return a newly added <a:lumOff> child element.
|
|
36
|
+
"""
|
|
37
|
+
lumOff = self._add_lumOff()
|
|
38
|
+
lumOff.val = value
|
|
39
|
+
return lumOff
|
|
40
|
+
|
|
41
|
+
def add_alpha(self, value):
|
|
42
|
+
"""Return a newly added `<a:alpha>` child element with `val` attribute set to `value`.
|
|
43
|
+
|
|
44
|
+
`value` is a float in the range [0.0, 1.0] where 1.0 is fully opaque.
|
|
45
|
+
"""
|
|
46
|
+
alpha = self._add_alpha()
|
|
47
|
+
alpha.val = value
|
|
48
|
+
return alpha
|
|
49
|
+
|
|
50
|
+
def clear_alpha(self):
|
|
51
|
+
"""Return self after removing any `<a:alpha>` child element."""
|
|
52
|
+
self._remove_alpha()
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def clear_lum(self):
|
|
56
|
+
"""
|
|
57
|
+
Return self after removing any <a:lumMod> and <a:lumOff> child
|
|
58
|
+
elements.
|
|
59
|
+
"""
|
|
60
|
+
self._remove_lumMod()
|
|
61
|
+
self._remove_lumOff()
|
|
62
|
+
return self
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class CT_Color(BaseOxmlElement):
|
|
66
|
+
"""Custom element class for `a:fgClr`, `a:bgClr` and perhaps others."""
|
|
67
|
+
|
|
68
|
+
eg_colorChoice = ZeroOrOneChoice(
|
|
69
|
+
(
|
|
70
|
+
Choice("a:scrgbClr"),
|
|
71
|
+
Choice("a:srgbClr"),
|
|
72
|
+
Choice("a:hslClr"),
|
|
73
|
+
Choice("a:sysClr"),
|
|
74
|
+
Choice("a:schemeClr"),
|
|
75
|
+
Choice("a:prstClr"),
|
|
76
|
+
),
|
|
77
|
+
successors=(),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class CT_HslColor(_BaseColorElement):
|
|
82
|
+
"""
|
|
83
|
+
Custom element class for <a:hslClr> element.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class CT_Percentage(BaseOxmlElement):
|
|
88
|
+
"""
|
|
89
|
+
Custom element class for <a:lumMod> and <a:lumOff> elements.
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
val = RequiredAttribute("val", ST_Percentage)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class CT_PositiveFixedPercentage(BaseOxmlElement):
|
|
96
|
+
"""Custom element class for `<a:alpha>` element.
|
|
97
|
+
|
|
98
|
+
`val` is a float in the closed interval [0.0, 1.0] where 1.0 is fully opaque.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
val = RequiredAttribute("val", ST_PositiveFixedPercentage)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class CT_PresetColor(_BaseColorElement):
|
|
105
|
+
"""
|
|
106
|
+
Custom element class for <a:prstClr> element.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class CT_SchemeColor(_BaseColorElement):
|
|
111
|
+
"""
|
|
112
|
+
Custom element class for <a:schemeClr> element.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
val = RequiredAttribute("val", MSO_THEME_COLOR)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class CT_ScRgbColor(_BaseColorElement):
|
|
119
|
+
"""
|
|
120
|
+
Custom element class for <a:scrgbClr> element.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class CT_SRgbColor(_BaseColorElement):
|
|
125
|
+
"""
|
|
126
|
+
Custom element class for <a:srgbClr> element.
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
val = RequiredAttribute("val", ST_HexColorRGB)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class CT_SystemColor(_BaseColorElement):
|
|
133
|
+
"""
|
|
134
|
+
Custom element class for <a:sysClr> element.
|
|
135
|
+
"""
|
pptx2/oxml/dml/effect.py
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"""lxml custom element classes for DrawingML visual-effect elements."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pptx2.enum.dml import MSO_PRESET_SHADOW
|
|
6
|
+
from pptx2.oxml.ns import qn
|
|
7
|
+
from pptx2.oxml.simpletypes import (
|
|
8
|
+
ST_FixedAngle,
|
|
9
|
+
ST_Percentage,
|
|
10
|
+
ST_PositiveCoordinate,
|
|
11
|
+
ST_PositiveFixedAngle,
|
|
12
|
+
ST_PositiveFixedPercentage,
|
|
13
|
+
XsdBoolean,
|
|
14
|
+
XsdStringEnumeration,
|
|
15
|
+
)
|
|
16
|
+
from pptx2.oxml.xmlchemy import (
|
|
17
|
+
BaseOxmlElement,
|
|
18
|
+
Choice,
|
|
19
|
+
OptionalAttribute,
|
|
20
|
+
RequiredAttribute,
|
|
21
|
+
ZeroOrOne,
|
|
22
|
+
ZeroOrOneChoice,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ST_RectAlignment(XsdStringEnumeration):
|
|
27
|
+
"""Valid values for `a:reflection@algn`.
|
|
28
|
+
|
|
29
|
+
The nine-point alignment used by the reflection effect to anchor its
|
|
30
|
+
bounding box relative to the source shape.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
TL = "tl"
|
|
34
|
+
T = "t"
|
|
35
|
+
TR = "tr"
|
|
36
|
+
L = "l"
|
|
37
|
+
CTR = "ctr"
|
|
38
|
+
R = "r"
|
|
39
|
+
BL = "bl"
|
|
40
|
+
B = "b"
|
|
41
|
+
BR = "br"
|
|
42
|
+
|
|
43
|
+
_members = (TL, T, TR, L, CTR, R, BL, B, BR)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
_COLOR_TAGS = frozenset(
|
|
47
|
+
qn(t)
|
|
48
|
+
for t in (
|
|
49
|
+
"a:scrgbClr",
|
|
50
|
+
"a:srgbClr",
|
|
51
|
+
"a:hslClr",
|
|
52
|
+
"a:sysClr",
|
|
53
|
+
"a:schemeClr",
|
|
54
|
+
"a:prstClr",
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
_COLOR_CHOICES = (
|
|
59
|
+
Choice("a:scrgbClr"),
|
|
60
|
+
Choice("a:srgbClr"),
|
|
61
|
+
Choice("a:hslClr"),
|
|
62
|
+
Choice("a:sysClr"),
|
|
63
|
+
Choice("a:schemeClr"),
|
|
64
|
+
Choice("a:prstClr"),
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class CT_EffectList(BaseOxmlElement):
|
|
69
|
+
"""`<a:effectLst>` custom element class — container for shape visual effects."""
|
|
70
|
+
|
|
71
|
+
_tag_seq = (
|
|
72
|
+
"a:blur",
|
|
73
|
+
"a:fillOverlay",
|
|
74
|
+
"a:glow",
|
|
75
|
+
"a:innerShdw",
|
|
76
|
+
"a:outerShdw",
|
|
77
|
+
"a:prstShdw",
|
|
78
|
+
"a:reflection",
|
|
79
|
+
"a:softEdge",
|
|
80
|
+
)
|
|
81
|
+
blur: CT_BlurEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
82
|
+
"a:blur", successors=_tag_seq[1:]
|
|
83
|
+
)
|
|
84
|
+
glow: CT_GlowEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
85
|
+
"a:glow", successors=_tag_seq[3:]
|
|
86
|
+
)
|
|
87
|
+
innerShdw: CT_InnerShadowEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
88
|
+
"a:innerShdw", successors=_tag_seq[4:]
|
|
89
|
+
)
|
|
90
|
+
outerShdw: CT_OuterShadowEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
91
|
+
"a:outerShdw", successors=_tag_seq[5:]
|
|
92
|
+
)
|
|
93
|
+
prstShdw: CT_PresetShadowEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
94
|
+
"a:prstShdw", successors=_tag_seq[6:]
|
|
95
|
+
)
|
|
96
|
+
reflection: CT_ReflectionEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
97
|
+
"a:reflection", successors=_tag_seq[7:]
|
|
98
|
+
)
|
|
99
|
+
softEdge: CT_SoftEdgesEffect | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
|
|
100
|
+
"a:softEdge", successors=_tag_seq[8:]
|
|
101
|
+
)
|
|
102
|
+
del _tag_seq
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class CT_GlowEffect(BaseOxmlElement):
|
|
106
|
+
"""`<a:glow>` custom element class.
|
|
107
|
+
|
|
108
|
+
Specifies a glow effect around the shape edges. `rad` is the glow radius in EMU.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
eg_colorChoice = ZeroOrOneChoice(_COLOR_CHOICES, successors=())
|
|
112
|
+
rad = OptionalAttribute("rad", ST_PositiveCoordinate)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class CT_OuterShadowEffect(BaseOxmlElement):
|
|
116
|
+
"""`<a:outerShdw>` custom element class.
|
|
117
|
+
|
|
118
|
+
Outer shadow effect. All read attributes return None when the attribute is
|
|
119
|
+
absent; writes are non-mutating only when the value is explicitly None.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
eg_colorChoice = ZeroOrOneChoice(_COLOR_CHOICES, successors=())
|
|
123
|
+
blurRad = OptionalAttribute("blurRad", ST_PositiveCoordinate)
|
|
124
|
+
dist = OptionalAttribute("dist", ST_PositiveCoordinate)
|
|
125
|
+
dir = OptionalAttribute("dir", ST_PositiveFixedAngle)
|
|
126
|
+
rotWithShape = OptionalAttribute("rotWithShape", XsdBoolean)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class CT_SoftEdgesEffect(BaseOxmlElement):
|
|
130
|
+
"""`<a:softEdge>` custom element class.
|
|
131
|
+
|
|
132
|
+
Specifies a soft-edge blur at the shape perimeter. `rad` is the blur radius in EMU.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
rad = OptionalAttribute("rad", ST_PositiveCoordinate)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class CT_BlurEffect(BaseOxmlElement):
|
|
139
|
+
"""`<a:blur>` custom element class.
|
|
140
|
+
|
|
141
|
+
Applies a Gaussian blur to the entire shape. `rad` is the blur radius in
|
|
142
|
+
EMU; `grow` controls whether the bounding box expands to accommodate the
|
|
143
|
+
blur (default True per the OOXML schema).
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
rad = OptionalAttribute("rad", ST_PositiveCoordinate)
|
|
147
|
+
grow = OptionalAttribute("grow", XsdBoolean)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class CT_InnerShadowEffect(BaseOxmlElement):
|
|
151
|
+
"""`<a:innerShdw>` custom element class.
|
|
152
|
+
|
|
153
|
+
Inner shadow effect. Mirrors the attribute set of the outer-shadow
|
|
154
|
+
element minus the outer-only `rotWithShape` flag. All read attributes
|
|
155
|
+
return None when the underlying attribute is absent.
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
eg_colorChoice = ZeroOrOneChoice(_COLOR_CHOICES, successors=())
|
|
159
|
+
blurRad = OptionalAttribute("blurRad", ST_PositiveCoordinate)
|
|
160
|
+
dist = OptionalAttribute("dist", ST_PositiveCoordinate)
|
|
161
|
+
dir = OptionalAttribute("dir", ST_PositiveFixedAngle)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class CT_PresetShadowEffect(BaseOxmlElement):
|
|
165
|
+
"""`<a:prstShdw>` custom element class.
|
|
166
|
+
|
|
167
|
+
Preset shadow effect. The ``prst`` attribute (one of ``shdw1`` ..
|
|
168
|
+
``shdw20``) is *required* by the OOXML schema, so it is declared as a
|
|
169
|
+
``RequiredAttribute`` — omitting it (or writing the element without it)
|
|
170
|
+
makes PowerPoint flag the deck as broken. ``dist`` / ``dir`` are optional
|
|
171
|
+
and a single ``EG_ColorChoice`` child is required.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
eg_colorChoice = ZeroOrOneChoice(_COLOR_CHOICES, successors=())
|
|
175
|
+
prst = RequiredAttribute("prst", MSO_PRESET_SHADOW)
|
|
176
|
+
dist = OptionalAttribute("dist", ST_PositiveCoordinate)
|
|
177
|
+
dir = OptionalAttribute("dir", ST_PositiveFixedAngle)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class CT_ReflectionEffect(BaseOxmlElement):
|
|
181
|
+
"""`<a:reflection>` custom element class.
|
|
182
|
+
|
|
183
|
+
Reflection effect placed beneath the shape. Exposes the attributes most
|
|
184
|
+
users actually want — blur radius, offset distance, direction, start/end
|
|
185
|
+
alpha, and alignment. Attributes are optional; reads return None when
|
|
186
|
+
absent so theme inheritance is preserved.
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
blurRad = OptionalAttribute("blurRad", ST_PositiveCoordinate)
|
|
190
|
+
stA = OptionalAttribute("stA", ST_PositiveFixedPercentage)
|
|
191
|
+
stPos = OptionalAttribute("stPos", ST_PositiveFixedPercentage)
|
|
192
|
+
endA = OptionalAttribute("endA", ST_PositiveFixedPercentage)
|
|
193
|
+
endPos = OptionalAttribute("endPos", ST_PositiveFixedPercentage)
|
|
194
|
+
dist = OptionalAttribute("dist", ST_PositiveCoordinate)
|
|
195
|
+
dir = OptionalAttribute("dir", ST_PositiveFixedAngle)
|
|
196
|
+
fadeDir = OptionalAttribute("fadeDir", ST_PositiveFixedAngle)
|
|
197
|
+
sx = OptionalAttribute("sx", ST_Percentage)
|
|
198
|
+
sy = OptionalAttribute("sy", ST_Percentage)
|
|
199
|
+
kx = OptionalAttribute("kx", ST_FixedAngle)
|
|
200
|
+
ky = OptionalAttribute("ky", ST_FixedAngle)
|
|
201
|
+
algn = OptionalAttribute("algn", ST_RectAlignment)
|
|
202
|
+
rotWithShape = OptionalAttribute("rotWithShape", XsdBoolean)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
# `<a:prstShdw>` is a post-fork addition; register its custom element class here
|
|
206
|
+
# (rather than in `pptx2.oxml.__init__`) so the lxml parser maps the tag to
|
|
207
|
+
# `CT_PresetShadowEffect` and the `CT_EffectList.prstShdw` accessor returns a
|
|
208
|
+
# typed element with a working `prst` attribute. `register_element_cls` is
|
|
209
|
+
# defined before this module is imported by `pptx2.oxml.__init__`, so this
|
|
210
|
+
# is safe despite the partial-import ordering.
|
|
211
|
+
from pptx2.oxml import register_element_cls # noqa: E402
|
|
212
|
+
|
|
213
|
+
register_element_cls("a:prstShdw", CT_PresetShadowEffect)
|