ps-python-pptx 1.1.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 (117) hide show
  1. pptx/__init__.py +84 -0
  2. pptx/action.py +270 -0
  3. pptx/api.py +49 -0
  4. pptx/chart/__init__.py +0 -0
  5. pptx/chart/axis.py +523 -0
  6. pptx/chart/category.py +200 -0
  7. pptx/chart/chart.py +280 -0
  8. pptx/chart/data.py +864 -0
  9. pptx/chart/datalabel.py +288 -0
  10. pptx/chart/legend.py +79 -0
  11. pptx/chart/marker.py +70 -0
  12. pptx/chart/plot.py +412 -0
  13. pptx/chart/point.py +101 -0
  14. pptx/chart/series.py +258 -0
  15. pptx/chart/xlsx.py +272 -0
  16. pptx/chart/xmlwriter.py +1840 -0
  17. pptx/dml/__init__.py +0 -0
  18. pptx/dml/chtfmt.py +40 -0
  19. pptx/dml/color.py +301 -0
  20. pptx/dml/effect.py +41 -0
  21. pptx/dml/fill.py +468 -0
  22. pptx/dml/line.py +100 -0
  23. pptx/enum/__init__.py +0 -0
  24. pptx/enum/action.py +71 -0
  25. pptx/enum/base.py +175 -0
  26. pptx/enum/chart.py +492 -0
  27. pptx/enum/dml.py +405 -0
  28. pptx/enum/lang.py +685 -0
  29. pptx/enum/shapes.py +1029 -0
  30. pptx/enum/text.py +371 -0
  31. pptx/exc.py +23 -0
  32. pptx/media.py +197 -0
  33. pptx/opc/__init__.py +0 -0
  34. pptx/opc/constants.py +331 -0
  35. pptx/opc/oxml.py +188 -0
  36. pptx/opc/package.py +762 -0
  37. pptx/opc/packuri.py +109 -0
  38. pptx/opc/serialized.py +296 -0
  39. pptx/opc/shared.py +20 -0
  40. pptx/opc/spec.py +44 -0
  41. pptx/oxml/__init__.py +492 -0
  42. pptx/oxml/action.py +53 -0
  43. pptx/oxml/chart/__init__.py +0 -0
  44. pptx/oxml/chart/axis.py +297 -0
  45. pptx/oxml/chart/chart.py +282 -0
  46. pptx/oxml/chart/datalabel.py +252 -0
  47. pptx/oxml/chart/legend.py +72 -0
  48. pptx/oxml/chart/marker.py +61 -0
  49. pptx/oxml/chart/plot.py +345 -0
  50. pptx/oxml/chart/series.py +254 -0
  51. pptx/oxml/chart/shared.py +219 -0
  52. pptx/oxml/coreprops.py +288 -0
  53. pptx/oxml/dml/__init__.py +0 -0
  54. pptx/oxml/dml/color.py +111 -0
  55. pptx/oxml/dml/fill.py +197 -0
  56. pptx/oxml/dml/line.py +12 -0
  57. pptx/oxml/ns.py +129 -0
  58. pptx/oxml/presentation.py +130 -0
  59. pptx/oxml/shapes/__init__.py +19 -0
  60. pptx/oxml/shapes/autoshape.py +455 -0
  61. pptx/oxml/shapes/connector.py +107 -0
  62. pptx/oxml/shapes/graphfrm.py +342 -0
  63. pptx/oxml/shapes/groupshape.py +280 -0
  64. pptx/oxml/shapes/picture.py +270 -0
  65. pptx/oxml/shapes/shared.py +523 -0
  66. pptx/oxml/simpletypes.py +740 -0
  67. pptx/oxml/slide.py +347 -0
  68. pptx/oxml/table.py +588 -0
  69. pptx/oxml/text.py +748 -0
  70. pptx/oxml/theme.py +29 -0
  71. pptx/oxml/xmlchemy.py +717 -0
  72. pptx/package.py +222 -0
  73. pptx/parts/__init__.py +0 -0
  74. pptx/parts/chart.py +95 -0
  75. pptx/parts/coreprops.py +167 -0
  76. pptx/parts/embeddedpackage.py +93 -0
  77. pptx/parts/image.py +275 -0
  78. pptx/parts/media.py +37 -0
  79. pptx/parts/presentation.py +126 -0
  80. pptx/parts/slide.py +297 -0
  81. pptx/parts/theme.py +13 -0
  82. pptx/presentation.py +113 -0
  83. pptx/py.typed +0 -0
  84. pptx/shapes/__init__.py +26 -0
  85. pptx/shapes/autoshape.py +355 -0
  86. pptx/shapes/base.py +293 -0
  87. pptx/shapes/connector.py +297 -0
  88. pptx/shapes/freeform.py +337 -0
  89. pptx/shapes/graphfrm.py +166 -0
  90. pptx/shapes/group.py +69 -0
  91. pptx/shapes/picture.py +203 -0
  92. pptx/shapes/placeholder.py +407 -0
  93. pptx/shapes/shapetree.py +1190 -0
  94. pptx/shared.py +82 -0
  95. pptx/slide.py +577 -0
  96. pptx/spec.py +632 -0
  97. pptx/table.py +520 -0
  98. pptx/templates/default.pptx +0 -0
  99. pptx/templates/docx-icon.emf +0 -0
  100. pptx/templates/generic-icon.emf +0 -0
  101. pptx/templates/notes.xml +23 -0
  102. pptx/templates/notesMaster.xml +352 -0
  103. pptx/templates/pptx-icon.emf +0 -0
  104. pptx/templates/theme.xml +321 -0
  105. pptx/templates/xlsx-icon.emf +0 -0
  106. pptx/text/__init__.py +0 -0
  107. pptx/text/fonts.py +399 -0
  108. pptx/text/layout.py +325 -0
  109. pptx/text/text.py +770 -0
  110. pptx/theme.py +135 -0
  111. pptx/types.py +36 -0
  112. pptx/util.py +284 -0
  113. ps_python_pptx-1.1.0.dist-info/METADATA +75 -0
  114. ps_python_pptx-1.1.0.dist-info/RECORD +117 -0
  115. ps_python_pptx-1.1.0.dist-info/WHEEL +5 -0
  116. ps_python_pptx-1.1.0.dist-info/licenses/LICENSE +20 -0
  117. ps_python_pptx-1.1.0.dist-info/top_level.txt +1 -0
pptx/__init__.py ADDED
@@ -0,0 +1,84 @@
1
+ """Initialization module for python-pptx package."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+ from typing import TYPE_CHECKING
7
+
8
+ import pptx.exc as exceptions
9
+ from pptx.api import Presentation
10
+ from pptx.opc.constants import CONTENT_TYPE as CT
11
+ from pptx.opc.package import PartFactory
12
+ from pptx.parts.chart import ChartPart
13
+ from pptx.parts.coreprops import CorePropertiesPart
14
+ from pptx.parts.image import ImagePart
15
+ from pptx.parts.media import MediaPart
16
+ from pptx.parts.theme import ThemePart
17
+ from pptx.parts.presentation import PresentationPart
18
+ from pptx.parts.slide import (
19
+ NotesMasterPart,
20
+ NotesSlidePart,
21
+ SlideLayoutPart,
22
+ SlideMasterPart,
23
+ SlidePart,
24
+ )
25
+
26
+ if TYPE_CHECKING:
27
+ from pptx.opc.package import Part
28
+
29
+ __version__ = "1.1.0"
30
+
31
+ sys.modules["pptx.exceptions"] = exceptions
32
+ del sys
33
+
34
+ __all__ = ["Presentation"]
35
+
36
+ content_type_to_part_class_map: dict[str, type[Part]] = {
37
+ CT.PML_PRESENTATION_MAIN: PresentationPart,
38
+ CT.PML_PRES_MACRO_MAIN: PresentationPart,
39
+ CT.PML_TEMPLATE_MAIN: PresentationPart,
40
+ CT.PML_SLIDESHOW_MAIN: PresentationPart,
41
+ CT.OPC_CORE_PROPERTIES: CorePropertiesPart,
42
+ CT.PML_NOTES_MASTER: NotesMasterPart,
43
+ CT.PML_NOTES_SLIDE: NotesSlidePart,
44
+ CT.PML_SLIDE: SlidePart,
45
+ CT.PML_SLIDE_LAYOUT: SlideLayoutPart,
46
+ CT.PML_SLIDE_MASTER: SlideMasterPart,
47
+ CT.DML_CHART: ChartPart,
48
+ CT.OFC_THEME: ThemePart,
49
+ CT.BMP: ImagePart,
50
+ CT.GIF: ImagePart,
51
+ CT.JPEG: ImagePart,
52
+ CT.MS_PHOTO: ImagePart,
53
+ CT.PNG: ImagePart,
54
+ CT.TIFF: ImagePart,
55
+ CT.X_EMF: ImagePart,
56
+ CT.X_WMF: ImagePart,
57
+ CT.ASF: MediaPart,
58
+ CT.AVI: MediaPart,
59
+ CT.MOV: MediaPart,
60
+ CT.MP4: MediaPart,
61
+ CT.MPG: MediaPart,
62
+ CT.MS_VIDEO: MediaPart,
63
+ CT.SWF: MediaPart,
64
+ CT.VIDEO: MediaPart,
65
+ CT.WMV: MediaPart,
66
+ CT.X_MS_VIDEO: MediaPart,
67
+ # -- accommodate "image/jpg" as an alias for "image/jpeg" --
68
+ "image/jpg": ImagePart,
69
+ }
70
+
71
+ PartFactory.part_type_for.update(content_type_to_part_class_map)
72
+
73
+ del (
74
+ ChartPart,
75
+ CorePropertiesPart,
76
+ ImagePart,
77
+ MediaPart,
78
+ SlidePart,
79
+ SlideLayoutPart,
80
+ SlideMasterPart,
81
+ PresentationPart,
82
+ CT,
83
+ PartFactory,
84
+ )
pptx/action.py ADDED
@@ -0,0 +1,270 @@
1
+ """Objects related to mouse click and hover actions on a shape or text."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, cast
6
+
7
+ from pptx.enum.action import PP_ACTION
8
+ from pptx.opc.constants import RELATIONSHIP_TYPE as RT
9
+ from pptx.shapes import Subshape
10
+ from pptx.util import lazyproperty
11
+
12
+ if TYPE_CHECKING:
13
+ from pptx.oxml.action import CT_Hyperlink
14
+ from pptx.oxml.shapes.shared import CT_NonVisualDrawingProps
15
+ from pptx.oxml.text import CT_TextCharacterProperties
16
+ from pptx.parts.slide import SlidePart
17
+ from pptx.shapes.base import BaseShape
18
+ from pptx.slide import Slide, Slides
19
+
20
+
21
+ class ActionSetting(Subshape):
22
+ """Properties specifying how a shape or run reacts to mouse actions."""
23
+
24
+ # -- The Subshape base class provides access to the Slide Part, which is needed to access
25
+ # -- relationships, which is where hyperlinks live.
26
+
27
+ def __init__(
28
+ self,
29
+ xPr: CT_NonVisualDrawingProps | CT_TextCharacterProperties,
30
+ parent: BaseShape,
31
+ hover: bool = False,
32
+ ):
33
+ super(ActionSetting, self).__init__(parent)
34
+ # xPr is either a cNvPr or rPr element
35
+ self._element = xPr
36
+ # _hover determines use of `a:hlinkClick` or `a:hlinkHover`
37
+ self._hover = hover
38
+
39
+ @property
40
+ def action(self):
41
+ """Member of :ref:`PpActionType` enumeration, such as `PP_ACTION.HYPERLINK`.
42
+
43
+ The returned member indicates the type of action that will result when the
44
+ specified shape or text is clicked or the mouse pointer is positioned over the
45
+ shape during a slide show.
46
+
47
+ If there is no click-action or the click-action value is not recognized (is not
48
+ one of the official `MsoPpAction` values) then `PP_ACTION.NONE` is returned.
49
+ """
50
+ hlink = self._hlink
51
+
52
+ if hlink is None:
53
+ return PP_ACTION.NONE
54
+
55
+ action_verb = hlink.action_verb
56
+
57
+ if action_verb == "hlinkshowjump":
58
+ relative_target = hlink.action_fields["jump"]
59
+ return {
60
+ "firstslide": PP_ACTION.FIRST_SLIDE,
61
+ "lastslide": PP_ACTION.LAST_SLIDE,
62
+ "lastslideviewed": PP_ACTION.LAST_SLIDE_VIEWED,
63
+ "nextslide": PP_ACTION.NEXT_SLIDE,
64
+ "previousslide": PP_ACTION.PREVIOUS_SLIDE,
65
+ "endshow": PP_ACTION.END_SHOW,
66
+ }[relative_target]
67
+
68
+ return {
69
+ None: PP_ACTION.HYPERLINK,
70
+ "hlinksldjump": PP_ACTION.NAMED_SLIDE,
71
+ "hlinkpres": PP_ACTION.PLAY,
72
+ "hlinkfile": PP_ACTION.OPEN_FILE,
73
+ "customshow": PP_ACTION.NAMED_SLIDE_SHOW,
74
+ "ole": PP_ACTION.OLE_VERB,
75
+ "macro": PP_ACTION.RUN_MACRO,
76
+ "program": PP_ACTION.RUN_PROGRAM,
77
+ }.get(action_verb, PP_ACTION.NONE)
78
+
79
+ @lazyproperty
80
+ def hyperlink(self) -> Hyperlink:
81
+ """
82
+ A |Hyperlink| object representing the hyperlink action defined on
83
+ this click or hover mouse event. A |Hyperlink| object is always
84
+ returned, even if no hyperlink or other click action is defined.
85
+ """
86
+ return Hyperlink(self._element, self._parent, self._hover)
87
+
88
+ @property
89
+ def target_slide(self) -> Slide | None:
90
+ """
91
+ A reference to the slide in this presentation that is the target of
92
+ the slide jump action in this shape. Slide jump actions include
93
+ `PP_ACTION.FIRST_SLIDE`, `LAST_SLIDE`, `NEXT_SLIDE`,
94
+ `PREVIOUS_SLIDE`, and `NAMED_SLIDE`. Returns |None| for all other
95
+ actions. In particular, the `LAST_SLIDE_VIEWED` action and the `PLAY`
96
+ (start other presentation) actions are not supported.
97
+
98
+ A slide object may be assigned to this property, which makes the
99
+ shape an "internal hyperlink" to the assigened slide::
100
+
101
+ slide, target_slide = prs.slides[0], prs.slides[1]
102
+ shape = slide.shapes[0]
103
+ shape.target_slide = target_slide
104
+
105
+ Assigning |None| removes any slide jump action. Note that this is
106
+ accomplished by removing any action present (such as a hyperlink),
107
+ without first checking that it is a slide jump action.
108
+ """
109
+ slide_jump_actions = (
110
+ PP_ACTION.FIRST_SLIDE,
111
+ PP_ACTION.LAST_SLIDE,
112
+ PP_ACTION.NEXT_SLIDE,
113
+ PP_ACTION.PREVIOUS_SLIDE,
114
+ PP_ACTION.NAMED_SLIDE,
115
+ )
116
+
117
+ if self.action not in slide_jump_actions:
118
+ return None
119
+
120
+ if self.action == PP_ACTION.FIRST_SLIDE:
121
+ return self._slides[0]
122
+ elif self.action == PP_ACTION.LAST_SLIDE:
123
+ return self._slides[-1]
124
+ elif self.action == PP_ACTION.NEXT_SLIDE:
125
+ next_slide_idx = self._slide_index + 1
126
+ if next_slide_idx >= len(self._slides):
127
+ raise ValueError("no next slide")
128
+ return self._slides[next_slide_idx]
129
+ elif self.action == PP_ACTION.PREVIOUS_SLIDE:
130
+ prev_slide_idx = self._slide_index - 1
131
+ if prev_slide_idx < 0:
132
+ raise ValueError("no previous slide")
133
+ return self._slides[prev_slide_idx]
134
+ elif self.action == PP_ACTION.NAMED_SLIDE:
135
+ assert self._hlink is not None
136
+ rId = self._hlink.rId
137
+ slide_part = cast("SlidePart", self.part.related_part(rId))
138
+ return slide_part.slide
139
+
140
+ @target_slide.setter
141
+ def target_slide(self, slide: Slide | None):
142
+ self._clear_click_action()
143
+ if slide is None:
144
+ return
145
+ hlink = self._element.get_or_add_hlinkClick()
146
+ hlink.action = "ppaction://hlinksldjump"
147
+ hlink.rId = self.part.relate_to(slide.part, RT.SLIDE)
148
+
149
+ def _clear_click_action(self):
150
+ """Remove any existing click action."""
151
+ hlink = self._hlink
152
+ if hlink is None:
153
+ return
154
+ rId = hlink.rId
155
+ if rId:
156
+ self.part.drop_rel(rId)
157
+ self._element.remove(hlink)
158
+
159
+ @property
160
+ def _hlink(self) -> CT_Hyperlink | None:
161
+ """
162
+ Reference to the `a:hlinkClick` or `a:hlinkHover` element for this
163
+ click action. Returns |None| if the element is not present.
164
+ """
165
+ if self._hover:
166
+ assert isinstance(self._element, CT_NonVisualDrawingProps)
167
+ return self._element.hlinkHover
168
+ return self._element.hlinkClick
169
+
170
+ @lazyproperty
171
+ def _slide(self):
172
+ """
173
+ Reference to the slide containing the shape having this click action.
174
+ """
175
+ return self.part.slide
176
+
177
+ @lazyproperty
178
+ def _slide_index(self):
179
+ """
180
+ Position in the slide collection of the slide containing the shape
181
+ having this click action.
182
+ """
183
+ return self._slides.index(self._slide)
184
+
185
+ @lazyproperty
186
+ def _slides(self) -> Slides:
187
+ """
188
+ Reference to the slide collection for this presentation.
189
+ """
190
+ return self.part.package.presentation_part.presentation.slides
191
+
192
+
193
+ class Hyperlink(Subshape):
194
+ """Represents a hyperlink action on a shape or text run."""
195
+
196
+ def __init__(
197
+ self,
198
+ xPr: CT_NonVisualDrawingProps | CT_TextCharacterProperties,
199
+ parent: BaseShape,
200
+ hover: bool = False,
201
+ ):
202
+ super(Hyperlink, self).__init__(parent)
203
+ # xPr is either a cNvPr or rPr element
204
+ self._element = xPr
205
+ # _hover determines use of `a:hlinkClick` or `a:hlinkHover`
206
+ self._hover = hover
207
+
208
+ @property
209
+ def address(self) -> str | None:
210
+ """Read/write. The URL of the hyperlink.
211
+
212
+ URL can be on http, https, mailto, or file scheme; others may work. Returns |None| if no
213
+ hyperlink is defined, including when another action such as `RUN_MACRO` is defined on the
214
+ object. Assigning |None| removes any action defined on the object, whether it is a hyperlink
215
+ action or not.
216
+ """
217
+ hlink = self._hlink
218
+
219
+ # there's no URL if there's no click action
220
+ if hlink is None:
221
+ return None
222
+
223
+ # a click action without a relationship has no URL
224
+ rId = hlink.rId
225
+ if not rId:
226
+ return None
227
+
228
+ return self.part.target_ref(rId)
229
+
230
+ @address.setter
231
+ def address(self, url: str | None):
232
+ # implements all three of add, change, and remove hyperlink
233
+ self._remove_hlink()
234
+
235
+ if url:
236
+ rId = self.part.relate_to(url, RT.HYPERLINK, is_external=True)
237
+ hlink = self._get_or_add_hlink()
238
+ hlink.rId = rId
239
+
240
+ def _get_or_add_hlink(self) -> CT_Hyperlink:
241
+ """Get the `a:hlinkClick` or `a:hlinkHover` element for the Hyperlink object.
242
+
243
+ The actual element depends on the value of `self._hover`. Create the element if not present.
244
+ """
245
+ if self._hover:
246
+ return cast("CT_NonVisualDrawingProps", self._element).get_or_add_hlinkHover()
247
+ return self._element.get_or_add_hlinkClick()
248
+
249
+ @property
250
+ def _hlink(self) -> CT_Hyperlink | None:
251
+ """Reference to the `a:hlinkClick` or `h:hlinkHover` element for this click action.
252
+
253
+ Returns |None| if the element is not present.
254
+ """
255
+ if self._hover:
256
+ return cast("CT_NonVisualDrawingProps", self._element).hlinkHover
257
+ return self._element.hlinkClick
258
+
259
+ def _remove_hlink(self):
260
+ """Remove the a:hlinkClick or a:hlinkHover element.
261
+
262
+ Also drops any relationship it might have.
263
+ """
264
+ hlink = self._hlink
265
+ if hlink is None:
266
+ return
267
+ rId = hlink.rId
268
+ if rId:
269
+ self.part.drop_rel(rId)
270
+ self._element.remove(hlink)
pptx/api.py ADDED
@@ -0,0 +1,49 @@
1
+ """Directly exposed API classes, Presentation for now.
2
+
3
+ Provides some syntactic sugar for interacting with the pptx.presentation.Package graph and also
4
+ provides some insulation so not so many classes in the other modules need to be named as internal
5
+ (leading underscore).
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import os
11
+ from typing import IO, TYPE_CHECKING
12
+
13
+ from pptx.opc.constants import CONTENT_TYPE as CT
14
+ from pptx.package import Package
15
+
16
+ if TYPE_CHECKING:
17
+ from pptx import presentation
18
+ from pptx.parts.presentation import PresentationPart
19
+
20
+
21
+ def Presentation(pptx: str | IO[bytes] | None = None) -> presentation.Presentation:
22
+ """
23
+ Return a |Presentation| object loaded from *pptx*, where *pptx* can be
24
+ either a path to a ``.pptx`` file (a string) or a file-like object. If
25
+ *pptx* is missing or ``None``, the built-in default presentation
26
+ "template" is loaded.
27
+ """
28
+ if pptx is None:
29
+ pptx = _default_pptx_path()
30
+
31
+ presentation_part = Package.open(pptx).main_document_part
32
+
33
+ if not _is_pptx_package(presentation_part):
34
+ tmpl = "file '%s' is not a PowerPoint file, content type is '%s'"
35
+ raise ValueError(tmpl % (pptx, presentation_part.content_type))
36
+
37
+ return presentation_part.presentation
38
+
39
+
40
+ def _default_pptx_path() -> str:
41
+ """Return the path to the built-in default .pptx package."""
42
+ _thisdir = os.path.split(__file__)[0]
43
+ return os.path.join(_thisdir, "templates", "default.pptx")
44
+
45
+
46
+ def _is_pptx_package(prs_part: PresentationPart):
47
+ """Return |True| if *prs_part* is a valid main document part, |False| otherwise."""
48
+ valid_content_types = (CT.PML_PRESENTATION_MAIN, CT.PML_PRES_MACRO_MAIN)
49
+ return prs_part.content_type in valid_content_types
pptx/chart/__init__.py ADDED
File without changes