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

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

125 statements  

1# -*- coding: utf-8 -*- 

2# 

3# Copyright (C) 2006-2009 Edgewall Software 

4# All rights reserved. 

5# 

6# This software is licensed as described in the file COPYING, which 

7# you should have received as part of this distribution. The terms 

8# are also available at http://genshi.edgewall.org/wiki/License. 

9# 

10# This software consists of voluntary contributions made by many 

11# individuals. For the exact contribution history, see the revision 

12# history and logs, available at http://genshi.edgewall.org/log/. 

13 

14# The add_metaclass and exec_ functions in this module were copied 

15# from 'six' version 1.17.0 (https://github.com/benjaminp/six/blob/main/six.py). 

16# and are copyrighted under the following license: 

17# 

18# Copyright (c) 2010-2024 Benjamin Peterson 

19# 

20# Permission is hereby granted, free of charge, to any person obtaining a copy 

21# of this software and associated documentation files (the "Software"), to deal 

22# in the Software without restriction, including without limitation the rights 

23# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 

24# copies of the Software, and to permit persons to whom the Software is 

25# furnished to do so, subject to the following conditions: 

26# 

27# The above copyright notice and this permission notice shall be included in all 

28# copies or substantial portions of the Software. 

29# 

30# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

31# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

32# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

33# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

34# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

35# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 

36# SOFTWARE. 

37 

38"""Various Python version compatibility classes and functions.""" 

39 

40try: 

41 # in Python 3.9 the "_ast" module does not provide "Index" anymore but 

42 # "ast" does. 

43 import ast 

44except ImportError: 

45 import _ast as ast 

46import sys 

47import warnings 

48from types import CodeType 

49 

50IS_PYTHON2 = (sys.version_info[0] == 2) 

51 

52 

53# Import moved modules 

54 

55if IS_PYTHON2: 

56 import __builtin__ as builtins 

57 import htmlentitydefs as html_entities 

58 import HTMLParser as html_parser 

59else: 

60 import builtins 

61 import html.entities as html_entities 

62 import html.parser as html_parser 

63 

64 

65# String types for Python 2 and 3. 

66 

67if IS_PYTHON2: 

68 string_types = basestring, 

69 integer_types = (int, long) 

70 text_type = unicode 

71 unichr = unichr 

72else: 

73 string_types = str, 

74 integer_types = int, 

75 text_type = str 

76 unichr = chr 

77 

78numeric_types = (float, ) + integer_types 

79 

80# This function should only be called in Python 2, and will fail in Python 3 

81 

82if IS_PYTHON2: 

83 def stringrepr(string): 

84 ascii = string.encode('ascii', 'backslashreplace') 

85 quoted = "'" + ascii.replace("'", "\\'") + "'" 

86 if len(ascii) > len(string): 

87 return 'u' + quoted 

88 return quoted 

89else: 

90 def stringrepr(string): 

91 raise RuntimeError( 

92 'Python 2 compatibility function. Not usable in Python 3.') 

93 

94 

95# We need to test if an object is an instance of a string type in places 

96 

97def isstring(obj): 

98 return isinstance(obj, string_types) 

99 

100# We need to differentiate between StringIO and BytesIO in places 

101 

102if IS_PYTHON2: 

103 from StringIO import StringIO 

104 try: 

105 from cStringIO import StringIO as BytesIO 

106 except ImportError: 

107 BytesIO = StringIO 

108else: 

109 from io import StringIO, BytesIO 

110 

111 

112# We want to test bytestring input to some stuff. 

113 

114if IS_PYTHON2: 

115 def wrapped_bytes(bstr): 

116 assert bstr.startswith('b') 

117 return bstr[1:] 

118else: 

119 def wrapped_bytes(bstr): 

120 assert bstr.startswith('b') 

121 return bstr 

122 

123 

124# Define a common exec function 

125 

126if IS_PYTHON2: 

127 def exec_(_code_, _globs_=None, _locs_=None): 

128 """Execute code in a namespace.""" 

129 if _globs_ is None: 

130 frame = sys._getframe(1) 

131 _globs_ = frame.f_globals 

132 if _locs_ is None: 

133 _locs_ = frame.f_locals 

134 del frame 

135 elif _locs_ is None: 

136 _locs_ = _globs_ 

137 exec("""exec _code_ in _globs_, _locs_""") 

138 

139else: 

140 exec_ = getattr(builtins, "exec") 

141 

142 

143# Class decorator for adding a metaclass 

144 

145def add_metaclass(metaclass): 

146 """Class decorator for creating a class with a metaclass.""" 

147 def wrapper(cls): 

148 orig_vars = cls.__dict__.copy() 

149 slots = orig_vars.get('__slots__') 

150 if slots is not None: 

151 if isinstance(slots, str): 

152 slots = [slots] 

153 for slots_var in slots: 

154 orig_vars.pop(slots_var) 

155 orig_vars.pop('__dict__', None) 

156 orig_vars.pop('__weakref__', None) 

157 if hasattr(cls, '__qualname__'): 

158 orig_vars['__qualname__'] = cls.__qualname__ 

159 return metaclass(cls.__name__, cls.__bases__, orig_vars) 

160 return wrapper 

161 

162 

163# We do some scary stuff with CodeType() in template/eval.py 

164 

165if IS_PYTHON2: 

166 def get_code_params(code): 

167 return (code.co_nlocals, code.co_stacksize, code.co_flags, 

168 code.co_code, code.co_consts, code.co_names, code.co_varnames, 

169 code.co_filename, code.co_name, code.co_firstlineno, 

170 code.co_lnotab, (), ()) 

171 

172 def build_code_chunk(code, filename, name, lineno): 

173 return CodeType(0, code.co_nlocals, code.co_stacksize, 

174 code.co_flags | 0x0040, code.co_code, code.co_consts, 

175 code.co_names, code.co_varnames, filename, name, 

176 lineno, code.co_lnotab, (), ()) 

177else: 

178 def get_code_params(code): 

179 params = [] 

180 if hasattr(code, "co_posonlyargcount"): 

181 # PEP 570 -- Python Positional-Only Parameters 

182 params.append(code.co_posonlyargcount) 

183 params.extend([code.co_kwonlyargcount, code.co_nlocals, 

184 code.co_stacksize, code.co_flags, code.co_code, 

185 code.co_consts, code.co_names, code.co_varnames, 

186 code.co_filename, code.co_name]) 

187 if hasattr(code, "co_qualname"): 

188 # https://bugs.python.org/issue13672 

189 params.append(code.co_qualname) 

190 params.append(code.co_firstlineno) 

191 if hasattr(code, "co_linetable"): 

192 # PEP 626 -- Precise line numbers for debugging and other tools. 

193 params.append(code.co_linetable) 

194 else: 

195 params.append(code.co_lnotab) 

196 if hasattr(code, "co_endlinetable"): 

197 # PEP 657 -- Include Fine Grained Error Locations in Tracebacks 

198 params.append(code.co_endlinetable) 

199 if hasattr(code, "co_columntable"): 

200 # PEP 657 -- Include Fine Grained Error Locations in Tracebacks 

201 params.append(code.co_columntable) 

202 if hasattr(code, "co_exceptiontable"): 

203 # https://bugs.python.org/issue40222 

204 params.append(code.co_exceptiontable) 

205 params.extend([(), ()]) 

206 return tuple(params) 

207 

208 

209 def build_code_chunk(code, filename, name, lineno): 

210 if hasattr(code, 'replace'): 

211 # Python 3.8+ 

212 return code.replace( 

213 co_filename=filename, 

214 co_name=name, 

215 co_firstlineno=lineno, 

216 ) 

217 # XXX: This isn't equivalent to the above "replace" code (we overwrite 

218 # co_argcount, co_flags, co_freevars, and co_cellvars). Should one of 

219 # them be changed? 

220 return CodeType(0, code.co_kwonlyargcount, code.co_nlocals, 

221 code.co_stacksize, code.co_flags | 0x0040, code.co_code, 

222 code.co_consts, code.co_names, code.co_varnames, 

223 filename, name, lineno, code.co_lnotab, (), ()) 

224 

225 

226# In Python 3.8, Str and Ellipsis was replaced by Constant 

227 

228with warnings.catch_warnings(): 

229 warnings.filterwarnings('error', category=DeprecationWarning) 

230 try: 

231 _ast_Ellipsis = ast.Ellipsis 

232 _ast_Ellipsis_value = lambda obj: Ellipsis 

233 _ast_Str = ast.Str 

234 _ast_Str_value = lambda obj: obj.s 

235 except (AttributeError, DeprecationWarning): 

236 _ast_Ellipsis = ast.Constant 

237 _ast_Ellipsis_value = lambda obj: obj.value 

238 _ast_Str = ast.Constant 

239 _ast_Str_value = lambda obj: obj.value 

240 

241class _DummyASTItem(object): 

242 pass 

243try: 

244 _ast_Constant = ast.Constant 

245except AttributeError: 

246 # Python 2 

247 _ast_Constant = _DummyASTItem