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.
Files changed (175) hide show
  1. pptx2/__init__.py +152 -0
  2. pptx2/_color.py +75 -0
  3. pptx2/_slide_importer.py +597 -0
  4. pptx2/_svg.py +155 -0
  5. pptx2/_template_applier.py +292 -0
  6. pptx2/_textstyle.py +187 -0
  7. pptx2/accessibility.py +365 -0
  8. pptx2/action.py +270 -0
  9. pptx2/animation.py +2237 -0
  10. pptx2/api.py +49 -0
  11. pptx2/audit.py +258 -0
  12. pptx2/chart/__init__.py +0 -0
  13. pptx2/chart/analytics.py +381 -0
  14. pptx2/chart/axis.py +543 -0
  15. pptx2/chart/category.py +200 -0
  16. pptx2/chart/chart.py +670 -0
  17. pptx2/chart/data.py +864 -0
  18. pptx2/chart/datalabel.py +406 -0
  19. pptx2/chart/legend.py +86 -0
  20. pptx2/chart/marker.py +70 -0
  21. pptx2/chart/palettes.py +129 -0
  22. pptx2/chart/plot.py +462 -0
  23. pptx2/chart/point.py +101 -0
  24. pptx2/chart/quick_layouts.py +325 -0
  25. pptx2/chart/series.py +334 -0
  26. pptx2/chart/xlsx.py +272 -0
  27. pptx2/chart/xmlwriter.py +1845 -0
  28. pptx2/compose/__init__.py +28 -0
  29. pptx2/compose/from_spec.py +1094 -0
  30. pptx2/design/__init__.py +8 -0
  31. pptx2/design/components.py +607 -0
  32. pptx2/design/figures.py +389 -0
  33. pptx2/design/layout.py +370 -0
  34. pptx2/design/recipes.py +1967 -0
  35. pptx2/design/style.py +209 -0
  36. pptx2/design/tokens.py +915 -0
  37. pptx2/diagrams.py +754 -0
  38. pptx2/dml/__init__.py +0 -0
  39. pptx2/dml/chtfmt.py +40 -0
  40. pptx2/dml/color.py +496 -0
  41. pptx2/dml/effect.py +909 -0
  42. pptx2/dml/fill.py +691 -0
  43. pptx2/dml/line.py +287 -0
  44. pptx2/dml/picture.py +212 -0
  45. pptx2/dml/three_d.py +381 -0
  46. pptx2/enum/__init__.py +0 -0
  47. pptx2/enum/action.py +71 -0
  48. pptx2/enum/animation.py +31 -0
  49. pptx2/enum/base.py +218 -0
  50. pptx2/enum/chart.py +574 -0
  51. pptx2/enum/dml.py +740 -0
  52. pptx2/enum/lang.py +685 -0
  53. pptx2/enum/presentation.py +133 -0
  54. pptx2/enum/shapes.py +1029 -0
  55. pptx2/enum/text.py +230 -0
  56. pptx2/exc.py +42 -0
  57. pptx2/formats.py +139 -0
  58. pptx2/geometry.py +420 -0
  59. pptx2/inherit.py +109 -0
  60. pptx2/lint.py +2256 -0
  61. pptx2/math.py +177 -0
  62. pptx2/media.py +197 -0
  63. pptx2/opc/__init__.py +0 -0
  64. pptx2/opc/constants.py +332 -0
  65. pptx2/opc/oxml.py +188 -0
  66. pptx2/opc/package.py +762 -0
  67. pptx2/opc/packuri.py +109 -0
  68. pptx2/opc/serialized.py +296 -0
  69. pptx2/opc/shared.py +20 -0
  70. pptx2/opc/spec.py +45 -0
  71. pptx2/oxml/__init__.py +555 -0
  72. pptx2/oxml/action.py +53 -0
  73. pptx2/oxml/chart/__init__.py +0 -0
  74. pptx2/oxml/chart/axis.py +337 -0
  75. pptx2/oxml/chart/chart.py +481 -0
  76. pptx2/oxml/chart/datalabel.py +253 -0
  77. pptx2/oxml/chart/legend.py +72 -0
  78. pptx2/oxml/chart/marker.py +61 -0
  79. pptx2/oxml/chart/plot.py +365 -0
  80. pptx2/oxml/chart/series.py +425 -0
  81. pptx2/oxml/chart/shared.py +220 -0
  82. pptx2/oxml/coreprops.py +288 -0
  83. pptx2/oxml/dml/__init__.py +0 -0
  84. pptx2/oxml/dml/color.py +135 -0
  85. pptx2/oxml/dml/effect.py +213 -0
  86. pptx2/oxml/dml/fill.py +316 -0
  87. pptx2/oxml/dml/line.py +12 -0
  88. pptx2/oxml/dml/three_d.py +110 -0
  89. pptx2/oxml/ns.py +135 -0
  90. pptx2/oxml/presentation.py +313 -0
  91. pptx2/oxml/shapes/__init__.py +19 -0
  92. pptx2/oxml/shapes/autoshape.py +467 -0
  93. pptx2/oxml/shapes/connector.py +107 -0
  94. pptx2/oxml/shapes/graphfrm.py +347 -0
  95. pptx2/oxml/shapes/groupshape.py +329 -0
  96. pptx2/oxml/shapes/picture.py +270 -0
  97. pptx2/oxml/shapes/shared.py +577 -0
  98. pptx2/oxml/simpletypes.py +1027 -0
  99. pptx2/oxml/slide.py +563 -0
  100. pptx2/oxml/table.py +650 -0
  101. pptx2/oxml/text.py +815 -0
  102. pptx2/oxml/theme.py +36 -0
  103. pptx2/oxml/xmlchemy.py +717 -0
  104. pptx2/package.py +222 -0
  105. pptx2/parts/__init__.py +0 -0
  106. pptx2/parts/chart.py +95 -0
  107. pptx2/parts/coreprops.py +167 -0
  108. pptx2/parts/diagram.py +37 -0
  109. pptx2/parts/embeddedpackage.py +93 -0
  110. pptx2/parts/image.py +275 -0
  111. pptx2/parts/media.py +37 -0
  112. pptx2/parts/presentation.py +136 -0
  113. pptx2/parts/slide.py +371 -0
  114. pptx2/presentation.py +408 -0
  115. pptx2/py.typed +0 -0
  116. pptx2/render.py +586 -0
  117. pptx2/section.py +272 -0
  118. pptx2/shapes/__init__.py +26 -0
  119. pptx2/shapes/autoshape.py +442 -0
  120. pptx2/shapes/base.py +1078 -0
  121. pptx2/shapes/connector.py +297 -0
  122. pptx2/shapes/freeform.py +337 -0
  123. pptx2/shapes/graphfrm.py +316 -0
  124. pptx2/shapes/group.py +264 -0
  125. pptx2/shapes/picture.py +422 -0
  126. pptx2/shapes/placeholder.py +468 -0
  127. pptx2/shapes/shapetree.py +2027 -0
  128. pptx2/shared.py +82 -0
  129. pptx2/skill/SKILL.md +450 -0
  130. pptx2/skill/__init__.py +78 -0
  131. pptx2/skill/__main__.py +64 -0
  132. pptx2/skill/references/animations.md +189 -0
  133. pptx2/skill/references/basics.md +421 -0
  134. pptx2/skill/references/charts.md +254 -0
  135. pptx2/skill/references/compose.md +234 -0
  136. pptx2/skill/references/design.md +366 -0
  137. pptx2/skill/references/effects.md +249 -0
  138. pptx2/skill/references/end-to-end-deck.md +231 -0
  139. pptx2/skill/references/geometry-and-arrows.md +334 -0
  140. pptx2/skill/references/lint.md +275 -0
  141. pptx2/skill/references/math.md +86 -0
  142. pptx2/skill/references/picture-effects.md +129 -0
  143. pptx2/skill/references/render.md +151 -0
  144. pptx2/skill/references/smart-art.md +75 -0
  145. pptx2/skill/references/space-aware-authoring.md +249 -0
  146. pptx2/skill/references/tables.md +244 -0
  147. pptx2/skill/references/theme.md +127 -0
  148. pptx2/skill/references/three-d.md +109 -0
  149. pptx2/skill/references/transitions.md +100 -0
  150. pptx2/slide.py +1244 -0
  151. pptx2/smart_art.py +220 -0
  152. pptx2/spec.py +633 -0
  153. pptx2/table.py +1181 -0
  154. pptx2/table_styles.py +184 -0
  155. pptx2/templates/default.pptx +0 -0
  156. pptx2/templates/docx-icon.emf +0 -0
  157. pptx2/templates/generic-icon.emf +0 -0
  158. pptx2/templates/notes.xml +23 -0
  159. pptx2/templates/notesMaster.xml +352 -0
  160. pptx2/templates/pptx-icon.emf +0 -0
  161. pptx2/templates/theme.xml +321 -0
  162. pptx2/templates/xlsx-icon.emf +0 -0
  163. pptx2/text/__init__.py +0 -0
  164. pptx2/text/fonts.py +482 -0
  165. pptx2/text/layout.py +374 -0
  166. pptx2/text/text.py +1272 -0
  167. pptx2/theme.py +721 -0
  168. pptx2/types.py +36 -0
  169. pptx2/util.py +263 -0
  170. python_pptx2-2.13.0.dist-info/METADATA +351 -0
  171. python_pptx2-2.13.0.dist-info/RECORD +175 -0
  172. python_pptx2-2.13.0.dist-info/WHEEL +5 -0
  173. python_pptx2-2.13.0.dist-info/entry_points.txt +3 -0
  174. python_pptx2-2.13.0.dist-info/licenses/LICENSE +22 -0
  175. python_pptx2-2.13.0.dist-info/top_level.txt +1 -0
pptx2/smart_art.py ADDED
@@ -0,0 +1,220 @@
1
+ """SmartArt shape access for text substitution.
2
+
3
+ Exposes :class:`SmartArtCollection` (accessed via ``slide.smart_art``) and
4
+ :class:`SmartArtShape`, whose :meth:`~SmartArtShape.set_text` method rewrites
5
+ the text nodes inside an existing ``diagrams/data#.xml`` part without touching
6
+ layout, style, or colour parts.
7
+
8
+ Scope: text *substitution* in existing SmartArt only. Full SmartArt creation
9
+ is explicitly out of scope.
10
+
11
+ Example::
12
+
13
+ slide = prs.slides[0]
14
+ org_chart = slide.smart_art[0]
15
+ print(org_chart.texts) # ['CEO', 'CTO', 'CFO']
16
+ org_chart.set_text(['Alice', 'Bob', 'Carol'])
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import TYPE_CHECKING, Iterator, Sequence
22
+
23
+ from lxml.etree import _Element as LxmlElement # pyright: ignore[reportPrivateUsage]
24
+
25
+ from pptx2.oxml.ns import _nsmap as _GLOBAL_NSMAP # pyright: ignore[reportPrivateUsage]
26
+ from pptx2.oxml.ns import qn
27
+ from pptx2.spec import GRAPHIC_DATA_URI_DIAGRAM
28
+
29
+ if TYPE_CHECKING:
30
+ from pptx2.oxml.xmlchemy import BaseOxmlElement
31
+
32
+ from pptx2.parts.slide import SlidePart
33
+ from pptx2.slide import Slide
34
+
35
+
36
+ # ---------------------------------------------------------------------------
37
+ # Internal helpers
38
+ # ---------------------------------------------------------------------------
39
+
40
+ # <dgm:pt> types that carry visible text content (all others are structural)
41
+ _NODE_TYPES = frozenset({"node", "asst"})
42
+
43
+
44
+ def _xpath(element: LxmlElement, expr: str) -> list[LxmlElement]:
45
+ """Evaluate *expr* on *element* using the global namespace map.
46
+
47
+ Uses ``lxml.etree._Element.xpath`` directly so that the call always
48
+ receives the full ``namespaces`` keyword argument, even when *element* is
49
+ a ``BaseOxmlElement`` whose ``xpath`` method has an overridden signature.
50
+ """
51
+ return LxmlElement.xpath(element, expr, namespaces=_GLOBAL_NSMAP) # type: ignore[arg-type]
52
+
53
+
54
+ def _node_pts(data_element: LxmlElement) -> list[LxmlElement]:
55
+ """Return all ``<dgm:pt>`` elements whose ``type`` marks them as content nodes.
56
+
57
+ The returned list is in document order, which corresponds to the visual
58
+ display order in most SmartArt layouts.
59
+ """
60
+ return _xpath(data_element, "dgm:ptLst/dgm:pt[@type='node' or @type='asst']")
61
+
62
+
63
+ def _text_runs(pt: LxmlElement) -> list[LxmlElement]:
64
+ """Return all ``<a:t>`` leaf elements inside a ``<dgm:pt>/<dgm:t>`` text body."""
65
+ return _xpath(pt, "dgm:t//a:r/a:t")
66
+
67
+
68
+ # ---------------------------------------------------------------------------
69
+ # Public classes
70
+ # ---------------------------------------------------------------------------
71
+
72
+
73
+ class SmartArtShape:
74
+ """Proxy for one SmartArt graphic on a slide.
75
+
76
+ Wraps a ``<p:graphicFrame>`` that encloses a SmartArt diagram and exposes
77
+ the diagram-data part as a mutable text surface.
78
+
79
+ Do not construct directly; obtain instances from :attr:`Slide.smart_art`.
80
+ """
81
+
82
+ def __init__(self, graphic_frame: BaseOxmlElement, slide_part: SlidePart) -> None:
83
+ self._frame = graphic_frame
84
+ self._slide_part = slide_part
85
+
86
+ # ------------------------------------------------------------------
87
+ # Public interface
88
+ # ------------------------------------------------------------------
89
+
90
+ @property
91
+ def name(self) -> str:
92
+ """Internal shape name, e.g. "SmartArt 5"."""
93
+ cNvPr_elms = _xpath(self._frame, ".//p:cNvPr")
94
+ return cNvPr_elms[0].get("name", "") if cNvPr_elms else ""
95
+
96
+ @property
97
+ def texts(self) -> list[str]:
98
+ """Ordered list of text strings — one per content node in the diagram data.
99
+
100
+ Each string is the concatenation of all ``<a:t>`` run text inside the
101
+ corresponding ``<dgm:pt>`` element. The order matches the visual
102
+ sequence in most layouts (document order in ``<dgm:ptLst>``).
103
+ """
104
+ data_el = self._data_element
105
+ result: list[str] = []
106
+ for pt in _node_pts(data_el):
107
+ runs = _text_runs(pt)
108
+ result.append("".join(r.text or "" for r in runs))
109
+ return result
110
+
111
+ def set_text(self, values: Sequence[str], *, strict: bool = True) -> None:
112
+ """Replace the text of each content node with the corresponding entry in *values*.
113
+
114
+ Parameters
115
+ ----------
116
+ values:
117
+ New text strings, one per content node. The order must match
118
+ :attr:`texts`.
119
+ strict:
120
+ When ``True`` (the default), raises :class:`ValueError` if
121
+ ``len(values)`` does not equal the number of content nodes.
122
+ When ``False``, extra values are silently ignored and nodes
123
+ without a corresponding value are left unchanged.
124
+
125
+ Raises
126
+ ------
127
+ ValueError
128
+ When ``strict=True`` and ``len(values) != len(self.texts)``.
129
+ """
130
+ data_el = self._data_element
131
+ nodes = _node_pts(data_el)
132
+
133
+ if strict and len(values) != len(nodes):
134
+ raise ValueError(
135
+ f"set_text() received {len(values)} value(s) but this SmartArt has "
136
+ f"{len(nodes)} content node(s). Pass strict=False to suppress this check."
137
+ )
138
+
139
+ for i, pt in enumerate(nodes):
140
+ if i >= len(values):
141
+ break
142
+ new_text = str(values[i])
143
+ runs = _text_runs(pt)
144
+ if runs:
145
+ # Overwrite first run; clear the rest.
146
+ runs[0].text = new_text
147
+ for extra_run in runs[1:]:
148
+ extra_run.text = ""
149
+ else:
150
+ # No existing <a:t>; build a minimal <dgm:t>/<a:p>/<a:r>/<a:t> subtree.
151
+ t_body = pt.find(qn("dgm:t"))
152
+ if t_body is None:
153
+ from lxml import etree
154
+
155
+ t_body = etree.SubElement(pt, qn("dgm:t"))
156
+ etree.SubElement(t_body, qn("a:bodyPr"))
157
+ etree.SubElement(t_body, qn("a:lstStyle"))
158
+ from lxml import etree
159
+
160
+ p = etree.SubElement(t_body, qn("a:p"))
161
+ r = etree.SubElement(p, qn("a:r"))
162
+ t = etree.SubElement(r, qn("a:t"))
163
+ t.text = new_text
164
+
165
+ # ------------------------------------------------------------------
166
+ # Internals
167
+ # ------------------------------------------------------------------
168
+
169
+ @property
170
+ def _data_rId(self) -> str:
171
+ """rId of the diagram-data relationship from the slide part."""
172
+ # <a:graphicData><dgm:relIds r:dm="rIdN" .../>
173
+ rel_ids = _xpath(self._frame, ".//dgm:relIds")
174
+ if not rel_ids:
175
+ raise ValueError("SmartArt frame has no <dgm:relIds> element.")
176
+ return rel_ids[0].get(qn("r:dm")) # type: ignore[return-value]
177
+
178
+ @property
179
+ def _data_element(self) -> BaseOxmlElement:
180
+ """Root element of the diagram-data part for this SmartArt."""
181
+ rId = self._data_rId
182
+ data_part = self._slide_part.related_part(rId)
183
+ return data_part._element # pyright: ignore[reportPrivateUsage]
184
+
185
+
186
+ class SmartArtCollection:
187
+ """Sequence of :class:`SmartArtShape` objects on a slide.
188
+
189
+ Accessed via :attr:`Slide.smart_art`. Supports indexing and iteration.
190
+ """
191
+
192
+ def __init__(self, slide: Slide) -> None:
193
+ self._slide = slide
194
+
195
+ def __len__(self) -> int:
196
+ return len(self._frames)
197
+
198
+ def __getitem__(self, idx: int) -> SmartArtShape:
199
+ frames = self._frames
200
+ if idx < 0 or idx >= len(frames):
201
+ raise IndexError(f"SmartArt index {idx} out of range (0–{len(frames) - 1})")
202
+ return SmartArtShape(frames[idx], self._slide.part)
203
+
204
+ def __iter__(self) -> Iterator[SmartArtShape]:
205
+ for frame in self._frames:
206
+ yield SmartArtShape(frame, self._slide.part)
207
+
208
+ def __repr__(self) -> str:
209
+ return f"SmartArtCollection({len(self)} SmartArt shape(s))"
210
+
211
+ @property
212
+ def _frames(self) -> list[BaseOxmlElement]:
213
+ """All ``<p:graphicFrame>`` elements on the slide whose URI is the SmartArt URI."""
214
+ spTree = self._slide._element.spTree # pyright: ignore[reportPrivateUsage]
215
+ frames: list[BaseOxmlElement] = []
216
+ for gf in spTree.iter(qn("p:graphicFrame")):
217
+ uri_nodes = _xpath(gf, ".//a:graphicData/@uri")
218
+ if uri_nodes and uri_nodes[0] == GRAPHIC_DATA_URI_DIAGRAM:
219
+ frames.append(gf) # type: ignore[arg-type]
220
+ return frames