This file is indexed.

/usr/lib/python3/dist-packages/lesscpy/lessc/color.py is in python3-lesscpy 0.13.0+ds-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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
# -*- coding: utf8 -*-
"""
.. module:: lesscpy.lessc.color
    :synopsis: Lesscpy Color functions

    Copyright (c)
    See LICENSE for details.
.. moduleauthor:: Johann T. Mariusson <jtm@robot.is>
"""

import operator

import colorsys
import re
import six
from . import utility
from lesscpy.lib import colors


class Color():

    def process(self, expression):
        """ Process color expression
        args:
            expression (tuple): color expression
        returns:
            str
        """
        a, o, b = expression
        c1 = self._hextorgb(a)
        c2 = self._hextorgb(b)
        r = ['#']
        for i in range(3):
            v = self.operate(c1[i], c2[i], o)
            if v > 0xff:
                v = 0xff
            if v < 0:
                v = 0
            r.append("%02x" % int(v))
        return ''.join(r)

    def operate(self, left, right, operation):
        """ Do operation on colors
        args:
            left (str): left side
            right (str): right side
            operation (str): Operation
        returns:
            str
        """
        operation = {
            '+': operator.add,
            '-': operator.sub,
            '*': operator.mul,
            '/': operator.truediv
        }.get(operation)
        return operation(left, right)

    def rgb(self, *args):
        """ Translate rgb(...) to color string
        raises:
            ValueError
        returns:
            str
        """
        if len(args) == 4:
            args = args[:3]
        if len(args) == 3:
            try:
                return self._rgbatohex(list(map(int, args)))
            except ValueError:
                if all((a for a in args
                        if a[-1] == '%'
                        and 100 >= int(a[:-1]) >= 0)):
                    return self._rgbatohex([int(a[:-1]) * 255 / 100.0
                                            for a in args])
        raise ValueError('Illegal color values')

    def rgba(self, *args):
        """ Translate rgba(...) to color string
        raises:
            ValueError
        returns:
            str
        """
        if len(args) == 4:
            try:
                falpha = float(list(args)[3])
                if falpha > 1:
                    args = args[:3]
                if falpha == 0:
                    values = self._rgbatohex_raw(list(map(int, args)))
                    return "rgba(%s)" % ','.join([str(a) for a in values])
                return self._rgbatohex(list(map(int, args)))
            except ValueError:
                if all((a for a in args
                        if a[-1] == '%'
                        and 100 >= int(a[:-1]) >= 0)):
                    alpha = list(args)[3]
                    if alpha[-1] == '%' and float(alpha[:-1]) == 0:
                        values = self._rgbatohex_raw([int(a[:-1]) * 255 / 100.0
                                                     for a in args])
                        return "rgba(%s)" % ','.join([str(a) for a in values])
                    return self._rgbatohex([int(a[:-1]) * 255 / 100.0
                                            for a in args])
        raise ValueError('Illegal color values')

    def argb(self, *args):
        """ Translate argb(...) to color string

        Creates a hex representation of a color in #AARRGGBB format (NOT
        #RRGGBBAA!). This format is used in Internet Explorer, and .NET
        and Android development.

        raises:
            ValueError
        returns:
            str
        """
        if len(args) == 1 and type(args[0]) is str:
            match = re.match(r'rgba\((.*)\)', args[0])
            if match:
                # NOTE(saschpe): Evil hack to cope with rgba(.., .., .., 0.5) passed through untransformed
                rgb = re.sub(r'\s+', '', match.group(1)).split(',')
            else:
                rgb = list(self._hextorgb(args[0]))
        else:
            rgb = list(args)
        if len(rgb) == 3:
            return self._rgbatohex([255] + list(map(int, rgb)))
        elif len(rgb) == 4:
            rgb = [rgb.pop()] + rgb  # Move Alpha to front
            try:
                fval = float(list(rgb)[0])
                if fval > 1:
                    rgb = [255] + rgb[1:]  # Clip invalid integer/float values
                elif 1 >= fval >= 0:
                    rgb = [fval * 256] + rgb[1:]  # Convert 0-1 to 0-255 range for _rgbatohex
                else:
                    rgb = [0] + rgb[1:]  # Clip lower bound
                return self._rgbatohex(list(map(int, rgb)))
            except ValueError:
                if all((a for a in rgb
                        if a[-1] == '%'
                        and 100 >= int(a[:-1]) >= 0)):
                    return self._rgbatohex([int(a[:-1]) * 255 / 100.0
                                            for a in rgb])
        raise ValueError('Illegal color values')

    def hsl(self, *args):
        """ Translate hsl(...) to color string
        raises:
            ValueError
        returns:
            str
        """
        if len(args) == 4:
            return self.hsla(*args)
        elif len(args) == 3:
            h, s, l = args
            rgb = colorsys.hls_to_rgb(int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s))
            color = (utility.convergent_round(c * 255) for c in rgb)
            return self._rgbatohex(color)
        raise ValueError('Illegal color values')

    def hsla(self, *args):
        """ Translate hsla(...) to color string
        raises:
            ValueError
        returns:
            str
        """
        if len(args) == 4:
            h, s, l, a = args
            rgb = colorsys.hls_to_rgb(int(h) / 360.0, utility.pc_or_float(l), utility.pc_or_float(s))
            color = [float(utility.convergent_round(c * 255)) for c in rgb]
            color.append(utility.pc_or_float(a))
            return "rgba(%s,%s,%s,%s)" % tuple(color)
        raise ValueError('Illegal color values')

    def hue(self, color, *args):
        """ Return the hue value of a color
        args:
            color (str): color
        raises:
            ValueError
        returns:
            float
        """
        if color:
            h, l, s = self._hextohls(color)
            return utility.convergent_round(h * 360.0, 3)
        raise ValueError('Illegal color values')

    def saturation(self, color, *args):
        """ Return the saturation value of a color
        args:
            color (str): color
        raises:
            ValueError
        returns:
            float
        """
        if color:
            h, l, s = self._hextohls(color)
            return s * 100.0
        raise ValueError('Illegal color values')

    def lightness(self, color, *args):
        """ Return the lightness value of a color
        args:
            color (str): color
        raises:
            ValueError
        returns:
            float
        """
        if color:
            h, l, s = self._hextohls(color)
            return l * 100.0
        raise ValueError('Illegal color values')

    def opacity(self, *args):
        """
        """
        pass

    def lighten(self, color, diff, *args):
        """ Lighten a color
        args:
            color (str): color
            diff (str): percentage
        returns:
            str
        """
        if color and diff:
            return self._ophsl(color, diff, 1, operator.add)
        raise ValueError('Illegal color values')

    def darken(self, color, diff, *args):
        """ Darken a color
        args:
            color (str): color
            diff (str): percentage
        returns:
            str
        """
        if color and diff:
            return self._ophsl(color, diff, 1, operator.sub)
        raise ValueError('Illegal color values')

    def saturate(self, color, diff, *args):
        """ Saturate a color
        args:
            color (str): color
            diff (str): percentage
        returns:
            str
        """
        if color and diff:
            return self._ophsl(color, diff, 2, operator.add)
        raise ValueError('Illegal color values')

    def desaturate(self, color, diff, *args):
        """ Desaturate a color
        args:
            color (str): color
            diff (str): percentage
        returns:
            str
        """
        if color and diff:
            return self._ophsl(color, diff, 2, operator.sub)
        raise ValueError('Illegal color values')

    def _clamp(self, value):
        # Clamp value
        return min(1, max(0, value))

    def greyscale(self, color, *args):
        """ Simply 100% desaturate.
        args:
            color (str): color
        returns:
            str
        """
        if color:
            return self.desaturate(color, 100.0)
        raise ValueError('Illegal color values')

    def grayscale(self, color, *args):
        """Wrapper for greyscale, other spelling
        """
        return self.greyscale(color, *args)

    def spin(self, color, degree, *args):
        """ Spin color by degree. (Increase / decrease hue)
        args:
            color (str): color
            degree (str): percentage
        raises:
            ValueError
        returns:
            str
        """
        if color and degree:
            if isinstance(degree, six.string_types):
                degree = float(degree.strip('%'))
            h, l, s = self._hextohls(color)
            h = ((h * 360.0) + degree) % 360.0
            h = 360.0 + h if h < 0 else h
            rgb = colorsys.hls_to_rgb(h / 360.0, l, s)
            color = (utility.convergent_round(c * 255) for c in rgb)
            return self._rgbatohex(color)
        raise ValueError('Illegal color values')

    def mix(self, color1, color2, weight=50, *args):
        """This algorithm factors in both the user-provided weight
        and the difference between the alpha values of the two colors
        to decide how to perform the weighted average of the two RGB values.

        It works by first normalizing both parameters to be within [-1, 1],
        where 1 indicates "only use color1", -1 indicates "only use color 0",
        and all values in between indicated a proportionately weighted average.

        Once we have the normalized variables w and a,
        we apply the formula (w + a)/(1 + w*a)
        to get the combined weight (in [-1, 1]) of color1.
        This formula has two especially nice properties:

         * When either w or a are -1 or 1, the combined weight is also that number
           (cases where w * a == -1 are undefined, and handled as a special case).

         * When a is 0, the combined weight is w, and vice versa

        Finally, the weight of color1 is renormalized to be within [0, 1]
        and the weight of color2 is given by 1 minus the weight of color1.

        Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
        http://sass-lang.com
        args:
            color1 (str): first color
            color2 (str): second color
            weight (int/str): weight
        raises:
            ValueError
        returns:
            str
        """
        if color1 and color2:
            if isinstance(weight, six.string_types):
                weight = float(weight.strip('%'))
            weight = ((weight / 100.0) * 2) - 1
            rgb1 = self._hextorgb(color1)
            rgb2 = self._hextorgb(color2)
            alpha = 0
            w1 = (((weight if weight * alpha == -1
                    else weight + alpha) / (1 + weight * alpha)) + 1)
            w1 = w1 / 2.0
            w2 = 1 - w1
            rgb = [
                rgb1[0] * w1 + rgb2[0] * w2,
                rgb1[1] * w1 + rgb2[1] * w2,
                rgb1[2] * w1 + rgb2[2] * w2,
            ]
            return self._rgbatohex(rgb)
        raise ValueError('Illegal color values')

    def fmt(self, color):
        """ Format CSS Hex color code.
        uppercase becomes lowercase, 3 digit codes expand to 6 digit.
        args:
            color (str): color
        raises:
            ValueError
        returns:
            str
        """
        if utility.is_color(color):
            color = color.lower().strip('#')
            if len(color) in [3, 4]:
                color = ''.join([c * 2 for c in color])
            return '#%s' % color
        raise ValueError('Cannot format non-color')

    def _rgbatohex_raw(self, rgba):
        values = ["%x" % int(v) for v in
                  [0xff if h > 0xff else 0 if h < 0 else h for h in rgba]]
        return values

    def _rgbatohex(self, rgba):
        return '#%s' % ''.join(["%02x" % int(v) for v in
                                [0xff
                                 if h > 0xff else
                                 0 if h < 0 else h
                                 for h in rgba]
                                ])

    def _hextorgb(self, hex):
        if hex.lower() in colors.lessColors:
            hex = colors.lessColors[hex.lower()]
        hex = hex.strip()
        if hex[0] == '#':
            hex = hex.strip('#').strip(';')
            if len(hex) == 3:
                hex = [c * 2 for c in hex]
            else:
                hex = [hex[i:i + 2] for i in range(0, len(hex), 2)]
            return tuple(int(c, 16) for c in hex)
        try:
            return [int(hex, 16)] * 3
        except:
            return [float(hex)] * 3

    def _hextohls(self, hex):
        rgb = self._hextorgb(hex)
        return colorsys.rgb_to_hls(*[c / 255.0 for c in rgb])

    def _ophsl(self, color, diff, idx, operation):
        if isinstance(diff, six.string_types):
            diff = float(diff.strip('%'))
        hls = list(self._hextohls(color))
        hls[idx] = self._clamp(operation(hls[idx], diff / 100.0))
        rgb = colorsys.hls_to_rgb(*hls)
        color = (utility.away_from_zero_round(c * 255) for c in rgb)
        return self._rgbatohex(color)