Videre
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
"""Module for displaying information about Numba's gdb set up"""
|
||||
from collections import namedtuple
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from textwrap import dedent
|
||||
from numba import config
|
||||
|
||||
# Container for the output of the gdb info data collection
|
||||
_fields = ('binary_loc, extension_loc, py_ver, np_ver, supported')
|
||||
_gdb_info = namedtuple('_gdb_info', _fields)
|
||||
|
||||
|
||||
class _GDBTestWrapper():
|
||||
"""Wraps the gdb binary and has methods for checking what the gdb binary
|
||||
has support for (Python and NumPy)."""
|
||||
|
||||
def __init__(self,):
|
||||
gdb_binary = config.GDB_BINARY
|
||||
if gdb_binary is None:
|
||||
msg = ("No valid binary could be found for gdb named: "
|
||||
f"{config.GDB_BINARY}")
|
||||
raise ValueError(msg)
|
||||
self._gdb_binary = gdb_binary
|
||||
|
||||
def _run_cmd(self, cmd=()):
|
||||
gdb_call = [self.gdb_binary, '-q',]
|
||||
for x in cmd:
|
||||
gdb_call.append('-ex')
|
||||
gdb_call.append(x)
|
||||
gdb_call.extend(['-ex', 'q'])
|
||||
return subprocess.run(gdb_call, capture_output=True, timeout=10,
|
||||
text=True)
|
||||
|
||||
@property
|
||||
def gdb_binary(self):
|
||||
return self._gdb_binary
|
||||
|
||||
@classmethod
|
||||
def success(cls, status):
|
||||
return status.returncode == 0
|
||||
|
||||
def check_launch(self):
|
||||
"""Checks that gdb will launch ok"""
|
||||
return self._run_cmd()
|
||||
|
||||
def check_python(self):
|
||||
cmd = ("python from __future__ import print_function; "
|
||||
"import sys; print(sys.version_info[:2])")
|
||||
return self._run_cmd((cmd,))
|
||||
|
||||
def check_numpy(self):
|
||||
cmd = ("python from __future__ import print_function; "
|
||||
"import types; import numpy; "
|
||||
"print(isinstance(numpy, types.ModuleType))")
|
||||
return self._run_cmd((cmd,))
|
||||
|
||||
def check_numpy_version(self):
|
||||
cmd = ("python from __future__ import print_function; "
|
||||
"import types; import numpy;"
|
||||
"print(numpy.__version__)")
|
||||
return self._run_cmd((cmd,))
|
||||
|
||||
|
||||
def collect_gdbinfo():
|
||||
"""Prints information to stdout about the gdb setup that Numba has found"""
|
||||
|
||||
# State flags:
|
||||
gdb_state = None
|
||||
gdb_has_python = False
|
||||
gdb_has_numpy = False
|
||||
gdb_python_version = 'No Python support'
|
||||
gdb_python_numpy_version = "No NumPy support"
|
||||
|
||||
# There are so many ways for gdb to not be working as expected. Surround
|
||||
# the "is it working" tests with try/except and if there's an exception
|
||||
# store it for processing later.
|
||||
try:
|
||||
# Check gdb exists
|
||||
gdb_wrapper = _GDBTestWrapper()
|
||||
|
||||
# Check gdb works
|
||||
status = gdb_wrapper.check_launch()
|
||||
if not gdb_wrapper.success(status):
|
||||
msg = (f"gdb at '{gdb_wrapper.gdb_binary}' does not appear to work."
|
||||
f"\nstdout: {status.stdout}\nstderr: {status.stderr}")
|
||||
raise ValueError(msg)
|
||||
gdb_state = gdb_wrapper.gdb_binary
|
||||
except Exception as e:
|
||||
gdb_state = f"Testing gdb binary failed. Reported Error: {e}"
|
||||
else:
|
||||
# Got this far, so gdb works, start checking what it supports
|
||||
status = gdb_wrapper.check_python()
|
||||
if gdb_wrapper.success(status):
|
||||
version_match = re.match(r'\((\d+),\s+(\d+)\)',
|
||||
status.stdout.strip())
|
||||
if version_match is not None:
|
||||
pymajor, pyminor = version_match.groups()
|
||||
gdb_python_version = f"{pymajor}.{pyminor}"
|
||||
gdb_has_python = True
|
||||
|
||||
status = gdb_wrapper.check_numpy()
|
||||
if gdb_wrapper.success(status):
|
||||
if "Traceback" not in status.stderr.strip():
|
||||
if status.stdout.strip() == 'True':
|
||||
gdb_has_numpy = True
|
||||
gdb_python_numpy_version = "Unknown"
|
||||
# NumPy is present find the version
|
||||
status = gdb_wrapper.check_numpy_version()
|
||||
if gdb_wrapper.success(status):
|
||||
if "Traceback" not in status.stderr.strip():
|
||||
gdb_python_numpy_version = \
|
||||
status.stdout.strip()
|
||||
|
||||
# Work out what level of print-extension support is present in this gdb
|
||||
if gdb_has_python:
|
||||
if gdb_has_numpy:
|
||||
print_ext_supported = "Full (Python and NumPy supported)"
|
||||
else:
|
||||
print_ext_supported = "Partial (Python only, no NumPy support)"
|
||||
else:
|
||||
print_ext_supported = "None"
|
||||
|
||||
# Work out print ext location
|
||||
print_ext_file = "gdb_print_extension.py"
|
||||
print_ext_path = os.path.join(os.path.dirname(__file__), print_ext_file)
|
||||
|
||||
# return!
|
||||
return _gdb_info(gdb_state, print_ext_path, gdb_python_version,
|
||||
gdb_python_numpy_version, print_ext_supported)
|
||||
|
||||
|
||||
def display_gdbinfo(sep_pos=45):
|
||||
"""Displays the information collected by collect_gdbinfo.
|
||||
"""
|
||||
gdb_info = collect_gdbinfo()
|
||||
print('-' * 80)
|
||||
fmt = f'%-{sep_pos}s : %-s'
|
||||
# Display the information
|
||||
print(fmt % ("Binary location", gdb_info.binary_loc))
|
||||
print(fmt % ("Print extension location", gdb_info.extension_loc))
|
||||
print(fmt % ("Python version", gdb_info.py_ver))
|
||||
print(fmt % ("NumPy version", gdb_info.np_ver))
|
||||
print(fmt % ("Numba printing extension support", gdb_info.supported))
|
||||
|
||||
print("")
|
||||
print("To load the Numba gdb printing extension, execute the following "
|
||||
"from the gdb prompt:")
|
||||
print(f"\nsource {gdb_info.extension_loc}\n")
|
||||
print('-' * 80)
|
||||
warn = """
|
||||
=============================================================
|
||||
IMPORTANT: Before sharing you should remove any information
|
||||
in the above that you wish to keep private e.g. paths.
|
||||
=============================================================
|
||||
"""
|
||||
print(dedent(warn))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
display_gdbinfo()
|
||||
Reference in New Issue
Block a user