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/parts/slide.py ADDED
@@ -0,0 +1,297 @@
1
+ """Slide and related objects."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import IO, TYPE_CHECKING, cast
6
+
7
+ from pptx.enum.shapes import PROG_ID
8
+ from pptx.opc.constants import CONTENT_TYPE as CT
9
+ from pptx.opc.constants import RELATIONSHIP_TYPE as RT
10
+ from pptx.opc.package import XmlPart
11
+ from pptx.opc.packuri import PackURI
12
+ from pptx.oxml.slide import CT_NotesMaster, CT_NotesSlide, CT_Slide
13
+ from pptx.oxml.theme import CT_OfficeStyleSheet
14
+ from pptx.parts.chart import ChartPart
15
+ from pptx.parts.embeddedpackage import EmbeddedPackagePart
16
+ from pptx.slide import NotesMaster, NotesSlide, Slide, SlideLayout, SlideMaster
17
+ from pptx.util import lazyproperty
18
+
19
+ if TYPE_CHECKING:
20
+ from pptx.chart.data import ChartData
21
+ from pptx.enum.chart import XL_CHART_TYPE
22
+ from pptx.media import Video
23
+ from pptx.parts.image import Image, ImagePart
24
+
25
+
26
+ class BaseSlidePart(XmlPart):
27
+ """Base class for slide parts.
28
+
29
+ This includes slide, slide-layout, and slide-master parts, but also notes-slide,
30
+ notes-master, and handout-master parts.
31
+ """
32
+
33
+ _element: CT_Slide
34
+
35
+ def get_image(self, rId: str) -> Image:
36
+ """Return an |Image| object containing the image related to this slide by *rId*.
37
+
38
+ Raises |KeyError| if no image is related by that id, which would generally indicate a
39
+ corrupted .pptx file.
40
+ """
41
+ return cast("ImagePart", self.related_part(rId)).image
42
+
43
+ def get_or_add_image_part(self, image_file: str | IO[bytes]):
44
+ """Return `(image_part, rId)` pair corresponding to `image_file`.
45
+
46
+ The returned |ImagePart| object contains the image in `image_file` and is
47
+ related to this slide with the key `rId`. If either the image part or
48
+ relationship already exists, they are reused, otherwise they are newly created.
49
+ """
50
+ image_part = self._package.get_or_add_image_part(image_file)
51
+ rId = self.relate_to(image_part, RT.IMAGE)
52
+ return image_part, rId
53
+
54
+ @property
55
+ def name(self) -> str:
56
+ """Internal name of this slide."""
57
+ return self._element.cSld.name
58
+
59
+
60
+ class NotesMasterPart(BaseSlidePart):
61
+ """Notes master part.
62
+
63
+ Corresponds to package file `ppt/notesMasters/notesMaster1.xml`.
64
+ """
65
+
66
+ @classmethod
67
+ def create_default(cls, package):
68
+ """
69
+ Create and return a default notes master part, including creating the
70
+ new theme it requires.
71
+ """
72
+ notes_master_part = cls._new(package)
73
+ theme_part = cls._new_theme_part(package)
74
+ notes_master_part.relate_to(theme_part, RT.THEME)
75
+ return notes_master_part
76
+
77
+ @lazyproperty
78
+ def notes_master(self):
79
+ """
80
+ Return the |NotesMaster| object that proxies this notes master part.
81
+ """
82
+ return NotesMaster(self._element, self)
83
+
84
+ @classmethod
85
+ def _new(cls, package):
86
+ """
87
+ Create and return a standalone, default notes master part based on
88
+ the built-in template (without any related parts, such as theme).
89
+ """
90
+ return NotesMasterPart(
91
+ PackURI("/ppt/notesMasters/notesMaster1.xml"),
92
+ CT.PML_NOTES_MASTER,
93
+ package,
94
+ CT_NotesMaster.new_default(),
95
+ )
96
+
97
+ @classmethod
98
+ def _new_theme_part(cls, package):
99
+ """Return new default theme-part suitable for use with a notes master."""
100
+ return XmlPart(
101
+ package.next_partname("/ppt/theme/theme%d.xml"),
102
+ CT.OFC_THEME,
103
+ package,
104
+ CT_OfficeStyleSheet.new_default(),
105
+ )
106
+
107
+
108
+ class NotesSlidePart(BaseSlidePart):
109
+ """Notes slide part.
110
+
111
+ Contains the slide notes content and the layout for the slide handout page.
112
+ Corresponds to package file `ppt/notesSlides/notesSlide[1-9][0-9]*.xml`.
113
+ """
114
+
115
+ @classmethod
116
+ def new(cls, package, slide_part):
117
+ """Return new |NotesSlidePart| for the slide in `slide_part`.
118
+
119
+ The new notes-slide part is based on the (singleton) notes master and related to
120
+ both the notes-master part and `slide_part`. If no notes-master is present,
121
+ one is created based on the default template.
122
+ """
123
+ notes_master_part = package.presentation_part.notes_master_part
124
+ notes_slide_part = cls._add_notes_slide_part(package, slide_part, notes_master_part)
125
+ notes_slide = notes_slide_part.notes_slide
126
+ notes_slide.clone_master_placeholders(notes_master_part.notes_master)
127
+ return notes_slide_part
128
+
129
+ @lazyproperty
130
+ def notes_master(self):
131
+ """Return the |NotesMaster| object this notes slide inherits from."""
132
+ notes_master_part = self.part_related_by(RT.NOTES_MASTER)
133
+ return notes_master_part.notes_master
134
+
135
+ @lazyproperty
136
+ def notes_slide(self):
137
+ """Return the |NotesSlide| object that proxies this notes slide part."""
138
+ return NotesSlide(self._element, self)
139
+
140
+ @classmethod
141
+ def _add_notes_slide_part(cls, package, slide_part, notes_master_part):
142
+ """Create and return a new notes-slide part.
143
+
144
+ The return part is fully related, but has no shape content (i.e. placeholders
145
+ not cloned).
146
+ """
147
+ notes_slide_part = NotesSlidePart(
148
+ package.next_partname("/ppt/notesSlides/notesSlide%d.xml"),
149
+ CT.PML_NOTES_SLIDE,
150
+ package,
151
+ CT_NotesSlide.new(),
152
+ )
153
+ notes_slide_part.relate_to(notes_master_part, RT.NOTES_MASTER)
154
+ notes_slide_part.relate_to(slide_part, RT.SLIDE)
155
+ return notes_slide_part
156
+
157
+
158
+ class SlidePart(BaseSlidePart):
159
+ """Slide part. Corresponds to package files ppt/slides/slide[1-9][0-9]*.xml."""
160
+
161
+ @classmethod
162
+ def new(cls, partname, package, slide_layout_part):
163
+ """Return newly-created blank slide part.
164
+
165
+ The new slide-part has `partname` and a relationship to `slide_layout_part`.
166
+ """
167
+ slide_part = cls(partname, CT.PML_SLIDE, package, CT_Slide.new())
168
+ slide_part.relate_to(slide_layout_part, RT.SLIDE_LAYOUT)
169
+ return slide_part
170
+
171
+ def add_chart_part(self, chart_type: XL_CHART_TYPE, chart_data: ChartData):
172
+ """Return str rId of new |ChartPart| object containing chart of `chart_type`.
173
+
174
+ The chart depicts `chart_data` and is related to the slide contained in this
175
+ part by `rId`.
176
+ """
177
+ return self.relate_to(ChartPart.new(chart_type, chart_data, self._package), RT.CHART)
178
+
179
+ def add_embedded_ole_object_part(
180
+ self, prog_id: PROG_ID | str, ole_object_file: str | IO[bytes]
181
+ ):
182
+ """Return rId of newly-added OLE-object part formed from `ole_object_file`."""
183
+ relationship_type = RT.PACKAGE if isinstance(prog_id, PROG_ID) else RT.OLE_OBJECT
184
+ return self.relate_to(
185
+ EmbeddedPackagePart.factory(
186
+ prog_id, self._blob_from_file(ole_object_file), self._package
187
+ ),
188
+ relationship_type,
189
+ )
190
+
191
+ def get_or_add_video_media_part(self, video: Video) -> tuple[str, str]:
192
+ """Return rIds for media and video relationships to media part.
193
+
194
+ A new |MediaPart| object is created if it does not already exist
195
+ (such as would occur if the same video appeared more than once in
196
+ a presentation). Two relationships to the media part are created,
197
+ one each with MEDIA and VIDEO relationship types. The need for two
198
+ appears to be for legacy support for an earlier (pre-Office 2010)
199
+ PowerPoint media embedding strategy.
200
+ """
201
+ media_part = self._package.get_or_add_media_part(video)
202
+ media_rId = self.relate_to(media_part, RT.MEDIA)
203
+ video_rId = self.relate_to(media_part, RT.VIDEO)
204
+ return media_rId, video_rId
205
+
206
+ @property
207
+ def has_notes_slide(self):
208
+ """
209
+ Return True if this slide has a notes slide, False otherwise. A notes
210
+ slide is created by the :attr:`notes_slide` property when one doesn't
211
+ exist; use this property to test for a notes slide without the
212
+ possible side-effect of creating one.
213
+ """
214
+ try:
215
+ self.part_related_by(RT.NOTES_SLIDE)
216
+ except KeyError:
217
+ return False
218
+ return True
219
+
220
+ @lazyproperty
221
+ def notes_slide(self) -> NotesSlide:
222
+ """The |NotesSlide| instance associated with this slide.
223
+
224
+ If the slide does not have a notes slide, a new one is created. The same single instance
225
+ is returned on each call.
226
+ """
227
+ try:
228
+ notes_slide_part = self.part_related_by(RT.NOTES_SLIDE)
229
+ except KeyError:
230
+ notes_slide_part = self._add_notes_slide_part()
231
+ return notes_slide_part.notes_slide
232
+
233
+ @lazyproperty
234
+ def slide(self):
235
+ """
236
+ The |Slide| object representing this slide part.
237
+ """
238
+ return Slide(self._element, self)
239
+
240
+ @property
241
+ def slide_id(self) -> int:
242
+ """Return the slide identifier stored in the presentation part for this slide part."""
243
+ presentation_part = self.package.presentation_part
244
+ return presentation_part.slide_id(self)
245
+
246
+ @property
247
+ def slide_layout(self) -> SlideLayout:
248
+ """|SlideLayout| object the slide in this part inherits appearance from."""
249
+ slide_layout_part = self.part_related_by(RT.SLIDE_LAYOUT)
250
+ return slide_layout_part.slide_layout
251
+
252
+ def _add_notes_slide_part(self):
253
+ """
254
+ Return a newly created |NotesSlidePart| object related to this slide
255
+ part. Caller is responsible for ensuring this slide doesn't already
256
+ have a notes slide part.
257
+ """
258
+ notes_slide_part = NotesSlidePart.new(self.package, self)
259
+ self.relate_to(notes_slide_part, RT.NOTES_SLIDE)
260
+ return notes_slide_part
261
+
262
+
263
+ class SlideLayoutPart(BaseSlidePart):
264
+ """Slide layout part.
265
+
266
+ Corresponds to package files ``ppt/slideLayouts/slideLayout[1-9][0-9]*.xml``.
267
+ """
268
+
269
+ @lazyproperty
270
+ def slide_layout(self):
271
+ """
272
+ The |SlideLayout| object representing this part.
273
+ """
274
+ return SlideLayout(self._element, self)
275
+
276
+ @property
277
+ def slide_master(self) -> SlideMaster:
278
+ """Slide master from which this slide layout inherits properties."""
279
+ return self.part_related_by(RT.SLIDE_MASTER).slide_master
280
+
281
+
282
+ class SlideMasterPart(BaseSlidePart):
283
+ """Slide master part.
284
+
285
+ Corresponds to package files ppt/slideMasters/slideMaster[1-9][0-9]*.xml.
286
+ """
287
+
288
+ def related_slide_layout(self, rId: str) -> SlideLayout:
289
+ """Return |SlideLayout| related to this slide-master by key `rId`."""
290
+ return self.related_part(rId).slide_layout
291
+
292
+ @lazyproperty
293
+ def slide_master(self):
294
+ """
295
+ The |SlideMaster| object representing this part.
296
+ """
297
+ return SlideMaster(self._element, self)
pptx/parts/theme.py ADDED
@@ -0,0 +1,13 @@
1
+ """Theme package part."""
2
+
3
+ from pptx.opc.package import XmlPart
4
+ from pptx.theme import Theme
5
+ from pptx.util import lazyproperty
6
+
7
+
8
+ class ThemePart(XmlPart):
9
+ """DrawingML theme with editable colors and fonts."""
10
+
11
+ @lazyproperty
12
+ def theme(self):
13
+ return Theme(self._element)
pptx/presentation.py ADDED
@@ -0,0 +1,113 @@
1
+ """Main presentation object."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import IO, TYPE_CHECKING, cast
6
+
7
+ from pptx.shared import PartElementProxy
8
+ from pptx.slide import SlideMasters, Slides
9
+ from pptx.util import lazyproperty
10
+
11
+ if TYPE_CHECKING:
12
+ from pptx.oxml.presentation import CT_Presentation, CT_SlideId
13
+ from pptx.parts.presentation import PresentationPart
14
+ from pptx.slide import NotesMaster, SlideLayouts
15
+ from pptx.util import Length
16
+
17
+
18
+ class Presentation(PartElementProxy):
19
+ """PresentationML (PML) presentation.
20
+
21
+ Not intended to be constructed directly. Use :func:`pptx.Presentation` to open or
22
+ create a presentation.
23
+ """
24
+
25
+ _element: CT_Presentation
26
+ part: PresentationPart # pyright: ignore[reportIncompatibleMethodOverride]
27
+
28
+ @property
29
+ def core_properties(self):
30
+ """|CoreProperties| instance for this presentation.
31
+
32
+ Provides read/write access to the Dublin Core document properties for the presentation.
33
+ """
34
+ return self.part.core_properties
35
+
36
+ @property
37
+ def notes_master(self) -> NotesMaster:
38
+ """Instance of |NotesMaster| for this presentation.
39
+
40
+ If the presentation does not have a notes master, one is created from a default template
41
+ and returned. The same single instance is returned on each call.
42
+ """
43
+ return self.part.notes_master
44
+
45
+ def save(self, file: str | IO[bytes]):
46
+ """Writes this presentation to `file`.
47
+
48
+ `file` can be either a file-path or a file-like object open for writing bytes.
49
+ """
50
+ self.part.save(file)
51
+
52
+ @property
53
+ def slide_height(self) -> Length | None:
54
+ """Height of slides in this presentation, in English Metric Units (EMU).
55
+
56
+ Returns |None| if no slide width is defined. Read/write.
57
+ """
58
+ sldSz = self._element.sldSz
59
+ if sldSz is None:
60
+ return None
61
+ return sldSz.cy
62
+
63
+ @slide_height.setter
64
+ def slide_height(self, height: Length):
65
+ sldSz = self._element.get_or_add_sldSz()
66
+ sldSz.cy = height
67
+
68
+ @property
69
+ def slide_layouts(self) -> SlideLayouts:
70
+ """|SlideLayouts| collection belonging to the first |SlideMaster| of this presentation.
71
+
72
+ A presentation can have more than one slide master and each master will have its own set
73
+ of layouts. This property is a convenience for the common case where the presentation has
74
+ only a single slide master.
75
+ """
76
+ return self.slide_masters[0].slide_layouts
77
+
78
+ @property
79
+ def slide_master(self):
80
+ """
81
+ First |SlideMaster| object belonging to this presentation. Typically,
82
+ presentations have only a single slide master. This property provides
83
+ simpler access in that common case.
84
+ """
85
+ return self.slide_masters[0]
86
+
87
+ @lazyproperty
88
+ def slide_masters(self) -> SlideMasters:
89
+ """|SlideMasters| collection of slide-masters belonging to this presentation."""
90
+ return SlideMasters(self._element.get_or_add_sldMasterIdLst(), self)
91
+
92
+ @property
93
+ def slide_width(self):
94
+ """
95
+ Width of slides in this presentation, in English Metric Units (EMU).
96
+ Returns |None| if no slide width is defined. Read/write.
97
+ """
98
+ sldSz = self._element.sldSz
99
+ if sldSz is None:
100
+ return None
101
+ return sldSz.cx
102
+
103
+ @slide_width.setter
104
+ def slide_width(self, width: Length):
105
+ sldSz = self._element.get_or_add_sldSz()
106
+ sldSz.cx = width
107
+
108
+ @lazyproperty
109
+ def slides(self):
110
+ """|Slides| object containing the slides in this presentation."""
111
+ sldIdLst = self._element.get_or_add_sldIdLst()
112
+ self.part.rename_slide_parts([cast("CT_SlideId", sldId).rId for sldId in sldIdLst])
113
+ return Slides(sldIdLst, self)
pptx/py.typed ADDED
File without changes
@@ -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 pptx.opc.package import XmlPart
9
+ from pptx.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