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
@@ -0,0 +1,1027 @@
1
+ """Simple-type classes.
2
+
3
+ A "simple-type" is a scalar type, generally serving as an XML attribute. This is in contrast to a
4
+ "complex-type" which would specify an XML element.
5
+
6
+ These objects providing validation and format translation for values stored in XML element
7
+ attributes. Naming generally corresponds to the simple type in the associated XML schema.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import numbers
13
+ from typing import Any
14
+
15
+ from pptx2.exc import InvalidXmlError
16
+ from pptx2.util import Centipoints, Emu
17
+
18
+
19
+ class BaseSimpleType:
20
+ @classmethod
21
+ def from_xml(cls, xml_value: str) -> Any:
22
+ return cls.convert_from_xml(xml_value)
23
+
24
+ @classmethod
25
+ def to_xml(cls, value: Any) -> str:
26
+ cls.validate(value)
27
+ str_value = cls.convert_to_xml(value)
28
+ return str_value
29
+
30
+ @classmethod
31
+ def validate_float(cls, value: Any):
32
+ """Note that int values are accepted."""
33
+ if not isinstance(value, (int, float)):
34
+ raise TypeError("value must be a number, got %s" % type(value))
35
+
36
+ @classmethod
37
+ def validate_int(cls, value):
38
+ if not isinstance(value, numbers.Integral):
39
+ raise TypeError("value must be an integral type, got %s" % type(value))
40
+
41
+ @classmethod
42
+ def validate_float_in_range(cls, value, min_inclusive, max_inclusive):
43
+ cls.validate_float(value)
44
+ if value < min_inclusive or value > max_inclusive:
45
+ raise ValueError(
46
+ "value must be in range %s to %s inclusive, got %s"
47
+ % (min_inclusive, max_inclusive, value)
48
+ )
49
+
50
+ @classmethod
51
+ def validate_int_in_range(cls, value, min_inclusive, max_inclusive):
52
+ cls.validate_int(value)
53
+ if value < min_inclusive or value > max_inclusive:
54
+ raise ValueError(
55
+ "value must be in range %d to %d inclusive, got %d"
56
+ % (min_inclusive, max_inclusive, value)
57
+ )
58
+
59
+ @classmethod
60
+ def validate_string(cls, value):
61
+ if isinstance(value, str):
62
+ return value
63
+ try:
64
+ if isinstance(value, basestring):
65
+ return value
66
+ except NameError: # means we're on Python 3
67
+ pass
68
+ raise TypeError("value must be a string, got %s" % type(value))
69
+
70
+
71
+ class BaseFloatType(BaseSimpleType):
72
+ @classmethod
73
+ def convert_from_xml(cls, str_value):
74
+ return float(str_value)
75
+
76
+ @classmethod
77
+ def convert_to_xml(cls, value):
78
+ return str(float(value))
79
+
80
+ @classmethod
81
+ def validate(cls, value):
82
+ if not isinstance(value, (int, float)):
83
+ raise TypeError("value must be a number, got %s" % type(value))
84
+
85
+
86
+ class BaseIntType(BaseSimpleType):
87
+ @classmethod
88
+ def convert_from_percent_literal(cls, str_value):
89
+ int_str = str_value.replace("%", "")
90
+ return int(int_str)
91
+
92
+ @classmethod
93
+ def convert_from_xml(cls, str_value):
94
+ return int(str_value)
95
+
96
+ @classmethod
97
+ def convert_to_xml(cls, value):
98
+ return str(value)
99
+
100
+ @classmethod
101
+ def validate(cls, value):
102
+ cls.validate_int(value)
103
+
104
+
105
+ class BaseStringType(BaseSimpleType):
106
+ @classmethod
107
+ def convert_from_xml(cls, str_value):
108
+ return str_value
109
+
110
+ @classmethod
111
+ def convert_to_xml(cls, value):
112
+ return value
113
+
114
+ @classmethod
115
+ def validate(cls, value):
116
+ cls.validate_string(value)
117
+
118
+
119
+ class BaseStringEnumerationType(BaseStringType):
120
+ @classmethod
121
+ def validate(cls, value):
122
+ cls.validate_string(value)
123
+ if value not in cls._members:
124
+ raise ValueError("must be one of %s, got '%s'" % (cls._members, value))
125
+
126
+
127
+ class XsdAnyUri(BaseStringType):
128
+ """
129
+ There's a regular expression this is supposed to meet but so far thinking
130
+ spending cycles on validating wouldn't be worth it for the number of
131
+ programming errors it would catch.
132
+ """
133
+
134
+
135
+ class XsdBoolean(BaseSimpleType):
136
+ @classmethod
137
+ def convert_from_xml(cls, str_value):
138
+ if str_value not in ("1", "0", "true", "false"):
139
+ raise InvalidXmlError(
140
+ "value must be one of '1', '0', 'true' or 'false', got '%s'" % str_value
141
+ )
142
+ return str_value in ("1", "true")
143
+
144
+ @classmethod
145
+ def convert_to_xml(cls, value):
146
+ return {True: "1", False: "0"}[value]
147
+
148
+ @classmethod
149
+ def validate(cls, value):
150
+ if value not in (True, False):
151
+ raise TypeError(
152
+ "only True or False (and possibly None) may be assigned, got '%s'" % value
153
+ )
154
+
155
+
156
+ class XsdDouble(BaseFloatType):
157
+ pass
158
+
159
+
160
+ class XsdId(BaseStringType):
161
+ """
162
+ String that must begin with a letter or underscore and cannot contain any
163
+ colons. Not fully validated because not used in external API.
164
+ """
165
+
166
+
167
+ class XsdInt(BaseIntType):
168
+ @classmethod
169
+ def validate(cls, value):
170
+ cls.validate_int_in_range(value, -2147483648, 2147483647)
171
+
172
+
173
+ class XsdLong(BaseIntType):
174
+ @classmethod
175
+ def validate(cls, value):
176
+ cls.validate_int_in_range(value, -9223372036854775808, 9223372036854775807)
177
+
178
+
179
+ class XsdString(BaseStringType):
180
+ pass
181
+
182
+
183
+ class XsdStringEnumeration(BaseStringEnumerationType):
184
+ """
185
+ Set of enumerated xsd:string values.
186
+ """
187
+
188
+
189
+ class XsdToken(BaseStringType):
190
+ """
191
+ xsd:string with whitespace collapsing, e.g. multiple spaces reduced to
192
+ one, leading and trailing space stripped.
193
+ """
194
+
195
+
196
+ class XsdTokenEnumeration(BaseStringEnumerationType):
197
+ """
198
+ xsd:string with whitespace collapsing, e.g. multiple spaces reduced to
199
+ one, leading and trailing space stripped.
200
+ """
201
+
202
+
203
+ class XsdUnsignedByte(BaseIntType):
204
+ @classmethod
205
+ def validate(cls, value):
206
+ cls.validate_int_in_range(value, 0, 255)
207
+
208
+
209
+ class XsdUnsignedInt(BaseIntType):
210
+ @classmethod
211
+ def validate(cls, value):
212
+ cls.validate_int_in_range(value, 0, 4294967295)
213
+
214
+
215
+ class XsdUnsignedShort(BaseIntType):
216
+ @classmethod
217
+ def validate(cls, value):
218
+ cls.validate_int_in_range(value, 0, 65535)
219
+
220
+
221
+ class ST_Angle(XsdInt):
222
+ """
223
+ Valid values for `rot` attribute on `<a:xfrm>` element. 60000ths of
224
+ a degree rotation.
225
+ """
226
+
227
+ DEGREE_INCREMENTS = 60000
228
+ THREE_SIXTY = 360 * DEGREE_INCREMENTS
229
+
230
+ @classmethod
231
+ def convert_from_xml(cls, str_value: str) -> float:
232
+ rot = int(str_value) % cls.THREE_SIXTY
233
+ return float(rot) / cls.DEGREE_INCREMENTS
234
+
235
+ @classmethod
236
+ def convert_to_xml(cls, value):
237
+ """
238
+ Convert signed angle float like -42.42 to int 60000 per degree,
239
+ normalized to positive value.
240
+ """
241
+ # modulo normalizes negative and >360 degree values
242
+ rot = int(round(value * cls.DEGREE_INCREMENTS)) % cls.THREE_SIXTY
243
+ return str(rot)
244
+
245
+ @classmethod
246
+ def validate(cls, value):
247
+ BaseFloatType.validate(value)
248
+
249
+
250
+ class ST_AxisUnit(XsdDouble):
251
+ """
252
+ Valid values for val attribute on c:majorUnit and others.
253
+ """
254
+
255
+ @classmethod
256
+ def validate(cls, value):
257
+ super(ST_AxisUnit, cls).validate(value)
258
+ if value <= 0.0:
259
+ raise ValueError("must be positive numeric value, got %s" % value)
260
+
261
+
262
+ class ST_BarDir(XsdStringEnumeration):
263
+ """
264
+ Valid values for <c:barDir val="?"> attribute
265
+ """
266
+
267
+ BAR = "bar"
268
+ COL = "col"
269
+
270
+ _members = (BAR, COL)
271
+
272
+
273
+ class ST_BubbleScale(BaseIntType):
274
+ """
275
+ String value is an integer in range 0-300, representing a percent,
276
+ optionally including a '%' suffix.
277
+ """
278
+
279
+ @classmethod
280
+ def convert_from_xml(cls, str_value):
281
+ if "%" in str_value:
282
+ return cls.convert_from_percent_literal(str_value)
283
+ return super(ST_BubbleScale, cls).convert_from_xml(str_value)
284
+
285
+ @classmethod
286
+ def validate(cls, value):
287
+ cls.validate_int_in_range(value, 0, 300)
288
+
289
+
290
+ class ST_ContentType(XsdString):
291
+ """
292
+ Has a pretty wicked regular expression it needs to match in the schema,
293
+ but figuring it's not worth the trouble or run time to identify
294
+ a programming error (as opposed to a user/runtime error).
295
+ """
296
+
297
+ pass
298
+
299
+
300
+ class ST_Coordinate(BaseSimpleType):
301
+ @classmethod
302
+ def convert_from_xml(cls, str_value):
303
+ if "i" in str_value or "m" in str_value or "p" in str_value:
304
+ return ST_UniversalMeasure.convert_from_xml(str_value)
305
+ return Emu(int(str_value))
306
+
307
+ @classmethod
308
+ def convert_to_xml(cls, value):
309
+ return str(value)
310
+
311
+ @classmethod
312
+ def validate(cls, value):
313
+ ST_CoordinateUnqualified.validate(value)
314
+
315
+
316
+ class ST_Coordinate32(BaseSimpleType):
317
+ """
318
+ xsd:union of ST_Coordinate32Unqualified, ST_UniversalMeasure
319
+ """
320
+
321
+ @classmethod
322
+ def convert_from_xml(cls, str_value):
323
+ if "i" in str_value or "m" in str_value or "p" in str_value:
324
+ return ST_UniversalMeasure.convert_from_xml(str_value)
325
+ return ST_Coordinate32Unqualified.convert_from_xml(str_value)
326
+
327
+ @classmethod
328
+ def convert_to_xml(cls, value):
329
+ return ST_Coordinate32Unqualified.convert_to_xml(value)
330
+
331
+ @classmethod
332
+ def validate(cls, value):
333
+ ST_Coordinate32Unqualified.validate(value)
334
+
335
+
336
+ class ST_Coordinate32Unqualified(XsdInt):
337
+ @classmethod
338
+ def convert_from_xml(cls, str_value):
339
+ return Emu(int(str_value))
340
+
341
+
342
+ class ST_CoordinateUnqualified(XsdLong):
343
+ @classmethod
344
+ def validate(cls, value):
345
+ cls.validate_int_in_range(value, -27273042329600, 27273042316900)
346
+
347
+
348
+ class ST_Direction(XsdTokenEnumeration):
349
+ """Valid values for `<p:ph orient="...">` attribute."""
350
+
351
+ HORZ = "horz"
352
+ VERT = "vert"
353
+
354
+ _members = (HORZ, VERT)
355
+
356
+
357
+ class ST_DrawingElementId(XsdUnsignedInt):
358
+ pass
359
+
360
+
361
+ class ST_Extension(XsdString):
362
+ """
363
+ Has a regular expression it needs to match in the schema, but figuring
364
+ it's not worth the trouble or run time to identify a programming error
365
+ (as opposed to a user/runtime error).
366
+ """
367
+
368
+ pass
369
+
370
+
371
+ class ST_FixedAngle(ST_Angle):
372
+ """Skew angle in 60000ths of a degree, exclusive range (-90, 90) degrees.
373
+
374
+ Used for `kx`/`ky` skew attributes (e.g. `a:reflection`). Unlike
375
+ |ST_Angle|, values are *not* normalized modulo 360 — the schema range is
376
+ (-5400000, 5400000) exclusive, so a negative skew must stay negative in
377
+ the XML and out-of-range values are rejected.
378
+ """
379
+
380
+ @classmethod
381
+ def convert_from_xml(cls, str_value: str) -> float:
382
+ return int(str_value) / cls.DEGREE_INCREMENTS
383
+
384
+ @classmethod
385
+ def convert_to_xml(cls, value):
386
+ return str(int(round(value * cls.DEGREE_INCREMENTS)))
387
+
388
+ @classmethod
389
+ def validate(cls, value):
390
+ BaseFloatType.validate(value)
391
+ if not -90.0 < value < 90.0:
392
+ raise ValueError(
393
+ "skew angle must be strictly between -90.0 and 90.0 degrees, got %s" % value
394
+ )
395
+
396
+
397
+ class ST_GapAmount(BaseIntType):
398
+ """
399
+ String value is an integer in range 0-500, representing a percent,
400
+ optionally including a '%' suffix.
401
+ """
402
+
403
+ @classmethod
404
+ def convert_from_xml(cls, str_value):
405
+ if "%" in str_value:
406
+ return cls.convert_from_percent_literal(str_value)
407
+ return super(ST_GapAmount, cls).convert_from_xml(str_value)
408
+
409
+ @classmethod
410
+ def validate(cls, value):
411
+ cls.validate_int_in_range(value, 0, 500)
412
+
413
+
414
+ class ST_Grouping(XsdStringEnumeration):
415
+ """
416
+ Valid values for <c:grouping val=""> attribute. Overloaded for use as
417
+ ST_BarGrouping using same tag name.
418
+ """
419
+
420
+ CLUSTERED = "clustered"
421
+ PERCENT_STACKED = "percentStacked"
422
+ STACKED = "stacked"
423
+ STANDARD = "standard"
424
+
425
+ _members = (CLUSTERED, PERCENT_STACKED, STACKED, STANDARD)
426
+
427
+
428
+ class ST_HexColorRGB(BaseStringType):
429
+ @classmethod
430
+ def convert_to_xml(cls, value):
431
+ """
432
+ Keep alpha characters all uppercase just for consistency.
433
+ """
434
+ return value.upper()
435
+
436
+ @classmethod
437
+ def validate(cls, value):
438
+ # must be string ---------------
439
+ str_value = cls.validate_string(value)
440
+
441
+ # must be 6 chars long----------
442
+ if len(str_value) != 6:
443
+ raise ValueError("RGB string must be six characters long, got '%s'" % str_value)
444
+
445
+ # must parse as hex int --------
446
+ try:
447
+ int(str_value, 16)
448
+ except ValueError:
449
+ raise ValueError("RGB string must be valid hex string, got '%s'" % str_value)
450
+
451
+
452
+ class ST_HoleSize(BaseIntType):
453
+ """
454
+ String value is an integer in range 10-90, representing a percent,
455
+ optionally including a '%' suffix. Used for the `val` attribute of the
456
+ `c:holeSize` element of a doughnut chart.
457
+ """
458
+
459
+ @classmethod
460
+ def convert_from_xml(cls, str_value):
461
+ if "%" in str_value:
462
+ return int(str_value[:-1])
463
+ return super(ST_HoleSize, cls).convert_from_xml(str_value)
464
+
465
+ @classmethod
466
+ def validate(cls, value):
467
+ cls.validate_int_in_range(value, 10, 90)
468
+
469
+
470
+ class ST_LayoutMode(XsdStringEnumeration):
471
+ """
472
+ Valid values for `val` attribute on c:xMode and other elements of type
473
+ CT_LayoutMode.
474
+ """
475
+
476
+ EDGE = "edge"
477
+ FACTOR = "factor"
478
+
479
+ _members = (EDGE, FACTOR)
480
+
481
+
482
+ class ST_LblOffset(XsdUnsignedShort):
483
+ """
484
+ Unsigned integer value between 0 and 1000 inclusive, with optional
485
+ percent character ('%') suffix.
486
+ """
487
+
488
+ @classmethod
489
+ def convert_from_xml(cls, str_value):
490
+ if str_value.endswith("%"):
491
+ return cls.convert_from_percent_literal(str_value)
492
+ return int(str_value)
493
+
494
+ @classmethod
495
+ def validate(cls, value):
496
+ cls.validate_int_in_range(value, 0, 1000)
497
+
498
+
499
+ class ST_LineWidth(XsdInt):
500
+ @classmethod
501
+ def convert_from_xml(cls, str_value):
502
+ return Emu(int(str_value))
503
+
504
+ @classmethod
505
+ def validate(cls, value):
506
+ super(ST_LineWidth, cls).validate(value)
507
+ if value < 0 or value > 20116800:
508
+ raise ValueError(
509
+ "value must be in range 0-20116800 inclusive (0-1584 points), got %d" % value
510
+ )
511
+
512
+
513
+ class ST_LogBase(XsdDouble):
514
+ """
515
+ Valid values for the `val` attribute of the `c:logBase` element, a float
516
+ in range 2-1000 inclusive specifying a logarithmic axis scale base.
517
+ """
518
+
519
+ @classmethod
520
+ def validate(cls, value):
521
+ super(ST_LogBase, cls).validate(value)
522
+ if value < 2 or value > 1000:
523
+ raise ValueError("value must be in range 2 to 1000 inclusive, got %s" % value)
524
+
525
+
526
+ class ST_MarkerSize(XsdUnsignedByte):
527
+ @classmethod
528
+ def validate(cls, value):
529
+ cls.validate_int_in_range(value, 2, 72)
530
+
531
+
532
+ class ST_Orientation(XsdStringEnumeration):
533
+ """Valid values for `val` attribute on c:orientation (CT_Orientation)."""
534
+
535
+ MAX_MIN = "maxMin"
536
+ MIN_MAX = "minMax"
537
+
538
+ _members = (MAX_MIN, MIN_MAX)
539
+
540
+
541
+ class ST_Overlap(BaseIntType):
542
+ """
543
+ String value is an integer in range -100..100, representing a percent,
544
+ optionally including a '%' suffix.
545
+ """
546
+
547
+ @classmethod
548
+ def convert_from_xml(cls, str_value):
549
+ if "%" in str_value:
550
+ return cls.convert_from_percent_literal(str_value)
551
+ return super(ST_Overlap, cls).convert_from_xml(str_value)
552
+
553
+ @classmethod
554
+ def validate(cls, value):
555
+ cls.validate_int_in_range(value, -100, 100)
556
+
557
+
558
+ class ST_Percentage(BaseIntType):
559
+ """Percentage value like 42000 or '42.0%'
560
+
561
+ Either an integer literal representing 1000ths of a percent
562
+ (e.g. "42000"), or a floating point literal with a '%' suffix
563
+ (e.g. "42.0%).
564
+ """
565
+
566
+ @classmethod
567
+ def convert_from_xml(cls, str_value):
568
+ if "%" in str_value:
569
+ return cls._convert_from_percent_literal(str_value)
570
+ return int(str_value) / 100000.0
571
+
572
+ @classmethod
573
+ def convert_to_xml(cls, value):
574
+ return str(int(round(value * 100000.0)))
575
+
576
+ @classmethod
577
+ def validate(cls, value):
578
+ cls.validate_float_in_range(value, -21474.83648, 21474.83647)
579
+
580
+ @classmethod
581
+ def _convert_from_percent_literal(cls, str_value):
582
+ float_part = str_value[:-1] # trim off '%' character
583
+ return float(float_part) / 100.0
584
+
585
+
586
+ class ST_FixedPercentage(ST_Percentage):
587
+ """Percentage constrained to [-100%, 100%], as a float in [-1.0, 1.0].
588
+
589
+ Same lexical forms as |ST_Percentage| (1000ths-of-a-percent integer or
590
+ "-42.0%" literal), restricted to the ST_FixedPercentage schema range.
591
+ """
592
+
593
+ @classmethod
594
+ def validate(cls, value):
595
+ cls.validate_float_in_range(value, -1.0, 1.0)
596
+
597
+
598
+ class ST_PathShadeType(XsdStringEnumeration):
599
+ """Valid values for `a:path@path` attribute on a gradient `<a:path>` element."""
600
+
601
+ CIRCLE = "circle"
602
+ RECT = "rect"
603
+ SHAPE = "shape"
604
+
605
+ _members = (CIRCLE, RECT, SHAPE)
606
+
607
+
608
+ class ST_PlaceholderSize(XsdTokenEnumeration):
609
+ """
610
+ Valid values for <p:ph> sz (size) attribute
611
+ """
612
+
613
+ FULL = "full"
614
+ HALF = "half"
615
+ QUARTER = "quarter"
616
+
617
+ _members = (FULL, HALF, QUARTER)
618
+
619
+
620
+ class ST_PositiveCoordinate(XsdLong):
621
+ @classmethod
622
+ def convert_from_xml(cls, str_value):
623
+ int_value = super(ST_PositiveCoordinate, cls).convert_from_xml(str_value)
624
+ return Emu(int_value)
625
+
626
+ @classmethod
627
+ def validate(cls, value):
628
+ cls.validate_int_in_range(value, 0, 27273042316900)
629
+
630
+
631
+ class ST_PositiveFixedAngle(ST_Angle):
632
+ """Valid values for `a:lin@ang`.
633
+
634
+ 60000ths of a degree rotation, constained to positive angles less than
635
+ 360 degrees.
636
+ """
637
+
638
+ @classmethod
639
+ def convert_to_xml(cls, degrees):
640
+ """Convert signed angle float like -427.42 to int 60000 per degree.
641
+
642
+ Value is normalized to a positive value less than 360 degrees.
643
+ """
644
+ if degrees < 0.0:
645
+ degrees %= -360
646
+ degrees += 360
647
+ elif degrees > 0.0:
648
+ degrees %= 360
649
+
650
+ return str(int(round(degrees * cls.DEGREE_INCREMENTS)))
651
+
652
+
653
+ class ST_PositiveFixedPercentage(ST_Percentage):
654
+ """Percentage value between 0 and 100% like 42000 or '42.0%'
655
+
656
+ Either an integer literal representing 1000ths of a percent
657
+ (e.g. "42000"), or a floating point literal with a '%' suffix
658
+ (e.g. "42.0%). Value is constrained to range of 0% to 100%. The source
659
+ value is a float between 0.0 and 1.0.
660
+ """
661
+
662
+ @classmethod
663
+ def validate(cls, value):
664
+ cls.validate_float_in_range(value, 0.0, 1.0)
665
+
666
+
667
+ class ST_RelationshipId(XsdString):
668
+ pass
669
+
670
+
671
+ class ST_SlideId(XsdUnsignedInt):
672
+ @classmethod
673
+ def validate(cls, value):
674
+ cls.validate_int_in_range(value, 256, 2147483647)
675
+
676
+
677
+ class ST_SlideSizeCoordinate(BaseIntType):
678
+ @classmethod
679
+ def convert_from_xml(cls, str_value):
680
+ return Emu(str_value)
681
+
682
+ @classmethod
683
+ def validate(cls, value):
684
+ cls.validate_int(value)
685
+ if value < 914400 or value > 51206400:
686
+ raise ValueError(
687
+ "value must be in range(914400, 51206400) (1-56 inches), got %d" % value
688
+ )
689
+
690
+
691
+ class ST_Style(XsdUnsignedByte):
692
+ @classmethod
693
+ def validate(cls, value):
694
+ cls.validate_int_in_range(value, 1, 48)
695
+
696
+
697
+ class ST_TargetMode(XsdString):
698
+ """
699
+ The valid values for the ``TargetMode`` attribute in a Relationship
700
+ element, either 'External' or 'Internal'.
701
+ """
702
+
703
+ @classmethod
704
+ def validate(cls, value):
705
+ cls.validate_string(value)
706
+ if value not in ("External", "Internal"):
707
+ raise ValueError("must be one of 'Internal' or 'External', got '%s'" % value)
708
+
709
+
710
+ class ST_TextFontScalePercentOrPercentString(BaseFloatType):
711
+ """
712
+ Valid values for the `fontScale` attribute of ``<a:normAutofit>``.
713
+ Translates to a float value.
714
+ """
715
+
716
+ @classmethod
717
+ def convert_from_xml(cls, str_value):
718
+ if str_value.endswith("%"):
719
+ return float(str_value[:-1]) # trim off '%' character
720
+ return int(str_value) / 1000.0
721
+
722
+ @classmethod
723
+ def convert_to_xml(cls, value):
724
+ return str(int(value * 1000.0))
725
+
726
+ @classmethod
727
+ def validate(cls, value):
728
+ BaseFloatType.validate(value)
729
+ if value < 1.0 or value > 100.0:
730
+ raise ValueError("value must be in range 1.0..100.0 (percent), got %s" % value)
731
+
732
+
733
+ class ST_TextFontSize(BaseIntType):
734
+ @classmethod
735
+ def validate(cls, value):
736
+ cls.validate_int_in_range(value, 100, 400000)
737
+
738
+
739
+ class ST_TextIndentLevelType(BaseIntType):
740
+ @classmethod
741
+ def validate(cls, value):
742
+ cls.validate_int_in_range(value, 0, 8)
743
+
744
+
745
+ class ST_PositiveCoordinate32(BaseSimpleType):
746
+ """Non-negative ST_Coordinate32 (xsd:int EMU >= 0).
747
+
748
+ Used for the `spcCol` attribute on `<a:bodyPr>` (inter-column spacing).
749
+ """
750
+
751
+ @classmethod
752
+ def convert_from_xml(cls, str_value):
753
+ if "i" in str_value or "m" in str_value or "p" in str_value:
754
+ return ST_UniversalMeasure.convert_from_xml(str_value)
755
+ return Emu(int(str_value))
756
+
757
+ @classmethod
758
+ def convert_to_xml(cls, value):
759
+ return str(int(value))
760
+
761
+ @classmethod
762
+ def validate(cls, value):
763
+ cls.validate_int_in_range(value, 0, 2147483647)
764
+
765
+
766
+ class ST_TextColumnCount(BaseIntType):
767
+ """Valid values for the `numCol` attribute on `<a:bodyPr>` (1..16)."""
768
+
769
+ @classmethod
770
+ def validate(cls, value):
771
+ cls.validate_int_in_range(value, 1, 16)
772
+
773
+
774
+ class ST_TextBulletStartAtNum(BaseIntType):
775
+ """Valid values for `startAt` on `<a:buAutoNum>` (1..32767)."""
776
+
777
+ @classmethod
778
+ def validate(cls, value):
779
+ cls.validate_int_in_range(value, 1, 32767)
780
+
781
+
782
+ class ST_TextTabAlignType(XsdTokenEnumeration):
783
+ """Valid values for the `algn` attribute on an `<a:tab>` tab stop."""
784
+
785
+ L = "l"
786
+ CTR = "ctr"
787
+ R = "r"
788
+ DEC = "dec"
789
+
790
+ _members = (L, CTR, R, DEC)
791
+
792
+
793
+ class ST_TextAutonumberScheme(XsdTokenEnumeration):
794
+ """Valid values for the `type` attribute on `<a:buAutoNum>`.
795
+
796
+ The ISO/IEC 29500 ``ST_TextAutonumberScheme`` enumeration of numbered-list
797
+ numbering schemes (arabic, roman, alphabetic, etc.).
798
+ """
799
+
800
+ ALPHA_LC_PAREN_BOTH = "alphaLcParenBoth"
801
+ ALPHA_UC_PAREN_BOTH = "alphaUcParenBoth"
802
+ ALPHA_LC_PAREN_R = "alphaLcParenR"
803
+ ALPHA_UC_PAREN_R = "alphaUcParenR"
804
+ ALPHA_LC_PERIOD = "alphaLcPeriod"
805
+ ALPHA_UC_PERIOD = "alphaUcPeriod"
806
+ ARABIC_PAREN_BOTH = "arabicParenBoth"
807
+ ARABIC_PAREN_R = "arabicParenR"
808
+ ARABIC_PERIOD = "arabicPeriod"
809
+ ARABIC_PLAIN = "arabicPlain"
810
+ ROMAN_LC_PAREN_BOTH = "romanLcParenBoth"
811
+ ROMAN_UC_PAREN_BOTH = "romanUcParenBoth"
812
+ ROMAN_LC_PAREN_R = "romanLcParenR"
813
+ ROMAN_UC_PAREN_R = "romanUcParenR"
814
+ ROMAN_LC_PERIOD = "romanLcPeriod"
815
+ ROMAN_UC_PERIOD = "romanUcPeriod"
816
+ CIRCLE_NUM_DB_PLAIN = "circleNumDbPlain"
817
+ CIRCLE_NUM_WD_BLACK_PLAIN = "circleNumWdBlackPlain"
818
+ CIRCLE_NUM_WD_WHITE_PLAIN = "circleNumWdWhitePlain"
819
+ ARABIC_DB_PERIOD = "arabicDbPeriod"
820
+ ARABIC_DB_PLAIN = "arabicDbPlain"
821
+ EA_1_CHS_PERIOD = "ea1ChsPeriod"
822
+ EA_1_CHS_PLAIN = "ea1ChsPlain"
823
+ EA_1_CHT_PERIOD = "ea1ChtPeriod"
824
+ EA_1_CHT_PLAIN = "ea1ChtPlain"
825
+ EA_1_JPN_CHS_DB_PERIOD = "ea1JpnChsDbPeriod"
826
+ EA_1_JPN_KOR_PLAIN = "ea1JpnKorPlain"
827
+ EA_1_JPN_KOR_PERIOD = "ea1JpnKorPeriod"
828
+ ARABIC_1_MINUS = "arabic1Minus"
829
+ ARABIC_2_MINUS = "arabic2Minus"
830
+ HEBREW_2_MINUS = "hebrew2Minus"
831
+ THAI_ALPHA_PERIOD = "thaiAlphaPeriod"
832
+ THAI_ALPHA_PAREN_R = "thaiAlphaParenR"
833
+ THAI_ALPHA_PAREN_BOTH = "thaiAlphaParenBoth"
834
+ THAI_NUM_PERIOD = "thaiNumPeriod"
835
+ THAI_NUM_PAREN_R = "thaiNumParenR"
836
+ THAI_NUM_PAREN_BOTH = "thaiNumParenBoth"
837
+ HINDI_ALPHA_PERIOD = "hindiAlphaPeriod"
838
+ HINDI_NUM_PERIOD = "hindiNumPeriod"
839
+ HINDI_NUM_PAREN_R = "hindiNumParenR"
840
+ HINDI_ALPHA_1_PERIOD = "hindiAlpha1Period"
841
+
842
+ _members = (
843
+ ALPHA_LC_PAREN_BOTH,
844
+ ALPHA_UC_PAREN_BOTH,
845
+ ALPHA_LC_PAREN_R,
846
+ ALPHA_UC_PAREN_R,
847
+ ALPHA_LC_PERIOD,
848
+ ALPHA_UC_PERIOD,
849
+ ARABIC_PAREN_BOTH,
850
+ ARABIC_PAREN_R,
851
+ ARABIC_PERIOD,
852
+ ARABIC_PLAIN,
853
+ ROMAN_LC_PAREN_BOTH,
854
+ ROMAN_UC_PAREN_BOTH,
855
+ ROMAN_LC_PAREN_R,
856
+ ROMAN_UC_PAREN_R,
857
+ ROMAN_LC_PERIOD,
858
+ ROMAN_UC_PERIOD,
859
+ CIRCLE_NUM_DB_PLAIN,
860
+ CIRCLE_NUM_WD_BLACK_PLAIN,
861
+ CIRCLE_NUM_WD_WHITE_PLAIN,
862
+ ARABIC_DB_PERIOD,
863
+ ARABIC_DB_PLAIN,
864
+ EA_1_CHS_PERIOD,
865
+ EA_1_CHS_PLAIN,
866
+ EA_1_CHT_PERIOD,
867
+ EA_1_CHT_PLAIN,
868
+ EA_1_JPN_CHS_DB_PERIOD,
869
+ EA_1_JPN_KOR_PLAIN,
870
+ EA_1_JPN_KOR_PERIOD,
871
+ ARABIC_1_MINUS,
872
+ ARABIC_2_MINUS,
873
+ HEBREW_2_MINUS,
874
+ THAI_ALPHA_PERIOD,
875
+ THAI_ALPHA_PAREN_R,
876
+ THAI_ALPHA_PAREN_BOTH,
877
+ THAI_NUM_PERIOD,
878
+ THAI_NUM_PAREN_R,
879
+ THAI_NUM_PAREN_BOTH,
880
+ HINDI_ALPHA_PERIOD,
881
+ HINDI_NUM_PERIOD,
882
+ HINDI_NUM_PAREN_R,
883
+ HINDI_ALPHA_1_PERIOD,
884
+ )
885
+
886
+
887
+ class ST_TextSpacingPercentOrPercentString(BaseFloatType):
888
+ @classmethod
889
+ def convert_from_xml(cls, str_value):
890
+ if str_value.endswith("%"):
891
+ return cls._convert_from_percent_literal(str_value)
892
+ return int(str_value) / 100000.0
893
+
894
+ @classmethod
895
+ def _convert_from_percent_literal(cls, str_value):
896
+ float_part = str_value[:-1] # trim off '%' character
897
+ percent_value = float(float_part)
898
+ lines_value = percent_value / 100.0
899
+ return lines_value
900
+
901
+ @classmethod
902
+ def convert_to_xml(cls, value):
903
+ """
904
+ 1.75 -> '175000'
905
+ """
906
+ lines = value * 100000.0
907
+ return str(int(round(lines)))
908
+
909
+ @classmethod
910
+ def validate(cls, value):
911
+ cls.validate_float_in_range(value, 0.0, 132.0)
912
+
913
+
914
+ class ST_TextSpacingPoint(BaseIntType):
915
+ @classmethod
916
+ def convert_from_xml(cls, str_value):
917
+ """
918
+ Reads string integer centipoints, returns |Length| value.
919
+ """
920
+ return Centipoints(int(str_value))
921
+
922
+ @classmethod
923
+ def convert_to_xml(cls, value):
924
+ length = Emu(value) # just to make sure
925
+ return str(length.centipoints)
926
+
927
+ @classmethod
928
+ def validate(cls, value):
929
+ cls.validate_int_in_range(value, 0, 20116800)
930
+
931
+
932
+ class ST_TextPoint(BaseIntType):
933
+ """Letter-spacing (tracking) value, `<a:rPr spc="">`.
934
+
935
+ Stored in the XML as signed integer centipoints (1/100 pt), in the range
936
+ -400000..400000 (i.e. -4000pt..4000pt). Exposed to Python as a |Length|.
937
+ """
938
+
939
+ @classmethod
940
+ def convert_from_xml(cls, str_value):
941
+ return Centipoints(int(str_value))
942
+
943
+ @classmethod
944
+ def convert_to_xml(cls, value):
945
+ return str(Emu(value).centipoints)
946
+
947
+ @classmethod
948
+ def validate(cls, value):
949
+ cls.validate_int_in_range(Emu(value).centipoints, -400000, 400000)
950
+
951
+
952
+ class ST_TextCapsType(XsdTokenEnumeration):
953
+ """Valid values for `<a:rPr cap="">` (capitalization effect)."""
954
+
955
+ NONE = "none"
956
+ SMALL = "small"
957
+ ALL = "all"
958
+
959
+ _members = (NONE, SMALL, ALL)
960
+
961
+
962
+ class ST_TextStrikeType(XsdTokenEnumeration):
963
+ """Valid values for `<a:rPr strike="">` (strikethrough effect)."""
964
+
965
+ NO_STRIKE = "noStrike"
966
+ SINGLE = "sngStrike"
967
+ DOUBLE = "dblStrike"
968
+
969
+ _members = (NO_STRIKE, SINGLE, DOUBLE)
970
+
971
+
972
+ class ST_TextVerticalType(XsdTokenEnumeration):
973
+ """Valid values for the `vert` attribute (text direction).
974
+
975
+ Used on `<a:bodyPr vert="">` and `<a:tcPr vert="">` to rotate or stack
976
+ cell/shape text. See ST_TextVerticalType in the ISO/IEC 29500 schema.
977
+ """
978
+
979
+ HORZ = "horz"
980
+ VERT = "vert"
981
+ VERT_270 = "vert270"
982
+ WORD_ART_VERT = "wordArtVert"
983
+ EA_VERT = "eaVert"
984
+ MONGOLIAN_VERT = "mongolianVert"
985
+ WORD_ART_VERT_RTL = "wordArtVertRtl"
986
+
987
+ _members = (
988
+ HORZ,
989
+ VERT,
990
+ VERT_270,
991
+ WORD_ART_VERT,
992
+ EA_VERT,
993
+ MONGOLIAN_VERT,
994
+ WORD_ART_VERT_RTL,
995
+ )
996
+
997
+
998
+ class ST_TextTypeface(XsdString):
999
+ pass
1000
+
1001
+
1002
+ class ST_TextWrappingType(XsdTokenEnumeration):
1003
+ """
1004
+ Valid values for <a:bodyPr wrap=""> attribute
1005
+ """
1006
+
1007
+ NONE = "none"
1008
+ SQUARE = "square"
1009
+
1010
+ _members = (NONE, SQUARE)
1011
+
1012
+
1013
+ class ST_UniversalMeasure(BaseSimpleType):
1014
+ @classmethod
1015
+ def convert_from_xml(cls, str_value):
1016
+ float_part, units_part = str_value[:-2], str_value[-2:]
1017
+ quantity = float(float_part)
1018
+ multiplier = {
1019
+ "mm": 36000,
1020
+ "cm": 360000,
1021
+ "in": 914400,
1022
+ "pt": 12700,
1023
+ "pc": 152400,
1024
+ "pi": 152400,
1025
+ }[units_part]
1026
+ emu_value = Emu(int(round(quantity * multiplier)))
1027
+ return emu_value