gdb libpython.py: Remove compatibility code (#105739)

Remove compatibility code for Python 2 and early Python 3 versions.

* Remove os_fsencode() reimplementation: use os.fsencode() directly.
  os.fsencode() was added to Python 3.2.
* Remove references to Python 2 and "Python 3": just say "Python".
* Remove outdated u'' string format: use '' instead.
This commit is contained in:
Victor Stinner 2023-06-14 12:30:22 +02:00 committed by GitHub
parent e5d45b7444
commit 0316063031
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -111,26 +111,6 @@ def safe_range(val):
# threshold in case the data was corrupted # threshold in case the data was corrupted
return range(safety_limit(int(val))) return range(safety_limit(int(val)))
try:
os_fsencode = os.fsencode
except AttributeError:
def os_fsencode(filename):
if not isinstance(filename, unicode):
return filename
encoding = sys.getfilesystemencoding()
if encoding == 'mbcs':
# mbcs doesn't support surrogateescape
return filename.encode(encoding)
encoded = []
for char in filename:
# surrogateescape error handler
if 0xDC80 <= ord(char) <= 0xDCFF:
byte = chr(ord(char) - 0xDC00)
else:
byte = char.encode(encoding)
encoded.append(byte)
return ''.join(encoded)
class StringTruncated(RuntimeError): class StringTruncated(RuntimeError):
pass pass
@ -174,16 +154,12 @@ class PyObjectPtr(object):
def field(self, name): def field(self, name):
''' '''
Get the gdb.Value for the given field within the PyObject, coping with Get the gdb.Value for the given field within the PyObject.
some python 2 versus python 3 differences.
Various libpython types are defined using the "PyObject_HEAD" and Various libpython types are defined using the "PyObject_HEAD" and
"PyObject_VAR_HEAD" macros. "PyObject_VAR_HEAD" macros.
In Python 2, this these are defined so that "ob_type" and (for a var In Python, this is defined as an embedded PyVarObject type thus:
object) "ob_size" are fields of the type in question.
In Python 3, this is defined as an embedded PyVarObject type thus:
PyVarObject ob_base; PyVarObject ob_base;
so that the "ob_size" field is located insize the "ob_base" field, and so that the "ob_size" field is located insize the "ob_base" field, and
the "ob_type" is most easily accessed by casting back to a (PyObject*). the "ob_type" is most easily accessed by casting back to a (PyObject*).
@ -204,8 +180,7 @@ class PyObjectPtr(object):
def pyop_field(self, name): def pyop_field(self, name):
''' '''
Get a PyObjectPtr for the given PyObject* field within this PyObject, Get a PyObjectPtr for the given PyObject* field within this PyObject.
coping with some python 2 versus python 3 differences.
''' '''
return PyObjectPtr.from_pyobject_ptr(self.field(name)) return PyObjectPtr.from_pyobject_ptr(self.field(name))
@ -924,7 +899,7 @@ class PyLongObjectPtr(PyObjectPtr):
return result return result
def write_repr(self, out, visited): def write_repr(self, out, visited):
# Write this out as a Python 3 int literal, i.e. without the "L" suffix # Write this out as a Python int literal
proxy = self.proxyval(visited) proxy = self.proxyval(visited)
out.write("%s" % proxy) out.write("%s" % proxy)
@ -1170,7 +1145,7 @@ class PyFramePtr:
filename = self.filename() filename = self.filename()
try: try:
with open(os_fsencode(filename), 'r', encoding="utf-8") as fp: with open(os.fsencode(filename), 'r', encoding="utf-8") as fp:
lines = fp.readlines() lines = fp.readlines()
except IOError: except IOError:
return None return None
@ -1263,7 +1238,7 @@ class PySetObjectPtr(PyObjectPtr):
return set(members) return set(members)
def write_repr(self, out, visited): def write_repr(self, out, visited):
# Emulate Python 3's set_repr # Emulate Python's set_repr
tp_name = self.safe_tp_name() tp_name = self.safe_tp_name()
# Guard against infinite loops: # Guard against infinite loops:
@ -1272,13 +1247,13 @@ class PySetObjectPtr(PyObjectPtr):
return return
visited.add(self.as_address()) visited.add(self.as_address())
# Python 3's set_repr special-cases the empty set: # Python's set_repr special-cases the empty set:
if not self.field('used'): if not self.field('used'):
out.write(tp_name) out.write(tp_name)
out.write('()') out.write('()')
return return
# Python 3 uses {} for set literals: # Python uses {} for set literals:
if tp_name != 'set': if tp_name != 'set':
out.write(tp_name) out.write(tp_name)
out.write('(') out.write('(')
@ -1309,13 +1284,13 @@ class PyBytesObjectPtr(PyObjectPtr):
return str(self) return str(self)
def write_repr(self, out, visited): def write_repr(self, out, visited):
# Write this out as a Python 3 bytes literal, i.e. with a "b" prefix # Write this out as a Python bytes literal, i.e. with a "b" prefix
# Get a PyStringObject* within the Python 2 gdb process: # Get a PyStringObject* within the Python gdb process:
proxy = self.proxyval(visited) proxy = self.proxyval(visited)
# Transliteration of Python 3's Objects/bytesobject.c:PyBytes_Repr # Transliteration of Python's Objects/bytesobject.c:PyBytes_Repr
# to Python 2 code: # to Python code:
quote = "'" quote = "'"
if "'" in proxy and not '"' in proxy: if "'" in proxy and not '"' in proxy:
quote = '"' quote = '"'
@ -1380,7 +1355,7 @@ class PyTypeObjectPtr(PyObjectPtr):
def _unichr_is_printable(char): def _unichr_is_printable(char):
# Logic adapted from Python 3's Tools/unicode/makeunicodedata.py # Logic adapted from Python's Tools/unicode/makeunicodedata.py
if char == u" ": if char == u" ":
return True return True
import unicodedata import unicodedata
@ -1416,17 +1391,17 @@ class PyUnicodeObjectPtr(PyObjectPtr):
# Convert the int code points to unicode characters, and generate a # Convert the int code points to unicode characters, and generate a
# local unicode instance. # local unicode instance.
result = u''.join(map(chr, code_points)) result = ''.join(map(chr, code_points))
return result return result
def write_repr(self, out, visited): def write_repr(self, out, visited):
# Write this out as a Python 3 str literal, i.e. without a "u" prefix # Write this out as a Python str literal
# Get a PyUnicodeObject* within the Python 2 gdb process: # Get a PyUnicodeObject* within the Python gdb process:
proxy = self.proxyval(visited) proxy = self.proxyval(visited)
# Transliteration of Python 3's Object/unicodeobject.c:unicode_repr # Transliteration of Python's Object/unicodeobject.c:unicode_repr
# to Python 2: # to Python:
if "'" in proxy and '"' not in proxy: if "'" in proxy and '"' not in proxy:
quote = '"' quote = '"'
else: else:
@ -1477,7 +1452,7 @@ class PyUnicodeObjectPtr(PyObjectPtr):
# (categories Z* and C* except ASCII space) # (categories Z* and C* except ASCII space)
if not printable: if not printable:
if ch2 is not None: if ch2 is not None:
# Match Python 3's representation of non-printable # Match Python's representation of non-printable
# wide characters. # wide characters.
code = (ord(ch) & 0x03FF) << 10 code = (ord(ch) & 0x03FF) << 10
code |= ord(ch2) & 0x03FF code |= ord(ch2) & 0x03FF
@ -1608,8 +1583,8 @@ The following code should ensure that the prettyprinter is registered
if the code is autoloaded by gdb when visiting libpython.so, provided if the code is autoloaded by gdb when visiting libpython.so, provided
that this python file is installed to the same path as the library (or its that this python file is installed to the same path as the library (or its
.debug file) plus a "-gdb.py" suffix, e.g: .debug file) plus a "-gdb.py" suffix, e.g:
/usr/lib/libpython2.6.so.1.0-gdb.py /usr/lib/libpython3.12.so.1.0-gdb.py
/usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py /usr/lib/debug/usr/lib/libpython3.12.so.1.0.debug-gdb.py
""" """
def register (obj): def register (obj):
if obj is None: if obj is None:
@ -1928,7 +1903,7 @@ class PyList(gdb.Command):
start = 1 start = 1
try: try:
f = open(os_fsencode(filename), 'r', encoding="utf-8") f = open(os.fsencode(filename), 'r', encoding="utf-8")
except IOError as err: except IOError as err:
sys.stdout.write('Unable to open %s: %s\n' sys.stdout.write('Unable to open %s: %s\n'
% (filename, err)) % (filename, err))