Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/nbconvert/exporters/qt_exporter.py: 25%

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

61 statements  

1"""A qt exporter.""" 

2 

3import os 

4import sys 

5import tempfile 

6import time 

7 

8from traitlets import default 

9 

10from .html import HTMLExporter 

11 

12 

13class QtExporter(HTMLExporter): 

14 """A qt exporter.""" 

15 

16 paginate = None 

17 format = "" 

18 

19 @default("file_extension") 

20 def _file_extension_default(self): 

21 return ".html" 

22 

23 def _check_launch_reqs(self): 

24 if sys.platform.startswith("win") and self.format == "png": 

25 msg = "Exporting to PNG using Qt is currently not supported on Windows." 

26 raise RuntimeError(msg) 

27 from .qt_screenshot import QT_INSTALLED # noqa: PLC0415 

28 

29 if not QT_INSTALLED: 

30 msg = ( 

31 f"PyQtWebEngine is not installed to support Qt {self.format.upper()} conversion. " 

32 f"Please install `nbconvert[qt{self.format}]` to enable." 

33 ) 

34 raise RuntimeError(msg) 

35 from .qt_screenshot import QtScreenshot # noqa: PLC0415 

36 

37 return QtScreenshot 

38 

39 def _run_pyqtwebengine(self, html): 

40 ext = ".html" 

41 temp_file = tempfile.NamedTemporaryFile( # noqa: SIM115 

42 suffix=ext, delete=False 

43 ) 

44 filename = f"{temp_file.name[: -len(ext)]}.{self.format}" 

45 with temp_file: 

46 temp_file.write(html.encode("utf-8")) 

47 try: 

48 QtScreenshot = self._check_launch_reqs() 

49 s = QtScreenshot() 

50 s.capture(f"file://{temp_file.name}", filename, self.paginate) 

51 finally: 

52 # Ensure the file is deleted even if pyqtwebengine raises an exception 

53 os.unlink(temp_file.name) 

54 # Prefer Qt's in-memory bytes, but fall back to reading the file on disk 

55 data = getattr(s, "data", b"") 

56 

57 if (not data) and os.path.exists(filename): 

58 deadline = time.time() + 5.0 

59 while time.time() < deadline: 

60 try: 

61 if os.path.getsize(filename) > 0: 

62 break 

63 except OSError: 

64 pass 

65 time.sleep(0.05) 

66 

67 if os.path.exists(filename) and os.path.getsize(filename) > 0: 

68 with open(filename, "rb") as f: 

69 data = f.read() 

70 

71 # Best-effort cleanup of the generated output file 

72 try: 

73 if os.path.exists(filename): 

74 os.unlink(filename) 

75 except OSError: 

76 pass 

77 

78 return data 

79 

80 def from_notebook_node(self, nb, resources=None, **kw): 

81 """Convert from notebook node.""" 

82 self._check_launch_reqs() 

83 html, resources = super().from_notebook_node(nb, resources=resources, **kw) 

84 

85 self.log.info("Building %s", self.format.upper()) 

86 data = self._run_pyqtwebengine(html) 

87 self.log.info("%s successfully created", self.format.upper()) 

88 

89 # convert output extension 

90 # the writer above required it to be html 

91 resources["output_extension"] = f".{self.format}" 

92 

93 return data, resources