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/section.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
"""Sections API — named groupings of slides in the slide-sorter/outline pane.
|
|
2
|
+
|
|
3
|
+
Sections are stored as a PowerPoint-2010 extension on the presentation part
|
|
4
|
+
(``p:presentation/p:extLst/p:ext[@uri="{521415D9-...}"]/p14:sectionLst``). A
|
|
5
|
+
section references its member slides by their numeric ``p:sldId/@id`` value
|
|
6
|
+
(not the relationship id).
|
|
7
|
+
|
|
8
|
+
The public entry point is :attr:`pptx2.presentation.Presentation.sections`,
|
|
9
|
+
which returns a :class:`Sections` collection. Typical use::
|
|
10
|
+
|
|
11
|
+
prs.sections.add("Intro", start_slide_index=0)
|
|
12
|
+
prs.sections.add("Body", start_slide_index=2)
|
|
13
|
+
for section in prs.sections:
|
|
14
|
+
print(section.name, [s.slide_id for s in section.slides])
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import re
|
|
20
|
+
from typing import TYPE_CHECKING, Iterator
|
|
21
|
+
|
|
22
|
+
from pptx2.oxml.ns import qn
|
|
23
|
+
from pptx2.shared import ParentedElementProxy
|
|
24
|
+
|
|
25
|
+
if TYPE_CHECKING:
|
|
26
|
+
from pptx2.oxml.presentation import (
|
|
27
|
+
CT_Presentation,
|
|
28
|
+
CT_Section,
|
|
29
|
+
)
|
|
30
|
+
from pptx2.parts.presentation import PresentationPart
|
|
31
|
+
from pptx2.presentation import Presentation
|
|
32
|
+
from pptx2.slide import Slide
|
|
33
|
+
|
|
34
|
+
# -- brace-wrapped GUID, the lexical form ST_Guid requires for `p14:section/@id` --
|
|
35
|
+
_GUID_RE = re.compile(
|
|
36
|
+
r"^\{[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}"
|
|
37
|
+
r"-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\}$"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _remove_section_element(section_elm: CT_Section) -> None:
|
|
42
|
+
"""Remove *section_elm*, keeping the section list a complete partition.
|
|
43
|
+
|
|
44
|
+
PowerPoint keeps every slide in exactly one section whenever a section
|
|
45
|
+
list exists, so the removed section's member slides are merged into the
|
|
46
|
+
previous section (or the next one when the first section is removed) —
|
|
47
|
+
the same behaviour as PowerPoint's own "Remove Section" command.
|
|
48
|
+
Removing the *only* section drops the whole `p14:sectionLst` extension
|
|
49
|
+
instead: an empty `<p14:sectionLst/>` violates CT_SectionList
|
|
50
|
+
(`minOccurs="1"` on `section`) and the deck simply becomes unsectioned.
|
|
51
|
+
"""
|
|
52
|
+
sectionLst = section_elm.getparent()
|
|
53
|
+
if sectionLst is None:
|
|
54
|
+
return
|
|
55
|
+
siblings = list(sectionLst)
|
|
56
|
+
idx = siblings.index(section_elm)
|
|
57
|
+
member_ids = [sldId.id for sldId in section_elm.sldId_lst]
|
|
58
|
+
|
|
59
|
+
if len(siblings) == 1:
|
|
60
|
+
ext = sectionLst.getparent() # the `p:ext` carrying the extension
|
|
61
|
+
extLst = ext.getparent() if ext is not None else None
|
|
62
|
+
if ext is not None and extLst is not None:
|
|
63
|
+
extLst.remove(ext)
|
|
64
|
+
if len(extLst) == 0:
|
|
65
|
+
prs_elm = extLst.getparent()
|
|
66
|
+
if prs_elm is not None:
|
|
67
|
+
prs_elm.remove(extLst)
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
sectionLst.remove(section_elm)
|
|
71
|
+
if not member_ids:
|
|
72
|
+
return
|
|
73
|
+
if idx > 0:
|
|
74
|
+
# Merge into the previous section: its slides now precede these.
|
|
75
|
+
for slide_id in member_ids:
|
|
76
|
+
siblings[idx - 1].add_sldId(slide_id)
|
|
77
|
+
else:
|
|
78
|
+
# The first section was removed: its slides precede the (new) first
|
|
79
|
+
# section's members, so prepend in order.
|
|
80
|
+
target_lst = siblings[1].get_or_add_sldIdLst()
|
|
81
|
+
for pos, slide_id in enumerate(member_ids):
|
|
82
|
+
entry = target_lst.makeelement(qn("p14:sldId"), {"id": str(slide_id)})
|
|
83
|
+
target_lst.insert(pos, entry)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Sections(ParentedElementProxy):
|
|
87
|
+
"""Sequence of |Section| objects belonging to a |Presentation|.
|
|
88
|
+
|
|
89
|
+
Supports ``len()``, indexed access, and iteration. Reading the
|
|
90
|
+
collection never modifies the deck; the underlying PowerPoint-2010
|
|
91
|
+
extension element is created only when the first section is added.
|
|
92
|
+
"""
|
|
93
|
+
|
|
94
|
+
part: PresentationPart # pyright: ignore[reportIncompatibleMethodOverride]
|
|
95
|
+
|
|
96
|
+
def __init__(self, prs_elm: CT_Presentation, prs: Presentation):
|
|
97
|
+
super(Sections, self).__init__(prs_elm, prs)
|
|
98
|
+
self._prs_elm = prs_elm
|
|
99
|
+
self._prs = prs
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def _section_elms(self) -> list[CT_Section]:
|
|
103
|
+
"""The `p14:section` elements, or an empty list when unsectioned."""
|
|
104
|
+
sectionLst = self._prs_elm.sectionLst
|
|
105
|
+
if sectionLst is None:
|
|
106
|
+
return []
|
|
107
|
+
return sectionLst.section_lst
|
|
108
|
+
|
|
109
|
+
def __getitem__(self, idx: int) -> Section:
|
|
110
|
+
"""Provide indexed access, e.g. ``prs.sections[0]``."""
|
|
111
|
+
try:
|
|
112
|
+
section = self._section_elms[idx]
|
|
113
|
+
except IndexError:
|
|
114
|
+
raise IndexError("section index out of range")
|
|
115
|
+
return Section(section, self._prs)
|
|
116
|
+
|
|
117
|
+
def __iter__(self) -> Iterator[Section]:
|
|
118
|
+
"""Support iteration, e.g. ``for section in prs.sections:``."""
|
|
119
|
+
for section in self._section_elms:
|
|
120
|
+
yield Section(section, self._prs)
|
|
121
|
+
|
|
122
|
+
def __len__(self) -> int:
|
|
123
|
+
"""Support ``len()`` built-in, e.g. ``len(prs.sections)``."""
|
|
124
|
+
return len(self._section_elms)
|
|
125
|
+
|
|
126
|
+
def add(
|
|
127
|
+
self,
|
|
128
|
+
name: str,
|
|
129
|
+
start_slide_index: int | None = None,
|
|
130
|
+
*,
|
|
131
|
+
id: str | None = None,
|
|
132
|
+
) -> Section:
|
|
133
|
+
"""Append a new |Section| named `name` and return it.
|
|
134
|
+
|
|
135
|
+
When `start_slide_index` is given, every slide from that zero-based
|
|
136
|
+
position to the end of the deck becomes a member of the new section
|
|
137
|
+
(the natural PowerPoint behaviour for a section that begins at a given
|
|
138
|
+
slide). PowerPoint sections are contiguous and non-overlapping, so
|
|
139
|
+
those slides are also *removed* from any earlier section that claimed
|
|
140
|
+
them — a new section beginning at slide N truncates the prior section
|
|
141
|
+
at N-1. When the *first* section of the deck starts beyond slide 0,
|
|
142
|
+
the slides before it are grouped into an auto-created "Default
|
|
143
|
+
Section" (mirroring PowerPoint, which never leaves a slide outside
|
|
144
|
+
every section). When `start_slide_index` is omitted, the section is
|
|
145
|
+
created empty.
|
|
146
|
+
|
|
147
|
+
`id` optionally fixes the section's brace-wrapped GUID; supplying it
|
|
148
|
+
keeps output deterministic for tests. A random GUID is generated
|
|
149
|
+
otherwise. A malformed or already-used id raises |ValueError| —
|
|
150
|
+
`p14:section/@id` is an ST_Guid and PowerPoint repairs decks whose
|
|
151
|
+
section ids are not unique GUIDs.
|
|
152
|
+
"""
|
|
153
|
+
if id is not None:
|
|
154
|
+
if not _GUID_RE.match(id):
|
|
155
|
+
raise ValueError(
|
|
156
|
+
"section id must be a brace-wrapped GUID like "
|
|
157
|
+
"'{3E86B4F5-40E6-4F32-8B4D-BE3E1E4C8A27}'; got %r" % (id,)
|
|
158
|
+
)
|
|
159
|
+
if any(s.id.lower() == id.lower() for s in self._section_elms):
|
|
160
|
+
raise ValueError("section id %s is already used in this deck" % id)
|
|
161
|
+
|
|
162
|
+
was_unsectioned = not self._section_elms
|
|
163
|
+
sectionLst = self._prs_elm.get_or_add_sectionLst()
|
|
164
|
+
section_elm = sectionLst.add_section(name, section_id=id)
|
|
165
|
+
section = Section(section_elm, self._prs)
|
|
166
|
+
if start_slide_index is not None:
|
|
167
|
+
slides = list(self._prs.slides)
|
|
168
|
+
claimed = slides[start_slide_index:]
|
|
169
|
+
# Sections don't overlap: take the claimed slides away from any
|
|
170
|
+
# earlier section before assigning them to the new one.
|
|
171
|
+
for other in self:
|
|
172
|
+
if other._element is section_elm:
|
|
173
|
+
continue
|
|
174
|
+
for slide in claimed:
|
|
175
|
+
other.remove_slide(slide)
|
|
176
|
+
for slide in claimed:
|
|
177
|
+
section.add_slide(slide)
|
|
178
|
+
# First section of the deck starting beyond slide 0: cover the
|
|
179
|
+
# preceding slides so the section list partitions the whole deck.
|
|
180
|
+
if was_unsectioned and start_slide_index > 0:
|
|
181
|
+
default_elm = sectionLst.add_section("Default Section")
|
|
182
|
+
section_elm.addprevious(default_elm)
|
|
183
|
+
default = Section(default_elm, self._prs)
|
|
184
|
+
for slide in slides[:start_slide_index]:
|
|
185
|
+
default.add_slide(slide)
|
|
186
|
+
return section
|
|
187
|
+
|
|
188
|
+
def remove(self, section: Section) -> None:
|
|
189
|
+
"""Remove `section` from this collection.
|
|
190
|
+
|
|
191
|
+
Slides referenced by the section are not deleted from the deck; they
|
|
192
|
+
are merged into the neighbouring section (previous when one exists,
|
|
193
|
+
else next), matching PowerPoint's "Remove Section" command. Removing
|
|
194
|
+
the only section removes the section grouping entirely.
|
|
195
|
+
"""
|
|
196
|
+
_remove_section_element(section._element)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
class Section(ParentedElementProxy):
|
|
200
|
+
"""A single named section grouping a contiguous run of slides."""
|
|
201
|
+
|
|
202
|
+
part: PresentationPart # pyright: ignore[reportIncompatibleMethodOverride]
|
|
203
|
+
|
|
204
|
+
def __init__(self, section: CT_Section, prs: Presentation):
|
|
205
|
+
super(Section, self).__init__(section, prs)
|
|
206
|
+
self._section = section
|
|
207
|
+
self._prs = prs
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def id(self) -> str:
|
|
211
|
+
"""The section's brace-wrapped GUID identifier (read-only)."""
|
|
212
|
+
return self._section.id
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def name(self) -> str:
|
|
216
|
+
"""The user-visible section name. Read/write."""
|
|
217
|
+
return self._section.name
|
|
218
|
+
|
|
219
|
+
@name.setter
|
|
220
|
+
def name(self, value: str) -> None:
|
|
221
|
+
self._section.name = value
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def slide_ids(self) -> list[int]:
|
|
225
|
+
"""List of numeric slide ids (``p:sldId/@id``) belonging to this section."""
|
|
226
|
+
return [sldId.id for sldId in self._section.sldId_lst]
|
|
227
|
+
|
|
228
|
+
@property
|
|
229
|
+
def slides(self) -> tuple[Slide, ...]:
|
|
230
|
+
"""Tuple of |Slide| objects belonging to this section.
|
|
231
|
+
|
|
232
|
+
Member references whose slide is no longer present in the deck are
|
|
233
|
+
silently skipped.
|
|
234
|
+
"""
|
|
235
|
+
result: list[Slide] = []
|
|
236
|
+
for slide_id in self.slide_ids:
|
|
237
|
+
slide = self.part.get_slide(slide_id)
|
|
238
|
+
if slide is not None:
|
|
239
|
+
result.append(slide)
|
|
240
|
+
return tuple(result)
|
|
241
|
+
|
|
242
|
+
def add_slide(self, slide: Slide) -> None:
|
|
243
|
+
"""Add `slide` to this section's membership (idempotent).
|
|
244
|
+
|
|
245
|
+
Sections are non-overlapping — PowerPoint repairs a deck whose
|
|
246
|
+
section list references one slide twice — so the slide is first
|
|
247
|
+
removed from any other section that claims it.
|
|
248
|
+
"""
|
|
249
|
+
slide_id = slide.slide_id
|
|
250
|
+
if slide_id in self.slide_ids:
|
|
251
|
+
return
|
|
252
|
+
sectionLst = self._section.getparent()
|
|
253
|
+
if sectionLst is not None:
|
|
254
|
+
for sibling in sectionLst:
|
|
255
|
+
if sibling is self._section:
|
|
256
|
+
continue
|
|
257
|
+
sibling.remove_sldId(slide_id)
|
|
258
|
+
self._section.add_sldId(slide_id)
|
|
259
|
+
|
|
260
|
+
def remove_slide(self, slide: Slide) -> None:
|
|
261
|
+
"""Remove `slide` from this section's membership (no-op if absent)."""
|
|
262
|
+
self._section.remove_sldId(slide.slide_id)
|
|
263
|
+
|
|
264
|
+
def delete(self) -> None:
|
|
265
|
+
"""Remove this section from the presentation.
|
|
266
|
+
|
|
267
|
+
The member slides themselves are left in the deck; they are merged
|
|
268
|
+
into the neighbouring section (previous when one exists, else next)
|
|
269
|
+
so the section list stays a complete partition. Deleting the only
|
|
270
|
+
section removes the section grouping entirely.
|
|
271
|
+
"""
|
|
272
|
+
_remove_section_element(self._section)
|
pptx2/shapes/__init__.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""Objects used across sub-package."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from pptx2.opc.package import XmlPart
|
|
9
|
+
from pptx2.types import ProvidesPart
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Subshape(object):
|
|
13
|
+
"""Provides access to the containing part for drawing elements that occur below a shape.
|
|
14
|
+
|
|
15
|
+
Access to the part is required for example to add or drop a relationship. Provides
|
|
16
|
+
`self._parent` attribute to subclasses.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(self, parent: ProvidesPart):
|
|
20
|
+
super(Subshape, self).__init__()
|
|
21
|
+
self._parent = parent
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def part(self) -> XmlPart:
|
|
25
|
+
"""The package part containing this object."""
|
|
26
|
+
return self._parent.part
|