Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/openpyxl/styles/fills.py: 57%

133 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2023-07-17 14:22 -0600

1from __future__ import division 

2# Copyright (c) 2010-2022 openpyxl 

3 

4from openpyxl.descriptors import ( 

5 Float, 

6 Set, 

7 Alias, 

8 NoneSet, 

9 Sequence, 

10 Integer, 

11 MinMax, 

12) 

13from openpyxl.descriptors.serialisable import Serialisable 

14from openpyxl.compat import safe_string 

15 

16from .colors import ColorDescriptor, Color 

17 

18from openpyxl.xml.functions import Element, localname 

19from openpyxl.xml.constants import SHEET_MAIN_NS 

20 

21 

22FILL_NONE = 'none' 

23FILL_SOLID = 'solid' 

24FILL_PATTERN_DARKDOWN = 'darkDown' 

25FILL_PATTERN_DARKGRAY = 'darkGray' 

26FILL_PATTERN_DARKGRID = 'darkGrid' 

27FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal' 

28FILL_PATTERN_DARKTRELLIS = 'darkTrellis' 

29FILL_PATTERN_DARKUP = 'darkUp' 

30FILL_PATTERN_DARKVERTICAL = 'darkVertical' 

31FILL_PATTERN_GRAY0625 = 'gray0625' 

32FILL_PATTERN_GRAY125 = 'gray125' 

33FILL_PATTERN_LIGHTDOWN = 'lightDown' 

34FILL_PATTERN_LIGHTGRAY = 'lightGray' 

35FILL_PATTERN_LIGHTGRID = 'lightGrid' 

36FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal' 

37FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis' 

38FILL_PATTERN_LIGHTUP = 'lightUp' 

39FILL_PATTERN_LIGHTVERTICAL = 'lightVertical' 

40FILL_PATTERN_MEDIUMGRAY = 'mediumGray' 

41 

42fills = (FILL_SOLID, FILL_PATTERN_DARKDOWN, FILL_PATTERN_DARKGRAY, 

43 FILL_PATTERN_DARKGRID, FILL_PATTERN_DARKHORIZONTAL, FILL_PATTERN_DARKTRELLIS, 

44 FILL_PATTERN_DARKUP, FILL_PATTERN_DARKVERTICAL, FILL_PATTERN_GRAY0625, 

45 FILL_PATTERN_GRAY125, FILL_PATTERN_LIGHTDOWN, FILL_PATTERN_LIGHTGRAY, 

46 FILL_PATTERN_LIGHTGRID, FILL_PATTERN_LIGHTHORIZONTAL, 

47 FILL_PATTERN_LIGHTTRELLIS, FILL_PATTERN_LIGHTUP, FILL_PATTERN_LIGHTVERTICAL, 

48 FILL_PATTERN_MEDIUMGRAY) 

49 

50 

51class Fill(Serialisable): 

52 

53 """Base class""" 

54 

55 tagname = "fill" 

56 

57 @classmethod 

58 def from_tree(cls, el): 

59 children = [c for c in el] 

60 if not children: 60 ↛ 61line 60 didn't jump to line 61, because the condition on line 60 was never true

61 return 

62 child = children[0] 

63 if "patternFill" in child.tag: 63 ↛ 65line 63 didn't jump to line 65, because the condition on line 63 was never false

64 return PatternFill._from_tree(child) 

65 return super(Fill, GradientFill).from_tree(child) 

66 

67 

68class PatternFill(Fill): 

69 """Area fill patterns for use in styles. 

70 Caution: if you do not specify a fill_type, other attributes will have 

71 no effect !""" 

72 

73 tagname = "patternFill" 

74 

75 __elements__ = ('fgColor', 'bgColor') 

76 

77 patternType = NoneSet(values=fills) 

78 fill_type = Alias("patternType") 

79 fgColor = ColorDescriptor() 

80 start_color = Alias("fgColor") 

81 bgColor = ColorDescriptor() 

82 end_color = Alias("bgColor") 

83 

84 def __init__(self, patternType=None, fgColor=Color(), bgColor=Color(), 

85 fill_type=None, start_color=None, end_color=None): 

86 if fill_type is not None: 86 ↛ 87line 86 didn't jump to line 87, because the condition on line 86 was never true

87 patternType = fill_type 

88 self.patternType = patternType 

89 if start_color is not None: 89 ↛ 90line 89 didn't jump to line 90, because the condition on line 89 was never true

90 fgColor = start_color 

91 self.fgColor = fgColor 

92 if end_color is not None: 92 ↛ 93line 92 didn't jump to line 93, because the condition on line 92 was never true

93 bgColor = end_color 

94 self.bgColor = bgColor 

95 

96 @classmethod 

97 def _from_tree(cls, el): 

98 attrib = dict(el.attrib) 

99 for child in el: 

100 desc = localname(child) 

101 attrib[desc] = Color.from_tree(child) 

102 return cls(**attrib) 

103 

104 

105 def to_tree(self, tagname=None, idx=None): 

106 parent = Element("fill") 

107 el = Element(self.tagname) 

108 if self.patternType is not None: 

109 el.set('patternType', self.patternType) 

110 for c in self.__elements__: 

111 value = getattr(self, c) 

112 if value != Color(): 

113 el.append(value.to_tree(c)) 

114 parent.append(el) 

115 return parent 

116 

117 

118DEFAULT_EMPTY_FILL = PatternFill() 

119DEFAULT_GRAY_FILL = PatternFill(patternType='gray125') 

120 

121 

122class Stop(Serialisable): 

123 

124 tagname = "stop" 

125 

126 position = MinMax(min=0, max=1) 

127 color = ColorDescriptor() 

128 

129 def __init__(self, color, position): 

130 self.position = position 

131 self.color = color 

132 

133 

134def _assign_position(values): 

135 """ 

136 Automatically assign positions if a list of colours is provided. 

137 

138 It is not permitted to mix colours and stops 

139 """ 

140 n_values = len(values) 

141 n_stops = sum(isinstance(value, Stop) for value in values) 

142 

143 if n_stops == 0: 

144 interval = 1 

145 if n_values > 2: 

146 interval = 1 / (n_values - 1) 

147 values = [Stop(value, i * interval) 

148 for i, value in enumerate(values)] 

149 

150 elif n_stops < n_values: 

151 raise ValueError('Cannot interpret mix of Stops and Colors in GradientFill') 

152 

153 pos = set() 

154 for stop in values: 

155 if stop.position in pos: 

156 raise ValueError("Duplicate position {0}".format(stop.position)) 

157 pos.add(stop.position) 

158 

159 return values 

160 

161 

162class StopList(Sequence): 

163 

164 expected_type = Stop 

165 

166 def __set__(self, obj, values): 

167 values = _assign_position(values) 

168 super(StopList, self).__set__(obj, values) 

169 

170 

171class GradientFill(Fill): 

172 """Fill areas with gradient 

173 

174 Two types of gradient fill are supported: 

175 

176 - A type='linear' gradient interpolates colours between 

177 a set of specified Stops, across the length of an area. 

178 The gradient is left-to-right by default, but this 

179 orientation can be modified with the degree 

180 attribute. A list of Colors can be provided instead 

181 and they will be positioned with equal distance between them. 

182 

183 - A type='path' gradient applies a linear gradient from each 

184 edge of the area. Attributes top, right, bottom, left specify 

185 the extent of fill from the respective borders. Thus top="0.2" 

186 will fill the top 20% of the cell. 

187 

188 """ 

189 

190 tagname = "gradientFill" 

191 

192 type = Set(values=('linear', 'path')) 

193 fill_type = Alias("type") 

194 degree = Float() 

195 left = Float() 

196 right = Float() 

197 top = Float() 

198 bottom = Float() 

199 stop = StopList() 

200 

201 

202 def __init__(self, type="linear", degree=0, left=0, right=0, top=0, 

203 bottom=0, stop=()): 

204 self.degree = degree 

205 self.left = left 

206 self.right = right 

207 self.top = top 

208 self.bottom = bottom 

209 self.stop = stop 

210 self.type = type 

211 

212 

213 def __iter__(self): 

214 for attr in self.__attrs__: 

215 value = getattr(self, attr) 

216 if value: 

217 yield attr, safe_string(value) 

218 

219 

220 def to_tree(self, tagname=None, namespace=None, idx=None): 

221 parent = Element("fill") 

222 el = super(GradientFill, self).to_tree() 

223 parent.append(el) 

224 return parent