Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/openpyxl/worksheet/print_settings.py: 49%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

105 statements  

1# Copyright (c) 2010-2024 openpyxl 

2 

3import re 

4from openpyxl.descriptors import ( 

5 Strict, 

6 Integer, 

7 String, 

8 Typed, 

9) 

10from openpyxl.utils import quote_sheetname, absolute_coordinate 

11from openpyxl.utils.cell import SHEET_TITLE, SHEETRANGE_RE, RANGE_EXPR 

12 

13from .cell_range import MultiCellRange 

14 

15COL_RANGE = r"""(?P<cols>[$]?(?P<min_col>[a-zA-Z]{1,3}):[$]?(?P<max_col>[a-zA-Z]{1,3}))""" 

16COL_RANGE_RE = re.compile(COL_RANGE) 

17ROW_RANGE = r"""(?P<rows>[$]?(?P<min_row>\d+):[$]?(?P<max_row>\d+))""" 

18ROW_RANGE_RE = re.compile(ROW_RANGE) 

19TITLES_REGEX = re.compile("""{0}{1}?,?{2}?,?""".format(SHEET_TITLE, ROW_RANGE, COL_RANGE), 

20 re.VERBOSE) 

21PRINT_AREA_RE = re.compile(f"({SHEET_TITLE})?(?P<cells>{RANGE_EXPR})", re.VERBOSE) 

22 

23class ColRange(Strict): 

24 """ 

25 Represent a range of at least one column 

26 """ 

27 

28 min_col = String() 

29 max_col = String() 

30 

31 

32 def __init__(self, range_string=None, min_col=None, max_col=None): 

33 if range_string is not None: 

34 match = COL_RANGE_RE.match(range_string) 

35 if not match: 

36 raise ValueError(f"{range_string} is not a valid column range") 

37 min_col, max_col = match.groups()[1:] 

38 self.min_col = min_col 

39 self.max_col = max_col 

40 

41 

42 def __eq__(self, other): 

43 if isinstance(other, self.__class__): 

44 return (self.min_col == other.min_col 

45 and 

46 self.max_col == other.max_col) 

47 elif isinstance(other, str): 

48 return (str(self) == other 

49 or 

50 f"{self.min_col}:{self.max_col}") 

51 return False 

52 

53 

54 def __repr__(self): 

55 return f"Range of columns from '{self.min_col}' to '{self.max_col}'" 

56 

57 

58 def __str__(self): 

59 return f"${self.min_col}:${self.max_col}" 

60 

61 

62class RowRange(Strict): 

63 """ 

64 Represent a range of at least one row 

65 """ 

66 

67 min_row = Integer() 

68 max_row = Integer() 

69 

70 def __init__(self, range_string=None, min_row=None, max_row=None): 

71 if range_string is not None: 

72 match = ROW_RANGE_RE.match(range_string) 

73 if not match: 

74 raise ValueError(f"{range_string} is not a valid row range") 

75 min_row, max_row = match.groups()[1:] 

76 self.min_row = min_row 

77 self.max_row = max_row 

78 

79 

80 def __eq__(self, other): 

81 if isinstance(other, self.__class__): 

82 return (self.min_row == other.min_row 

83 and 

84 self.max_row == other.max_row) 

85 elif isinstance(other, str): 

86 return (str(self) == other 

87 or 

88 f"{self.min_row}:{self.max_row}") 

89 return False 

90 

91 def __repr__(self): 

92 return f"Range of rows from '{self.min_row}' to '{self.max_row}'" 

93 

94 

95 def __str__(self): 

96 return f"${self.min_row}:${self.max_row}" 

97 

98 

99class PrintTitles(Strict): 

100 """ 

101 Contains at least either a range of rows or columns 

102 """ 

103 

104 cols = Typed(expected_type=ColRange, allow_none=True) 

105 rows = Typed(expected_type=RowRange, allow_none=True) 

106 title = String() 

107 

108 

109 def __init__(self, cols=None, rows=None, title=""): 

110 self.cols = cols 

111 self.rows = rows 

112 self.title = title 

113 

114 

115 @classmethod 

116 def from_string(cls, value): 

117 kw = dict((k, v) for match in TITLES_REGEX.finditer(value) 

118 for k, v in match.groupdict().items() if v) 

119 

120 if not kw: 

121 raise ValueError(f"{value} is not a valid print titles definition") 

122 

123 cols = rows = None 

124 

125 if "cols" in kw: 

126 cols = ColRange(kw["cols"]) 

127 if "rows" in kw: 

128 rows = RowRange(kw["rows"]) 

129 

130 title = kw.get("quoted") or kw.get("notquoted") 

131 

132 return cls(cols=cols, rows=rows, title=title) 

133 

134 

135 def __eq__(self, other): 

136 if isinstance(other, self.__class__): 

137 return (self.cols == other.cols 

138 and 

139 self.rows == other.rows 

140 and 

141 self.title == other.title) 

142 elif isinstance(other, str): 

143 return str(self) == other 

144 return False 

145 

146 def __repr__(self): 

147 return f"Print titles for sheet {self.title} cols {self.rows}, rows {self.cols}" 

148 

149 

150 def __str__(self): 

151 title = quote_sheetname(self.title) 

152 titles = ",".join([f"{title}!{value}" for value in (self.rows, self.cols) if value]) 

153 return titles or "" 

154 

155 

156class PrintArea(MultiCellRange): 

157 

158 

159 @classmethod 

160 def from_string(cls, value): 

161 new = [] 

162 for m in PRINT_AREA_RE.finditer(value): # can be multiple 

163 coord = m.group("cells") 

164 if coord: 

165 new.append(coord) 

166 return cls(new) 

167 

168 

169 def __init__(self, ranges=(), title=""): 

170 self.title = "" 

171 super().__init__(ranges) 

172 

173 

174 def __str__(self): 

175 if self.ranges: 

176 return ",".join([f"{quote_sheetname(self.title)}!{absolute_coordinate(str(range))}" 

177 for range in self.sorted()]) 

178 return "" 

179 

180 

181 def __eq__(self, other): 

182 super().__eq__(other) 

183 if isinstance(other, str): 

184 return str(self) == other