This file is indexed.

/usr/lib/python3/dist-packages/pygal/graph/stackedbar.py is in python3-pygal 2.4.0-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
# -*- coding: utf-8 -*-
# This file is part of pygal
#
# A python svg graph plotting library
# Copyright © 2012-2016 Kozea
#
# This library is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This library is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with pygal. If not, see <http://www.gnu.org/licenses/>.
"""
Stacked Bar chart: Like a bar chart but with all series stacking
on top of the others instead of being displayed side by side.
"""

from __future__ import division

from pygal.adapters import none_to_zero
from pygal.graph.bar import Bar


class StackedBar(Bar):

    """Stacked Bar graph class"""

    _adapters = [none_to_zero]

    def _get_separated_values(self, secondary=False):
        """Separate values between positives and negatives stacked"""
        series = self.secondary_series if secondary else self.series
        transposed = list(zip(*[serie.values for serie in series]))
        positive_vals = [sum([
            val for val in vals
            if val is not None and val >= self.zero])
            for vals in transposed]
        negative_vals = [sum([
            val
            for val in vals
            if val is not None and val < self.zero])
            for vals in transposed]
        return positive_vals, negative_vals

    def _compute_box(self, positive_vals, negative_vals):
        """Compute Y min and max"""
        if self.range and self.range[0] is not None:
            self._box.ymin = self.range[0]
        else:
            self._box.ymin = negative_vals and min(
                min(negative_vals), self.zero) or self.zero
        if self.range and self.range[1] is not None:
            self._box.ymax = self.range[1]
        else:
            self._box.ymax = positive_vals and max(
                max(positive_vals), self.zero) or self.zero

    def _compute(self):
        """Compute y min and max and y scale and set labels"""
        positive_vals, negative_vals = self._get_separated_values()

        if self.logarithmic:
            positive_vals = list(filter(
                lambda x: x > self.zero, positive_vals))
            negative_vals = list(filter(
                lambda x: x > self.zero, negative_vals))

        self._compute_box(positive_vals, negative_vals)
        positive_vals = positive_vals or [self.zero]
        negative_vals = negative_vals or [self.zero]

        self._x_pos = [
            x / self._len for x in range(self._len + 1)
        ] if self._len > 1 else [0, 1]  # Center if only one value

        self._points(self._x_pos)

        self.negative_cumulation = [0] * self._len
        self.positive_cumulation = [0] * self._len

        if self.secondary_series:
            positive_vals, negative_vals = self._get_separated_values(True)
            positive_vals = positive_vals or [self.zero]
            negative_vals = negative_vals or [self.zero]
            self.secondary_negative_cumulation = [0] * self._len
            self.secondary_positive_cumulation = [0] * self._len
            self._pre_compute_secondary(positive_vals, negative_vals)

        self._x_pos = [(i + .5) / self._len for i in range(self._len)]

    def _pre_compute_secondary(self, positive_vals, negative_vals):
        """Compute secondary y min and max"""
        self._secondary_min = (negative_vals and min(
            min(negative_vals), self.zero)) or self.zero
        self._secondary_max = (positive_vals and max(
            max(positive_vals), self.zero)) or self.zero

    def _bar(self, serie, parent, x, y, i, zero, secondary=False):
        """Internal stacking bar drawing function"""
        if secondary:
            cumulation = (self.secondary_negative_cumulation
                          if y < self.zero else
                          self.secondary_positive_cumulation)
        else:
            cumulation = (self.negative_cumulation
                          if y < self.zero else
                          self.positive_cumulation)
        zero = cumulation[i]
        cumulation[i] = zero + y
        if zero == 0:
            zero = self.zero
            y -= self.zero
        y += zero

        width = (self.view.x(1) - self.view.x(0)) / self._len
        x, y = self.view((x, y))
        y = y or 0
        series_margin = width * self._series_margin
        x += series_margin
        width -= 2 * series_margin
        if self.secondary_series:
            width /= 2
            x += int(secondary) * width
            serie_margin = width * self._serie_margin
            x += serie_margin
            width -= 2 * serie_margin
        height = self.view.y(zero) - y
        r = serie.rounded_bars * 1 if serie.rounded_bars else 0
        self.svg.transposable_node(
            parent, 'rect',
            x=x, y=y, rx=r, ry=r, width=width, height=height,
            class_='rect reactive tooltip-trigger')
        return x, y, width, height

    def _plot(self):
        """Draw bars for series and secondary series"""
        for serie in self.series[::-1 if self.stack_from_top else 1]:
            self.bar(serie)
        for serie in self.secondary_series[::-1 if self.stack_from_top else 1]:
            self.bar(serie, True)