This file is indexed.

/usr/lib/python3/dist-packages/xlsxwriter/chart_scatter.py is in python3-xlsxwriter 0.7.3-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
###############################################################################
#
# ChartScatter - A class for writing the Excel XLSX Scatter charts.
#
# Copyright 2013-2015, John McNamara, jmcnamara@cpan.org
#

from . import chart


class ChartScatter(chart.Chart):
    """
    A class for writing the Excel XLSX Scatter charts.


    """

    ###########################################################################
    #
    # Public API.
    #
    ###########################################################################

    def __init__(self, options=None):
        """
        Constructor.

        """
        super(ChartScatter, self).__init__()

        if options is None:
            options = {}

        self.subtype = options.get('subtype')

        if not self.subtype:
            self.subtype = 'marker_only'

        self.cross_between = 'midCat'
        self.horiz_val_axis = 0
        self.val_axis_postion = 'b'
        self.smooth_allowed = True
        self.requires_category = True

        # Set the available data label positions for this chart type.
        self.label_position_default = 'right'
        self.label_positions = {
            'center': 'ctr',
            'right': 'r',
            'left': 'l',
            'above': 't',
            'below': 'b',
            # For backward compatibility.
            'top': 't',
            'bottom': 'b'}

    def combine(self, chart=None):
        """
        Create a combination chart with a secondary chart.

        Note: Override parent method to add a warning.

        Args:
            chart: The secondary chart to combine with the primary chart.

        Returns:
            Nothing.

        """
        if chart is None:
            return

        warn('Combined chart not currently supported with scatter chart '
             'as the primary chart')

    ###########################################################################
    #
    # Private API.
    #
    ###########################################################################

    def _write_chart_type(self, args):
        # Override the virtual superclass method with a chart specific method.
        # Write the c:scatterChart element.
        self._write_scatter_chart(args)

    ###########################################################################
    #
    # XML methods.
    #
    ###########################################################################

    def _write_scatter_chart(self, args):
        # Write the <c:scatterChart> element.

        if args['primary_axes']:
            series = self._get_primary_axes_series()
        else:
            series = self._get_secondary_axes_series()

        if not len(series):
            return

        style = 'lineMarker'
        subtype = self.subtype

        # Set the user defined chart subtype.
        if subtype == 'marker_only':
            style = 'lineMarker'

        if subtype == 'straight_with_markers':
            style = 'lineMarker'

        if subtype == 'straight':
            style = 'lineMarker'

        if subtype == 'smooth_with_markers':
            style = 'smoothMarker'

        if subtype == 'smooth':
            style = 'smoothMarker'

        # Add default formatting to the series data.
        self._modify_series_formatting()

        self._xml_start_tag('c:scatterChart')

        # Write the c:scatterStyle element.
        self._write_scatter_style(style)

        # Write the series elements.
        for data in series:
            self._write_ser(data)

        # Write the c:marker element.
        self._write_marker_value()

        # Write the c:axId elements
        self._write_axis_ids(args)

        self._xml_end_tag('c:scatterChart')

    def _write_ser(self, series):
        # Over-ridden to write c:xVal/c:yVal instead of c:cat/c:val elements.
        # Write the <c:ser> element.

        index = self.series_index
        self.series_index += 1

        self._xml_start_tag('c:ser')

        # Write the c:idx element.
        self._write_idx(index)

        # Write the c:order element.
        self._write_order(index)

        # Write the series name.
        self._write_series_name(series)

        # Write the c:spPr element.
        self._write_sp_pr(series)

        # Write the c:marker element.
        self._write_marker(series.get('marker'))

        # Write the c:dPt element.
        self._write_d_pt(series.get('points'))

        # Write the c:dLbls element.
        self._write_d_lbls(series.get('labels'))

        # Write the c:trendline element.
        self._write_trendline(series.get('trendline'))

        # Write the c:errBars element.
        self._write_error_bars(series.get('error_bars'))

        # Write the c:xVal element.
        self._write_x_val(series)

        # Write the c:yVal element.
        self._write_y_val(series)

        # Write the c:smooth element.
        if 'smooth' in self.subtype and series['smooth'] is None:
            # Default is on for smooth scatter charts.
            self._write_c_smooth(True)
        else:
            self._write_c_smooth(series['smooth'])

        self._xml_end_tag('c:ser')

    def _write_plot_area(self):
        # Over-ridden to have 2 valAx elements for scatter charts instead
        # of catAx/valAx.
        #
        # Write the <c:plotArea> element.
        self._xml_start_tag('c:plotArea')

        # Write the c:layout element.
        self._write_layout(self.plotarea.get('layout'), 'plot')

        # Write the subclass chart elements for primary and secondary axes.
        self._write_chart_type({'primary_axes': 1})
        self._write_chart_type({'primary_axes': 0})

        # Write c:catAx and c:valAx elements for series using primary axes.
        self._write_cat_val_axis({'x_axis': self.x_axis,
                                  'y_axis': self.y_axis,
                                  'axis_ids': self.axis_ids,
                                  'position': 'b',
                                  })

        tmp = self.horiz_val_axis
        self.horiz_val_axis = 1

        self._write_val_axis({'x_axis': self.x_axis,
                              'y_axis': self.y_axis,
                              'axis_ids': self.axis_ids,
                              'position': 'l',
                              })

        self.horiz_val_axis = tmp

        # Write c:valAx and c:catAx elements for series using secondary axes
        self._write_cat_val_axis({'x_axis': self.x2_axis,
                                  'y_axis': self.y2_axis,
                                  'axis_ids': self.axis2_ids,
                                  'position': 'b',
                                  })
        self.horiz_val_axis = 1
        self._write_val_axis({'x_axis': self.x2_axis,
                              'y_axis': self.y2_axis,
                              'axis_ids': self.axis2_ids,
                              'position': 'l',
                              })

        # Write the c:spPr element for the plotarea formatting.
        self._write_sp_pr(self.plotarea)

        self._xml_end_tag('c:plotArea')

    def _write_x_val(self, series):
        # Write the <c:xVal> element.
        formula = series.get('categories')
        data_id = series.get('cat_data_id')
        data = self.formula_data[data_id]

        self._xml_start_tag('c:xVal')

        # Check the type of cached data.
        data_type = self._get_data_type(data)

        # TODO. Can a scatter plot have non-numeric data.
        if data_type == 'str':
            # Write the c:numRef element.
            self._write_str_ref(formula, data, data_type)
        else:
            # Write the c:numRef element.
            self._write_num_ref(formula, data, data_type)

        self._xml_end_tag('c:xVal')

    def _write_y_val(self, series):
        # Write the <c:yVal> element.
        formula = series.get('values')
        data_id = series.get('val_data_id')
        data = self.formula_data[data_id]

        self._xml_start_tag('c:yVal')

        # Unlike Cat axes data should only be numeric.
        # Write the c:numRef element.
        self._write_num_ref(formula, data, 'num')

        self._xml_end_tag('c:yVal')

    def _write_scatter_style(self, val):
        # Write the <c:scatterStyle> element.
        attributes = [('val', val)]

        self._xml_empty_tag('c:scatterStyle', attributes)

    def _modify_series_formatting(self):
        # Add default formatting to the series data unless it has already been
        # specified by the user.
        subtype = self.subtype

        # The default scatter style "markers only" requires a line type.
        if subtype == 'marker_only':

            # Go through each series and define default values.
            for series in self.series:

                # Set a line type unless there is already a user defined type.
                if not series['line']['defined']:
                    series['line'] = {'width': 2.25,
                                      'none': 1,
                                      'defined': 1,
                                      }

        # Turn markers off for subtypes that don't have them.
        if 'marker' not in subtype:
            # Go through each series and define default values.
            for series in self.series:
                # Set a marker type unless there is a user defined type.
                if not series.get('marker'):
                    series['marker'] = {'type': 'none', 'defined': 1}

    def _write_d_pt_point(self, index, point):
        # Write an individual <c:dPt> element. Override the parent method to
        # add markers.

        self._xml_start_tag('c:dPt')

        # Write the c:idx element.
        self._write_idx(index)

        self._xml_start_tag('c:marker')

        # Write the c:spPr element.
        self._write_sp_pr(point)

        self._xml_end_tag('c:marker')

        self._xml_end_tag('c:dPt')