Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/netaddr/strategy/__init__.py: 20%

113 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-07 06:45 +0000

1#----------------------------------------------------------------------------- 

2# Copyright (c) 2008 by David P. D. Moss. All rights reserved. 

3# 

4# Released under the BSD license. See the LICENSE file for details. 

5#----------------------------------------------------------------------------- 

6""" 

7Shared logic for various address types. 

8""" 

9import re as _re 

10 

11from netaddr.compat import _range, _is_str 

12 

13 

14def bytes_to_bits(): 

15 """ 

16 :return: A 256 element list containing 8-bit binary digit strings. The 

17 list index value is equivalent to its bit string value. 

18 """ 

19 lookup = [] 

20 bits_per_byte = _range(7, -1, -1) 

21 for num in range(256): 

22 bits = 8 * [None] 

23 for i in bits_per_byte: 

24 bits[i] = '01'[num & 1] 

25 num >>= 1 

26 lookup.append(''.join(bits)) 

27 return lookup 

28 

29#: A lookup table of 8-bit integer values to their binary digit bit strings. 

30BYTES_TO_BITS = bytes_to_bits() 

31 

32 

33def valid_words(words, word_size, num_words): 

34 """ 

35 :param words: A sequence of unsigned integer word values. 

36 

37 :param word_size: Width (in bits) of each unsigned integer word value. 

38 

39 :param num_words: Number of unsigned integer words expected. 

40 

41 :return: ``True`` if word sequence is valid for this address type, 

42 ``False`` otherwise. 

43 """ 

44 if not hasattr(words, '__iter__'): 

45 return False 

46 

47 if len(words) != num_words: 

48 return False 

49 

50 max_word = 2 ** word_size - 1 

51 

52 for i in words: 

53 if not 0 <= i <= max_word: 

54 return False 

55 

56 return True 

57 

58 

59def int_to_words(int_val, word_size, num_words): 

60 """ 

61 :param int_val: Unsigned integer to be divided into words of equal size. 

62 

63 :param word_size: Width (in bits) of each unsigned integer word value. 

64 

65 :param num_words: Number of unsigned integer words expected. 

66 

67 :return: A tuple contain unsigned integer word values split according 

68 to provided arguments. 

69 """ 

70 max_int = 2 ** (num_words * word_size) - 1 

71 

72 if not 0 <= int_val <= max_int: 

73 raise IndexError('integer out of bounds: %r!' % hex(int_val)) 

74 

75 max_word = 2 ** word_size - 1 

76 

77 words = [] 

78 for _ in range(num_words): 

79 word = int_val & max_word 

80 words.append(int(word)) 

81 int_val >>= word_size 

82 

83 return tuple(reversed(words)) 

84 

85 

86def words_to_int(words, word_size, num_words): 

87 """ 

88 :param words: A sequence of unsigned integer word values. 

89 

90 :param word_size: Width (in bits) of each unsigned integer word value. 

91 

92 :param num_words: Number of unsigned integer words expected. 

93 

94 :return: An unsigned integer that is equivalent to value represented 

95 by word sequence. 

96 """ 

97 if not valid_words(words, word_size, num_words): 

98 raise ValueError('invalid integer word sequence: %r!' % (words,)) 

99 

100 int_val = 0 

101 for i, num in enumerate(reversed(words)): 

102 word = num 

103 word = word << word_size * i 

104 int_val = int_val | word 

105 

106 return int_val 

107 

108 

109def valid_bits(bits, width, word_sep=''): 

110 """ 

111 :param bits: A network address in a delimited binary string format. 

112 

113 :param width: Maximum width (in bits) of a network address (excluding 

114 delimiters). 

115 

116 :param word_sep: (optional) character or string used to delimit word 

117 groups (default: '', no separator). 

118 

119 :return: ``True`` if network address is valid, ``False`` otherwise. 

120 """ 

121 if not _is_str(bits): 

122 return False 

123 

124 if word_sep != '': 

125 bits = bits.replace(word_sep, '') 

126 

127 if len(bits) != width: 

128 return False 

129 

130 max_int = 2 ** width - 1 

131 

132 try: 

133 if 0 <= int(bits, 2) <= max_int: 

134 return True 

135 except ValueError: 

136 pass 

137 

138 return False 

139 

140 

141def bits_to_int(bits, width, word_sep=''): 

142 """ 

143 :param bits: A network address in a delimited binary string format. 

144 

145 :param width: Maximum width (in bits) of a network address (excluding 

146 delimiters). 

147 

148 :param word_sep: (optional) character or string used to delimit word 

149 groups (default: '', no separator). 

150 

151 :return: An unsigned integer that is equivalent to value represented 

152 by network address in readable binary form. 

153 """ 

154 if not valid_bits(bits, width, word_sep): 

155 raise ValueError('invalid readable binary string: %r!' % (bits,)) 

156 

157 if word_sep != '': 

158 bits = bits.replace(word_sep, '') 

159 

160 return int(bits, 2) 

161 

162 

163def int_to_bits(int_val, word_size, num_words, word_sep=''): 

164 """ 

165 :param int_val: An unsigned integer. 

166 

167 :param word_size: Width (in bits) of each unsigned integer word value. 

168 

169 :param num_words: Number of unsigned integer words expected. 

170 

171 :param word_sep: (optional) character or string used to delimit word 

172 groups (default: '', no separator). 

173 

174 :return: A network address in a delimited binary string format that is 

175 equivalent in value to unsigned integer. 

176 """ 

177 bit_words = [] 

178 

179 for word in int_to_words(int_val, word_size, num_words): 

180 bits = [] 

181 while word: 

182 bits.append(BYTES_TO_BITS[word & 255]) 

183 word >>= 8 

184 bits.reverse() 

185 bit_str = ''.join(bits) or '0' * word_size 

186 bits = ('0' * word_size + bit_str)[-word_size:] 

187 bit_words.append(bits) 

188 

189 if word_sep != '': 

190 # Check custom separator. 

191 if not _is_str(word_sep): 

192 raise ValueError('word separator is not a string: %r!' % (word_sep,)) 

193 

194 return word_sep.join(bit_words) 

195 

196 

197def valid_bin(bin_val, width): 

198 """ 

199 :param bin_val: A network address in Python's binary representation format 

200 ('0bxxx'). 

201 

202 :param width: Maximum width (in bits) of a network address (excluding 

203 delimiters). 

204 

205 :return: ``True`` if network address is valid, ``False`` otherwise. 

206 """ 

207 if not _is_str(bin_val): 

208 return False 

209 

210 if not bin_val.startswith('0b'): 

211 return False 

212 

213 bin_val = bin_val.replace('0b', '') 

214 

215 if len(bin_val) > width: 

216 return False 

217 

218 max_int = 2 ** width - 1 

219 

220 try: 

221 if 0 <= int(bin_val, 2) <= max_int: 

222 return True 

223 except ValueError: 

224 pass 

225 

226 return False 

227 

228 

229def int_to_bin(int_val, width): 

230 """ 

231 :param int_val: An unsigned integer. 

232 

233 :param width: Maximum allowed width (in bits) of a unsigned integer. 

234 

235 :return: Equivalent string value in Python's binary representation format 

236 ('0bxxx'). 

237 """ 

238 bin_tokens = [] 

239 

240 try: 

241 # Python 2.6.x and upwards. 

242 bin_val = bin(int_val) 

243 except NameError: 

244 # Python 2.4.x and 2.5.x 

245 i = int_val 

246 while i > 0: 

247 word = i & 0xff 

248 bin_tokens.append(BYTES_TO_BITS[word]) 

249 i >>= 8 

250 

251 bin_tokens.reverse() 

252 bin_val = '0b' + _re.sub(r'^[0]+([01]+)$', r'\1', ''.join(bin_tokens)) 

253 

254 if len(bin_val[2:]) > width: 

255 raise IndexError('binary string out of bounds: %s!' % (bin_val,)) 

256 

257 return bin_val 

258 

259 

260def bin_to_int(bin_val, width): 

261 """ 

262 :param bin_val: A string containing an unsigned integer in Python's binary 

263 representation format ('0bxxx'). 

264 

265 :param width: Maximum allowed width (in bits) of a unsigned integer. 

266 

267 :return: An unsigned integer that is equivalent to value represented 

268 by Python binary string format. 

269 """ 

270 if not valid_bin(bin_val, width): 

271 raise ValueError('not a valid Python binary string: %r!' % (bin_val,)) 

272 

273 return int(bin_val.replace('0b', ''), 2)