Path:
strictdoc/features/html2pdf/pdf_print_driver.py
Lines:
104
Non-empty lines:
88
Non-empty lines covered with requirements:
88 / 88 (100.0%)
Functions:
8
Functions covered by requirements:
8 / 8 (100.0%)
1
"""2
@relation(SDOC-SRS-51, scope=file)3
"""4
5
import os.path
6
from subprocess import CalledProcessError, CompletedProcess, TimeoutExpired, run
7
from typing import List, Tuple
8
9
from html2pdf4doc.main import HPDExitCode
10
11
from strictdoc.core.project_config import ProjectConfig
12
from strictdoc.features.html2pdf.pdf_postprocessor import PDFPostprocessor
13
from strictdoc.helpers.timing import measure_performance
14
15
16
class PDFPrintDriverException(Exception):
17
def __init__(self, exception: Exception):
18
super().__init__()
19
self.exception: Exception = exception
20
21
def get_server_user_message(self) -> str:
22
"""
23
Provide a user-friendly message that describes the underlying exception/error.24
"""25
26
if self.is_could_not_detect_chrome():
27
return "HTML2PDF could not detect an existing Chrome installation."
28
29
if self.is_timeout_error():
30
return "HTML2PDF timeout error."
31
32
if self.is_js_success_timeout():
33
return "HTML2PDF.js success timeout error."
34
35
return "HTML2PDF internal error."
36
37
def is_timeout_error(self) -> bool:
38
return isinstance(self.exception, TimeoutExpired)
39
40
def is_could_not_detect_chrome(self) -> bool:
41
return (
42
isinstance(self.exception, CalledProcessError)
43
and self.exception.returncode == HPDExitCode.COULD_NOT_FIND_CHROME
44
)45
46
def is_js_success_timeout(self) -> bool:
47
return (
48
isinstance(self.exception, CalledProcessError)
49
and self.exception.returncode
50
== HPDExitCode.DID_NOT_RECEIVE_SUCCESS_STATUS_FROM_HTML2PDF4DOC_JS
51
)52
53
54
class PDFPrintDriver:
55
@staticmethod56
def get_pdf_from_html(
57
project_config: ProjectConfig,
58
paths_to_print: List[Tuple[str, str]],
59
path_to_input_root: str,
60
) -> None:
61
assert isinstance(paths_to_print, list), paths_to_print
62
path_to_html2pdf4doc_cache = os.path.join(
63
project_config.get_path_to_cache_dir(), "html2pdf"
64
)65
cmd: List[str] = [
66
# Using sys.executable instead of "python" is important because67
# venv subprocess call to python resolves to wrong interpreter,68
# https://github.com/python/cpython/issues/8620769
# Switching back to calling html2pdf4doc directly because the70
# python -m doesn't work well with PyInstaller.71
# sys.executable, "-m"72
"html2pdf4doc",
73
"print",
74
"--cache-dir",
75
path_to_html2pdf4doc_cache,
76
]77
if project_config.chromedriver is not None:
78
cmd.extend(
79
[80
"--chromedriver",
81
project_config.chromedriver,
82
]83
)84
if project_config.html2pdf_strict:
85
cmd.append("--strict")
86
for path_to_print_ in paths_to_print:
87
cmd.append(path_to_print_[0])
88
cmd.append(path_to_print_[1])
89
90
with measure_performance(
91
"PDFPrintDriver: printing HTML to PDF using HTML2PDF and Chrome Driver"92
):93
try:
94
_: CompletedProcess[bytes] = run(
95
cmd,
96
capture_output=False,
97
check=True,
98
)99
PDFPostprocessor.rewrite_cross_document_links(
100
path_to_input_root=path_to_input_root,
101
paths_to_print=paths_to_print,
102
)103
except Exception as e_:
104
raise PDFPrintDriverException(e_) from e_