Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/scapy/compat.py: 62%

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

65 statements  

1# SPDX-License-Identifier: GPL-2.0-only 

2# This file is part of Scapy 

3# See https://scapy.net/ for more information 

4 

5""" 

6Python 2 and 3 link classes. 

7""" 

8 

9import base64 

10import binascii 

11import struct 

12import sys 

13 

14from typing import ( 

15 Any, 

16 AnyStr, 

17 Callable, 

18 Optional, 

19 TypeVar, 

20 TYPE_CHECKING, 

21 Union, 

22) 

23 

24# Very important: will issue typing errors otherwise 

25__all__ = [ 

26 # typing 

27 'DecoratorCallable', 

28 'Literal', 

29 'Protocol', 

30 'Self', 

31 'UserDict', 

32 # compat 

33 'base64_bytes', 

34 'bytes_base64', 

35 'bytes_encode', 

36 'bytes_hex', 

37 'chb', 

38 'hex_bytes', 

39 'orb', 

40 'plain_str', 

41 'raw', 

42] 

43 

44# Typing compatibility 

45 

46# Note: 

47# supporting typing on multiple python versions is a nightmare. 

48# we provide a FakeType class to be able to use types added on 

49# later Python versions (since we run mypy on 3.12), on older 

50# ones. 

51 

52 

53# Import or create fake types 

54 

55def _FakeType(name, cls=object): 

56 # type: (str, Optional[type]) -> Any 

57 class _FT(object): 

58 def __init__(self, name): 

59 # type: (str) -> None 

60 self.name = name 

61 

62 # make the objects subscriptable indefinitely 

63 def __getitem__(self, item): # type: ignore 

64 return cls 

65 

66 def __call__(self, *args, **kargs): 

67 # type: (*Any, **Any) -> Any 

68 if isinstance(args[0], str): 

69 self.name = args[0] 

70 return self 

71 

72 def __repr__(self): 

73 # type: () -> str 

74 return "<Fake typing.%s>" % self.name 

75 return _FT(name) 

76 

77 

78# Python 3.8 Only 

79if sys.version_info >= (3, 8): 

80 from typing import Literal 

81 from typing import Protocol 

82else: 

83 Literal = _FakeType("Literal") 

84 

85 class Protocol: 

86 pass 

87 

88 

89# Python 3.9 Only 

90if sys.version_info >= (3, 9): 

91 from collections import UserDict 

92else: 

93 from collections import UserDict as _UserDict 

94 UserDict = _FakeType("_UserDict", _UserDict) 

95 

96 

97# Python 3.11 Only 

98if sys.version_info >= (3, 11): 

99 from typing import Self 

100else: 

101 Self = _FakeType("Self") 

102 

103########### 

104# Python3 # 

105########### 

106 

107# https://mypy.readthedocs.io/en/stable/generics.html#declaring-decorators 

108DecoratorCallable = TypeVar("DecoratorCallable", bound=Callable[..., Any]) 

109 

110 

111# This is ugly, but we don't want to move raw() out of compat.py 

112# and it makes it much clearer 

113if TYPE_CHECKING: 

114 from scapy.packet import Packet 

115 

116 

117def raw(x): 

118 # type: (Packet) -> bytes 

119 """ 

120 Builds a packet and returns its bytes representation. 

121 This function is and will always be cross-version compatible 

122 """ 

123 return bytes(x) 

124 

125 

126def bytes_encode(x): 

127 # type: (Any) -> bytes 

128 """Ensure that the given object is bytes. If the parameter is a 

129 packet, raw() should be preferred. 

130 

131 """ 

132 if isinstance(x, str): 

133 return x.encode() 

134 return bytes(x) 

135 

136 

137def plain_str(x): 

138 # type: (Any) -> str 

139 """Convert basic byte objects to str""" 

140 if isinstance(x, bytes): 

141 return x.decode(errors="backslashreplace") 

142 return str(x) 

143 

144 

145def chb(x): 

146 # type: (int) -> bytes 

147 """Same than chr() but encode as bytes.""" 

148 return struct.pack("!B", x) 

149 

150 

151def orb(x): 

152 # type: (Union[int, str, bytes]) -> int 

153 """Return ord(x) when not already an int.""" 

154 if isinstance(x, int): 

155 return x 

156 return ord(x) 

157 

158 

159def bytes_hex(x): 

160 # type: (AnyStr) -> bytes 

161 """Hexify a str or a bytes object""" 

162 return binascii.b2a_hex(bytes_encode(x)) 

163 

164 

165def hex_bytes(x): 

166 # type: (AnyStr) -> bytes 

167 """De-hexify a str or a byte object""" 

168 return binascii.a2b_hex(bytes_encode(x)) 

169 

170 

171def int_bytes(x, size): 

172 # type: (int, int) -> bytes 

173 """Convert an int to an arbitrary sized bytes string""" 

174 return x.to_bytes(size, byteorder='big') 

175 

176 

177def bytes_int(x): 

178 # type: (bytes) -> int 

179 """Convert an arbitrary sized bytes string to an int""" 

180 return int.from_bytes(x, "big") 

181 

182 

183def base64_bytes(x): 

184 # type: (AnyStr) -> bytes 

185 """Turn base64 into bytes""" 

186 return base64.decodebytes(bytes_encode(x)) 

187 

188 

189def bytes_base64(x): 

190 # type: (AnyStr) -> bytes 

191 """Turn bytes into base64""" 

192 return base64.encodebytes(bytes_encode(x)).replace(b'\n', b'')