"""Module managing errors.""" from __future__ import annotations import re import subprocess import sys import scooby from pyvista._deprecate_positional_args import _deprecate_positional_args _cmd = """\ import pyvista; \ plotter = pyvista.Plotter(notebook=False, off_screen=True); \ plotter.add_mesh(pyvista.Sphere()); \ plotter.show(auto_close=False); \ gpu_info = plotter.render_window.ReportCapabilities(); \ print(gpu_info); \ plotter.close()\ """ def get_gpu_info(): # numpydoc ignore=RT01 """Get all information about the GPU.""" # an OpenGL context MUST be opened before trying to do this. proc = subprocess.run([sys.executable, '-c', _cmd], check=False, capture_output=True) return '' if proc.returncode else proc.stdout.decode() class GPUInfo: """A class to hold GPU details.""" def __init__(self): """Instantiate a container for the GPU information.""" self._gpu_info = get_gpu_info() @property def renderer(self): # numpydoc ignore=RT01 """GPU renderer name.""" regex = re.compile('OpenGL renderer string:(.+)\n') try: renderer = regex.findall(self._gpu_info)[0] except IndexError: msg = 'Unable to parse GPU information for the renderer.' raise RuntimeError(msg) from None return renderer.strip() @property def version(self): # numpydoc ignore=RT01 """GPU renderer version.""" regex = re.compile('OpenGL version string:(.+)\n') try: version = regex.findall(self._gpu_info)[0] except IndexError: msg = 'Unable to parse GPU information for the version.' raise RuntimeError(msg) from None return version.strip() @property def vendor(self): # numpydoc ignore=RT01 """GPU renderer vendor.""" regex = re.compile('OpenGL vendor string:(.+)\n') try: vendor = regex.findall(self._gpu_info)[0] except IndexError: msg = 'Unable to parse GPU information for the vendor.' raise RuntimeError(msg) from None return vendor.strip() def get_info(self): """All GPU information as tuple pairs. Returns ------- tuple Tuples of ``(key, info)``. """ return [ ('GPU Vendor', self.vendor), ('GPU Renderer', self.renderer), ('GPU Version', self.version), ] def _repr_html_(self): """HTML table representation.""" fmt = '' row = '\n' for meta in self.get_info(): fmt += row.format(*meta) fmt += '
{}{}
' return fmt def __repr__(self): """Representation method.""" content = '\n' for k, v in self.get_info(): content += f'{k:>18} : {v}\n' content += '\n' return content class Report(scooby.Report): """Generate a PyVista software environment report. Parameters ---------- additional : sequence[types.ModuleType], sequence[str] List of packages or package names to add to output information. ncol : int, default: 3 Number of package-columns in html table; only has effect if ``mode='HTML'`` or ``mode='html'``. text_width : int, default: 80 The text width for non-HTML display modes. sort : bool, default: False Alphabetically sort the packages. gpu : bool, default: True Gather information about the GPU. Defaults to ``True`` but if experiencing rendering issues, pass ``False`` to safely generate a report. Examples -------- >>> import pyvista as pv >>> pv.Report() # doctest:+SKIP Date: Fri Oct 28 15:54:11 2022 MDT OS : Linux CPU(s) : 6 Machine : x86_64 Architecture : 64bit RAM : 62.6 GiB Environment : IPython File system : ext4 GPU Vendor : NVIDIA Corporation GPU Renderer : Quadro P2000/PCIe/SSE2 GPU Version : 4.5.0 NVIDIA 470.141.03 Python 3.8.10 (default, Jun 22 2022, 20:18:18) [GCC 9.4.0] pyvista : 0.37.dev0 vtk : 9.1.0 numpy : 1.23.3 imageio : 2.22.0 scooby : 0.7.1.dev1+gf097dad pooch : v1.6.0 matplotlib : 3.6.0 IPython : 7.31.0 colorcet : 3.0.1 cmocean : 2.0 scipy : 1.9.1 tqdm : 4.64.1 meshio : 5.3.4 jupyterlab : 3.4.7 """ @_deprecate_positional_args def __init__( # noqa: PLR0917 self, additional=None, ncol=3, text_width=80, sort=False, # noqa: FBT002 gpu=True, # noqa: FBT002 ): """Generate a :class:`scooby.Report` instance.""" from vtkmodules.vtkRenderingCore import vtkRenderWindow # noqa: PLC0415 from pyvista.plotting.tools import check_math_text_support # noqa: PLC0415 # Mandatory packages core = ['pyvista', 'vtk', 'numpy', 'matplotlib', 'scooby', 'pooch', 'pillow'] # Optional packages. optional = [ 'imageio', 'pyvistaqt', 'PyQt5', 'IPython', 'colorcet', 'cmocean', 'ipywidgets', 'scipy', 'tqdm', 'meshio', 'jupyterlab', 'pytest_pyvista', 'trame', 'trame_client', 'trame_server', 'trame_vtk', 'trame_vuetify', 'jupyter_server_proxy', 'nest_asyncio', ] # Information about the GPU - catch all Exception in case there is a rendering # bug that the user is trying to report. if gpu: try: extra_meta = GPUInfo().get_info() except Exception: # noqa: BLE001 extra_meta = [ ('GPU Details', 'error'), ] else: extra_meta = [ ('GPU Details', 'None'), ] extra_meta.append(('Render Window', vtkRenderWindow().GetClassName())) extra_meta.append(('MathText Support', check_math_text_support())) scooby.Report.__init__( self, additional=additional, core=core, # type: ignore[arg-type] optional=optional, # type: ignore[arg-type] ncol=ncol, text_width=text_width, sort=sort, extra_meta=extra_meta, )