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/chart/plot.py ADDED
@@ -0,0 +1,412 @@
1
+ """Plot-related objects.
2
+
3
+ A plot is known as a chart group in the MS API. A chart can have more than one plot overlayed on
4
+ each other, such as a line plot layered over a bar plot.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from pptx.chart.category import Categories
10
+ from pptx.chart.datalabel import DataLabels
11
+ from pptx.chart.series import SeriesCollection
12
+ from pptx.enum.chart import XL_CHART_TYPE as XL
13
+ from pptx.oxml.ns import qn
14
+ from pptx.oxml.simpletypes import ST_BarDir, ST_Grouping
15
+ from pptx.util import lazyproperty
16
+
17
+
18
+ class _BasePlot(object):
19
+ """
20
+ A distinct plot that appears in the plot area of a chart. A chart may
21
+ have more than one plot, in which case they appear as superimposed
22
+ layers, such as a line plot appearing on top of a bar chart.
23
+ """
24
+
25
+ def __init__(self, xChart, chart):
26
+ super(_BasePlot, self).__init__()
27
+ self._element = xChart
28
+ self._chart = chart
29
+
30
+ @lazyproperty
31
+ def categories(self):
32
+ """
33
+ Returns a |category.Categories| sequence object containing
34
+ a |category.Category| object for each of the category labels
35
+ associated with this plot. The |category.Category| class derives from
36
+ ``str``, so the returned value can be treated as a simple sequence of
37
+ strings for the common case where all you need is the labels in the
38
+ order they appear on the chart. |category.Categories| provides
39
+ additional properties for dealing with hierarchical categories when
40
+ required.
41
+ """
42
+ return Categories(self._element)
43
+
44
+ @property
45
+ def chart(self):
46
+ """
47
+ The |Chart| object containing this plot.
48
+ """
49
+ return self._chart
50
+
51
+ @property
52
+ def data_labels(self):
53
+ """
54
+ |DataLabels| instance providing properties and methods on the
55
+ collection of data labels associated with this plot.
56
+ """
57
+ dLbls = self._element.dLbls
58
+ if dLbls is None:
59
+ raise ValueError("plot has no data labels, set has_data_labels = True first")
60
+ return DataLabels(dLbls)
61
+
62
+ @property
63
+ def has_data_labels(self):
64
+ """
65
+ Read/write boolean, |True| if the series has data labels. Assigning
66
+ |True| causes data labels to be added to the plot. Assigning False
67
+ removes any existing data labels.
68
+ """
69
+ return self._element.dLbls is not None
70
+
71
+ @has_data_labels.setter
72
+ def has_data_labels(self, value):
73
+ """
74
+ Add, remove, or leave alone the ``<c:dLbls>`` child element depending
75
+ on current state and assigned *value*. If *value* is |True| and no
76
+ ``<c:dLbls>`` element is present, a new default element is added with
77
+ default child elements and settings. When |False|, any existing dLbls
78
+ element is removed.
79
+ """
80
+ if bool(value) is False:
81
+ self._element._remove_dLbls()
82
+ else:
83
+ if self._element.dLbls is None:
84
+ dLbls = self._element._add_dLbls()
85
+ dLbls.showVal.val = True
86
+
87
+ @lazyproperty
88
+ def series(self):
89
+ """
90
+ A sequence of |Series| objects representing the series in this plot,
91
+ in the order they appear in the plot.
92
+ """
93
+ return SeriesCollection(self._element)
94
+
95
+ @property
96
+ def vary_by_categories(self):
97
+ """
98
+ Read/write boolean value specifying whether to use a different color
99
+ for each of the points in this plot. Only effective when there is
100
+ a single series; PowerPoint automatically varies color by series when
101
+ more than one series is present.
102
+ """
103
+ varyColors = self._element.varyColors
104
+ if varyColors is None:
105
+ return True
106
+ return varyColors.val
107
+
108
+ @vary_by_categories.setter
109
+ def vary_by_categories(self, value):
110
+ self._element.get_or_add_varyColors().val = bool(value)
111
+
112
+
113
+ class AreaPlot(_BasePlot):
114
+ """
115
+ An area plot.
116
+ """
117
+
118
+
119
+ class Area3DPlot(_BasePlot):
120
+ """
121
+ A 3-dimensional area plot.
122
+ """
123
+
124
+
125
+ class BarPlot(_BasePlot):
126
+ """
127
+ A bar chart-style plot.
128
+ """
129
+
130
+ @property
131
+ def gap_width(self):
132
+ """
133
+ Width of gap between bar(s) of each category, as an integer
134
+ percentage of the bar width. The default value for a new bar chart is
135
+ 150, representing 150% or 1.5 times the width of a single bar.
136
+ """
137
+ gapWidth = self._element.gapWidth
138
+ if gapWidth is None:
139
+ return 150
140
+ return gapWidth.val
141
+
142
+ @gap_width.setter
143
+ def gap_width(self, value):
144
+ gapWidth = self._element.get_or_add_gapWidth()
145
+ gapWidth.val = value
146
+
147
+ @property
148
+ def overlap(self):
149
+ """
150
+ Read/write int value in range -100..100 specifying a percentage of
151
+ the bar width by which to overlap adjacent bars in a multi-series bar
152
+ chart. Default is 0. A setting of -100 creates a gap of a full bar
153
+ width and a setting of 100 causes all the bars in a category to be
154
+ superimposed. A stacked bar plot has overlap of 100 by default.
155
+ """
156
+ overlap = self._element.overlap
157
+ if overlap is None:
158
+ return 0
159
+ return overlap.val
160
+
161
+ @overlap.setter
162
+ def overlap(self, value):
163
+ """
164
+ Set the value of the ``<c:overlap>`` child element to *int_value*,
165
+ or remove the overlap element if *int_value* is 0.
166
+ """
167
+ if value == 0:
168
+ self._element._remove_overlap()
169
+ return
170
+ self._element.get_or_add_overlap().val = value
171
+
172
+
173
+ class BubblePlot(_BasePlot):
174
+ """
175
+ A bubble chart plot.
176
+ """
177
+
178
+ @property
179
+ def bubble_scale(self):
180
+ """
181
+ An integer between 0 and 300 inclusive indicating the percentage of
182
+ the default size at which bubbles should be displayed. Assigning
183
+ |None| produces the same behavior as assigning `100`.
184
+ """
185
+ bubbleScale = self._element.bubbleScale
186
+ if bubbleScale is None:
187
+ return 100
188
+ return bubbleScale.val
189
+
190
+ @bubble_scale.setter
191
+ def bubble_scale(self, value):
192
+ bubbleChart = self._element
193
+ bubbleChart._remove_bubbleScale()
194
+ if value is None:
195
+ return
196
+ bubbleScale = bubbleChart._add_bubbleScale()
197
+ bubbleScale.val = value
198
+
199
+
200
+ class DoughnutPlot(_BasePlot):
201
+ """
202
+ An doughnut plot.
203
+ """
204
+
205
+
206
+ class LinePlot(_BasePlot):
207
+ """
208
+ A line chart-style plot.
209
+ """
210
+
211
+
212
+ class PiePlot(_BasePlot):
213
+ """
214
+ A pie chart-style plot.
215
+ """
216
+
217
+
218
+ class RadarPlot(_BasePlot):
219
+ """
220
+ A radar-style plot.
221
+ """
222
+
223
+
224
+ class XyPlot(_BasePlot):
225
+ """
226
+ An XY (scatter) plot.
227
+ """
228
+
229
+
230
+ def PlotFactory(xChart, chart):
231
+ """
232
+ Return an instance of the appropriate subclass of _BasePlot based on the
233
+ tagname of *xChart*.
234
+ """
235
+ try:
236
+ PlotCls = {
237
+ qn("c:areaChart"): AreaPlot,
238
+ qn("c:area3DChart"): Area3DPlot,
239
+ qn("c:barChart"): BarPlot,
240
+ qn("c:bubbleChart"): BubblePlot,
241
+ qn("c:doughnutChart"): DoughnutPlot,
242
+ qn("c:lineChart"): LinePlot,
243
+ qn("c:pieChart"): PiePlot,
244
+ qn("c:radarChart"): RadarPlot,
245
+ qn("c:scatterChart"): XyPlot,
246
+ }[xChart.tag]
247
+ except KeyError:
248
+ raise ValueError("unsupported plot type %s" % xChart.tag)
249
+
250
+ return PlotCls(xChart, chart)
251
+
252
+
253
+ class PlotTypeInspector(object):
254
+ """
255
+ "One-shot" service object that knows how to identify the type of a plot
256
+ as a member of the XL_CHART_TYPE enumeration.
257
+ """
258
+
259
+ @classmethod
260
+ def chart_type(cls, plot):
261
+ """
262
+ Return the member of :ref:`XlChartType` that corresponds to the chart
263
+ type of *plot*.
264
+ """
265
+ try:
266
+ chart_type_method = {
267
+ "AreaPlot": cls._differentiate_area_chart_type,
268
+ "Area3DPlot": cls._differentiate_area_3d_chart_type,
269
+ "BarPlot": cls._differentiate_bar_chart_type,
270
+ "BubblePlot": cls._differentiate_bubble_chart_type,
271
+ "DoughnutPlot": cls._differentiate_doughnut_chart_type,
272
+ "LinePlot": cls._differentiate_line_chart_type,
273
+ "PiePlot": cls._differentiate_pie_chart_type,
274
+ "RadarPlot": cls._differentiate_radar_chart_type,
275
+ "XyPlot": cls._differentiate_xy_chart_type,
276
+ }[plot.__class__.__name__]
277
+ except KeyError:
278
+ raise NotImplementedError(
279
+ "chart_type() not implemented for %s" % plot.__class__.__name__
280
+ )
281
+ return chart_type_method(plot)
282
+
283
+ @classmethod
284
+ def _differentiate_area_3d_chart_type(cls, plot):
285
+ return {
286
+ ST_Grouping.STANDARD: XL.THREE_D_AREA,
287
+ ST_Grouping.STACKED: XL.THREE_D_AREA_STACKED,
288
+ ST_Grouping.PERCENT_STACKED: XL.THREE_D_AREA_STACKED_100,
289
+ }[plot._element.grouping_val]
290
+
291
+ @classmethod
292
+ def _differentiate_area_chart_type(cls, plot):
293
+ return {
294
+ ST_Grouping.STANDARD: XL.AREA,
295
+ ST_Grouping.STACKED: XL.AREA_STACKED,
296
+ ST_Grouping.PERCENT_STACKED: XL.AREA_STACKED_100,
297
+ }[plot._element.grouping_val]
298
+
299
+ @classmethod
300
+ def _differentiate_bar_chart_type(cls, plot):
301
+ barChart = plot._element
302
+ if barChart.barDir.val == ST_BarDir.BAR:
303
+ return {
304
+ ST_Grouping.CLUSTERED: XL.BAR_CLUSTERED,
305
+ ST_Grouping.STACKED: XL.BAR_STACKED,
306
+ ST_Grouping.PERCENT_STACKED: XL.BAR_STACKED_100,
307
+ }[barChart.grouping_val]
308
+ if barChart.barDir.val == ST_BarDir.COL:
309
+ return {
310
+ ST_Grouping.CLUSTERED: XL.COLUMN_CLUSTERED,
311
+ ST_Grouping.STACKED: XL.COLUMN_STACKED,
312
+ ST_Grouping.PERCENT_STACKED: XL.COLUMN_STACKED_100,
313
+ }[barChart.grouping_val]
314
+ raise ValueError("invalid barChart.barDir value '%s'" % barChart.barDir.val)
315
+
316
+ @classmethod
317
+ def _differentiate_bubble_chart_type(cls, plot):
318
+ def first_bubble3D(bubbleChart):
319
+ results = bubbleChart.xpath("c:ser/c:bubble3D")
320
+ return results[0] if results else None
321
+
322
+ bubbleChart = plot._element
323
+ bubble3D = first_bubble3D(bubbleChart)
324
+
325
+ if bubble3D is None:
326
+ return XL.BUBBLE
327
+ if bubble3D.val:
328
+ return XL.BUBBLE_THREE_D_EFFECT
329
+ return XL.BUBBLE
330
+
331
+ @classmethod
332
+ def _differentiate_doughnut_chart_type(cls, plot):
333
+ doughnutChart = plot._element
334
+ explosion = doughnutChart.xpath("./c:ser/c:explosion")
335
+ return XL.DOUGHNUT_EXPLODED if explosion else XL.DOUGHNUT
336
+
337
+ @classmethod
338
+ def _differentiate_line_chart_type(cls, plot):
339
+ lineChart = plot._element
340
+
341
+ def has_line_markers():
342
+ matches = lineChart.xpath('c:ser/c:marker/c:symbol[@val="none"]')
343
+ if matches:
344
+ return False
345
+ return True
346
+
347
+ if has_line_markers():
348
+ return {
349
+ ST_Grouping.STANDARD: XL.LINE_MARKERS,
350
+ ST_Grouping.STACKED: XL.LINE_MARKERS_STACKED,
351
+ ST_Grouping.PERCENT_STACKED: XL.LINE_MARKERS_STACKED_100,
352
+ }[plot._element.grouping_val]
353
+ else:
354
+ return {
355
+ ST_Grouping.STANDARD: XL.LINE,
356
+ ST_Grouping.STACKED: XL.LINE_STACKED,
357
+ ST_Grouping.PERCENT_STACKED: XL.LINE_STACKED_100,
358
+ }[plot._element.grouping_val]
359
+
360
+ @classmethod
361
+ def _differentiate_pie_chart_type(cls, plot):
362
+ pieChart = plot._element
363
+ explosion = pieChart.xpath("./c:ser/c:explosion")
364
+ return XL.PIE_EXPLODED if explosion else XL.PIE
365
+
366
+ @classmethod
367
+ def _differentiate_radar_chart_type(cls, plot):
368
+ radarChart = plot._element
369
+ radar_style = radarChart.xpath("c:radarStyle")[0].get("val")
370
+
371
+ def noMarkers():
372
+ matches = radarChart.xpath("c:ser/c:marker/c:symbol")
373
+ if matches and matches[0].get("val") == "none":
374
+ return True
375
+ return False
376
+
377
+ if radar_style is None:
378
+ return XL.RADAR
379
+ if radar_style == "filled":
380
+ return XL.RADAR_FILLED
381
+ if noMarkers():
382
+ return XL.RADAR
383
+ return XL.RADAR_MARKERS
384
+
385
+ @classmethod
386
+ def _differentiate_xy_chart_type(cls, plot):
387
+ scatterChart = plot._element
388
+
389
+ def noLine():
390
+ return bool(scatterChart.xpath("c:ser/c:spPr/a:ln/a:noFill"))
391
+
392
+ def noMarkers():
393
+ symbols = scatterChart.xpath("c:ser/c:marker/c:symbol")
394
+ if symbols and symbols[0].get("val") == "none":
395
+ return True
396
+ return False
397
+
398
+ scatter_style = scatterChart.xpath("c:scatterStyle")[0].get("val")
399
+
400
+ if scatter_style == "lineMarker":
401
+ if noLine():
402
+ return XL.XY_SCATTER
403
+ if noMarkers():
404
+ return XL.XY_SCATTER_LINES_NO_MARKERS
405
+ return XL.XY_SCATTER_LINES
406
+
407
+ if scatter_style == "smoothMarker":
408
+ if noMarkers():
409
+ return XL.XY_SCATTER_SMOOTH_NO_MARKERS
410
+ return XL.XY_SCATTER_SMOOTH
411
+
412
+ return XL.XY_SCATTER
pptx/chart/point.py ADDED
@@ -0,0 +1,101 @@
1
+ """Data point-related objects."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Sequence
6
+
7
+ from pptx.chart.datalabel import DataLabel
8
+ from pptx.chart.marker import Marker
9
+ from pptx.dml.chtfmt import ChartFormat
10
+ from pptx.util import lazyproperty
11
+
12
+
13
+ class _BasePoints(Sequence):
14
+ """
15
+ Sequence providing access to the individual data points in a series.
16
+ """
17
+
18
+ def __init__(self, ser):
19
+ super(_BasePoints, self).__init__()
20
+ self._element = ser
21
+ self._ser = ser
22
+
23
+ def __getitem__(self, idx):
24
+ if idx < 0 or idx >= self.__len__():
25
+ raise IndexError("point index out of range")
26
+ return Point(self._ser, idx)
27
+
28
+
29
+ class BubblePoints(_BasePoints):
30
+ """
31
+ Sequence providing access to the individual data points in
32
+ a |BubbleSeries| object.
33
+ """
34
+
35
+ def __len__(self):
36
+ return min(
37
+ self._ser.xVal_ptCount_val,
38
+ self._ser.yVal_ptCount_val,
39
+ self._ser.bubbleSize_ptCount_val,
40
+ )
41
+
42
+
43
+ class CategoryPoints(_BasePoints):
44
+ """
45
+ Sequence providing access to individual |Point| objects, each
46
+ representing the visual properties of a data point in the specified
47
+ category series.
48
+ """
49
+
50
+ def __len__(self):
51
+ return self._ser.cat_ptCount_val
52
+
53
+
54
+ class Point(object):
55
+ """
56
+ Provides access to the properties of an individual data point in
57
+ a series, such as the visual properties of its marker and the text and
58
+ font of its data label.
59
+ """
60
+
61
+ def __init__(self, ser, idx):
62
+ super(Point, self).__init__()
63
+ self._element = ser
64
+ self._ser = ser
65
+ self._idx = idx
66
+
67
+ @lazyproperty
68
+ def data_label(self):
69
+ """
70
+ The |DataLabel| object representing the label on this data point.
71
+ """
72
+ return DataLabel(self._ser, self._idx)
73
+
74
+ @lazyproperty
75
+ def format(self):
76
+ """
77
+ The |ChartFormat| object providing access to the shape formatting
78
+ properties of this data point, such as line and fill.
79
+ """
80
+ dPt = self._ser.get_or_add_dPt_for_point(self._idx)
81
+ return ChartFormat(dPt)
82
+
83
+ @lazyproperty
84
+ def marker(self):
85
+ """
86
+ The |Marker| instance for this point, providing access to the visual
87
+ properties of the data point marker, such as fill and line. Setting
88
+ these properties overrides any value set at the series level.
89
+ """
90
+ dPt = self._ser.get_or_add_dPt_for_point(self._idx)
91
+ return Marker(dPt)
92
+
93
+
94
+ class XyPoints(_BasePoints):
95
+ """
96
+ Sequence providing access to the individual data points in an |XySeries|
97
+ object.
98
+ """
99
+
100
+ def __len__(self):
101
+ return min(self._ser.xVal_ptCount_val, self._ser.yVal_ptCount_val)