Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/styles/colors.py: 70%
86 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1# Copyright (c) 2010-2022 openpyxl
3import re
4from openpyxl.compat import safe_string
5from openpyxl.descriptors import (
6 String,
7 Bool,
8 MinMax,
9 Integer,
10 Typed,
11)
12from openpyxl.descriptors.sequence import NestedSequence
13from openpyxl.descriptors.serialisable import Serialisable
15# Default Color Index as per 18.8.27 of ECMA Part 4
16COLOR_INDEX = (
17 '00000000', '00FFFFFF', '00FF0000', '0000FF00', '000000FF', #0-4
18 '00FFFF00', '00FF00FF', '0000FFFF', '00000000', '00FFFFFF', #5-9
19 '00FF0000', '0000FF00', '000000FF', '00FFFF00', '00FF00FF', #10-14
20 '0000FFFF', '00800000', '00008000', '00000080', '00808000', #15-19
21 '00800080', '00008080', '00C0C0C0', '00808080', '009999FF', #20-24
22 '00993366', '00FFFFCC', '00CCFFFF', '00660066', '00FF8080', #25-29
23 '000066CC', '00CCCCFF', '00000080', '00FF00FF', '00FFFF00', #30-34
24 '0000FFFF', '00800080', '00800000', '00008080', '000000FF', #35-39
25 '0000CCFF', '00CCFFFF', '00CCFFCC', '00FFFF99', '0099CCFF', #40-44
26 '00FF99CC', '00CC99FF', '00FFCC99', '003366FF', '0033CCCC', #45-49
27 '0099CC00', '00FFCC00', '00FF9900', '00FF6600', '00666699', #50-54
28 '00969696', '00003366', '00339966', '00003300', '00333300', #55-59
29 '00993300', '00993366', '00333399', '00333333', #60-63
30)
31# indices 64 and 65 are reserved for the system foreground and background colours respectively
33# Will remove these definitions in a future release
34BLACK = COLOR_INDEX[0]
35WHITE = COLOR_INDEX[1]
36#RED = COLOR_INDEX[2]
37#DARKRED = COLOR_INDEX[8]
38BLUE = COLOR_INDEX[4]
39#DARKBLUE = COLOR_INDEX[12]
40#GREEN = COLOR_INDEX[3]
41#DARKGREEN = COLOR_INDEX[9]
42#YELLOW = COLOR_INDEX[5]
43#DARKYELLOW = COLOR_INDEX[19]
46aRGB_REGEX = re.compile("^([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6})$")
49class RGB(Typed):
50 """
51 Descriptor for aRGB values
52 If not supplied alpha is 00
53 """
55 expected_type = str
57 def __set__(self, instance, value):
58 if not self.allow_none: 58 ↛ 64line 58 didn't jump to line 64, because the condition on line 58 was never false
59 m = aRGB_REGEX.match(value)
60 if m is None: 60 ↛ 61line 60 didn't jump to line 61, because the condition on line 60 was never true
61 raise ValueError("Colors must be aRGB hex values")
62 if len(value) == 6: 62 ↛ 63line 62 didn't jump to line 63, because the condition on line 62 was never true
63 value = "00" + value
64 super(RGB, self).__set__(instance, value)
67class Color(Serialisable):
68 """Named colors for use in styles."""
70 tagname = "color"
72 rgb = RGB()
73 indexed = Integer()
74 auto = Bool()
75 theme = Integer()
76 tint = MinMax(min=-1, max=1, expected_type=float)
77 type = String()
80 def __init__(self, rgb=BLACK, indexed=None, auto=None, theme=None, tint=0.0, index=None, type='rgb'):
81 if index is not None: 81 ↛ 82line 81 didn't jump to line 82, because the condition on line 81 was never true
82 indexed = index
83 if indexed is not None:
84 self.type = 'indexed'
85 self.indexed = indexed
86 elif theme is not None:
87 self.type = 'theme'
88 self.theme = theme
89 elif auto is not None: 89 ↛ 90line 89 didn't jump to line 90, because the condition on line 89 was never true
90 self.type = 'auto'
91 self.auto = auto
92 else:
93 self.rgb = rgb
94 self.type = 'rgb'
95 self.tint = tint
97 @property
98 def value(self):
99 return getattr(self, self.type)
101 @value.setter
102 def value(self, value):
103 setattr(self, self.type, value)
105 def __iter__(self):
106 attrs = [(self.type, self.value)]
107 if self.tint != 0:
108 attrs.append(('tint', self.tint))
109 for k, v in attrs:
110 yield k, safe_string(v)
112 @property
113 def index(self):
114 # legacy
115 return self.value
118 def __add__(self, other):
119 """
120 Adding colours is undefined behaviour best do nothing
121 """
122 if not isinstance(other, Color):
123 return super(Color, self).__add__(other)
124 return self
127class ColorDescriptor(Typed):
129 expected_type = Color
131 def __set__(self, instance, value):
132 if isinstance(value, str): 132 ↛ 133line 132 didn't jump to line 133, because the condition on line 132 was never true
133 value = Color(rgb=value)
134 super(ColorDescriptor, self).__set__(instance, value)
137class RgbColor(Serialisable):
139 tagname = "rgbColor"
141 rgb = RGB()
143 def __init__(self,
144 rgb=None,
145 ):
146 self.rgb = rgb
149class ColorList(Serialisable):
151 tagname = "colors"
153 indexedColors = NestedSequence(expected_type=RgbColor)
154 mruColors = NestedSequence(expected_type=Color)
156 __elements__ = ('indexedColors', 'mruColors')
158 def __init__(self,
159 indexedColors=(),
160 mruColors=(),
161 ):
162 self.indexedColors = indexedColors
163 self.mruColors = mruColors
166 def __bool__(self):
167 return bool(self.indexedColors) or bool(self.mruColors)
170 @property
171 def index(self):
172 return [val.rgb for val in self.indexedColors]