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
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
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/.
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.
38"""Various Python version compatibility classes and functions."""
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
50IS_PYTHON2 = (sys.version_info[0] == 2)
53# Import moved modules
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
65# String types for Python 2 and 3.
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
78numeric_types = (float, ) + integer_types
80# This function should only be called in Python 2, and will fail in Python 3
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.')
95# We need to test if an object is an instance of a string type in places
97def isstring(obj):
98 return isinstance(obj, string_types)
100# We need to differentiate between StringIO and BytesIO in places
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
112# We want to test bytestring input to some stuff.
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
124# Define a common exec function
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_""")
139else:
140 exec_ = getattr(builtins, "exec")
143# Class decorator for adding a metaclass
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
163# We do some scary stuff with CodeType() in template/eval.py
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, (), ())
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)
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, (), ())
226# In Python 3.8, Str and Ellipsis was replaced by Constant
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
241class _DummyASTItem(object):
242 pass
243try:
244 _ast_Constant = ast.Constant
245except AttributeError:
246 # Python 2
247 _ast_Constant = _DummyASTItem