Skip to content

Commit 0fe6104

Browse files
committed
html2print: minor cleanups on windows
1 parent 660ef53 commit 0fe6104

File tree

5 files changed

+83
-38
lines changed

5 files changed

+83
-38
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
entrypoint.sh -text

.github/workflows/ci-windows.yml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,7 @@ jobs:
2828
shell: powershell
2929

3030
- name: Check Chrome Version
31-
run: '& "C:\Program Files\Google\Chrome\Application\chrome.exe" --version'
32-
shell: powershell
33-
34-
- name: Add Chrome to PATH
35-
run: |
36-
$chromePath = "C:\Program Files\Google\Chrome\Application"
37-
echo "Adding $chromePath to PATH"
38-
echo "$chromePath" | Out-File -Append -Encoding utf8 $env:GITHUB_PATH
39-
shell: powershell
40-
41-
- name: Verify Chrome Installation
42-
run: chrome --version
31+
run: '(Get-Item "C:\Program Files\Google\Chrome\Application\chrome.exe").VersionInfo'
4332
shell: powershell
4433

4534
- name: Upgrade pip

html2print/html2print.py

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
from time import sleep
1414
from typing import Dict, List, Optional
1515

16+
import browsers
1617
import requests
17-
from requests import Response
18+
from requests import RequestException, Response
1819
from selenium import webdriver
1920
from selenium.webdriver.chrome.options import Options
2021
from selenium.webdriver.chrome.service import Service
21-
from webdriver_manager.core.os_manager import ChromeType, OperationSystemManager
2222

2323
__version__ = "0.0.15"
2424

@@ -39,9 +39,7 @@
3939

4040

4141
class ChromeDriverManager:
42-
def get_chrome_driver(self, path_to_cache_dir: str):
43-
chrome_version = self.get_chrome_version()
44-
42+
def get_chrome_driver(self, chrome_version: str, path_to_cache_dir: str):
4543
# If Web Driver Manager cannot detect Chrome, it returns None.
4644
if chrome_version is None:
4745
raise RuntimeError(
@@ -104,13 +102,24 @@ def get_chrome_driver(self, path_to_cache_dir: str):
104102

105103
@staticmethod
106104
def _download_chromedriver(
107-
chrome_major_version,
105+
chrome_major_version: str,
108106
os_type: str,
109-
path_to_driver_cache_dir,
110-
path_to_cached_chrome_driver,
111-
):
107+
path_to_driver_cache_dir: str,
108+
path_to_cached_chrome_driver: str,
109+
) -> str:
112110
url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
113-
response = ChromeDriverManager.send_http_get_request(url).json()
111+
response = ChromeDriverManager.send_http_get_request(url)
112+
if response is None:
113+
raise RuntimeError(
114+
"Could not download known-good-versions-with-downloads.json"
115+
)
116+
117+
response = response.json()
118+
if response is None:
119+
raise RuntimeError(
120+
"Could not parse known-good-versions-with-downloads.json"
121+
)
122+
assert isinstance(response, dict)
114123

115124
matching_versions = [
116125
item
@@ -143,6 +152,11 @@ def _download_chromedriver(
143152
)
144153
response = ChromeDriverManager.send_http_get_request(driver_url)
145154

155+
if response is None:
156+
raise Exception(
157+
f"Could not download ChromeDriver from {driver_url}"
158+
)
159+
146160
Path(path_to_driver_cache_dir).mkdir(parents=True, exist_ok=True)
147161
zip_path = os.path.join(path_to_driver_cache_dir, "chromedriver.zip")
148162
print( # noqa: T201
@@ -180,9 +194,12 @@ def send_http_get_request(url, params=None, **kwargs) -> Response:
180194
f"html2print: "
181195
f"failed to get response for URL: {url} with error: {last_error}"
182196
)
197+
raise RequestException(
198+
f"GET request failed after 3 attempts: {url}"
199+
) from last_error
183200

184201
@staticmethod
185-
def get_chrome_version():
202+
def get_browser_info() -> browsers.Browser:
186203
# Special case: GitHub Actions macOS CI machines have both
187204
# Google Chrome for Testing and normal Google Chrome installed, and
188205
# sometimes their versions are of different major version families.
@@ -216,17 +233,24 @@ def get_chrome_version():
216233
f"html2print: Google Chrome for Testing Version: {chrome_version}"
217234
)
218235

219-
return chrome_version
236+
return browsers.Browser(
237+
browser_type="chrome-for-testing",
238+
path=chrome_path,
239+
version=chrome_version,
240+
display_name="Google Chrome for Testing",
241+
)
220242
except FileNotFoundError:
221243
print("html2print: Chrome for Testing not available.") # noqa: T201
222244
except Exception as e:
223245
print( # noqa: T201
224246
f"html2print: Error getting Google Chrome for Testing version: {e}"
225247
)
248+
else:
249+
chrome_browser_info = browsers.get("chrome") or browsers.get(
250+
"chromium"
251+
)
226252

227-
os_manager = OperationSystemManager(os_type=None)
228-
version = os_manager.get_browser_version_from_os(ChromeType.GOOGLE)
229-
return version
253+
return chrome_browser_info
230254

231255

232256
def get_inches_from_millimeters(mm: float) -> float:
@@ -305,34 +329,44 @@ class Done(Exception):
305329

306330

307331
def create_webdriver(
332+
browser_info: browsers.Browser,
308333
chromedriver: Optional[str],
309334
path_to_cache_dir: str,
310335
page_load_timeout: int,
311336
debug: bool = False,
312337
) -> webdriver.Chrome:
313338
print("html2print: creating ChromeDriver service.", flush=True) # noqa: T201
339+
314340
if chromedriver is None:
315-
path_to_chrome = ChromeDriverManager().get_chrome_driver(
316-
path_to_cache_dir
341+
path_to_chrome_driver = ChromeDriverManager().get_chrome_driver(
342+
chrome_version=browser_info["version"],
343+
path_to_cache_dir=path_to_cache_dir,
317344
)
318345
else:
319-
path_to_chrome = chromedriver
320-
print(f"html2print: ChromeDriver available at path: {path_to_chrome}") # noqa: T201
346+
path_to_chrome_driver = chromedriver
347+
print( # noqa: T201
348+
f"html2print: ChromeDriver available at path: {path_to_chrome_driver}"
349+
)
321350

322351
if debug:
323352
service = Service(
324-
path_to_chrome, log_output=PATH_TO_CHROME_DRIVER_DEBUG_LOG
353+
path_to_chrome_driver, log_output=PATH_TO_CHROME_DRIVER_DEBUG_LOG
325354
)
326355
else:
327-
service = Service(path_to_chrome)
356+
service = Service(path_to_chrome_driver)
328357

329358
webdriver_options = Options()
359+
# Workaround for Windows: chrome is not typically found in the PATH, so need to supply the exact binary location manually
360+
if platform.system() == "Windows":
361+
webdriver_options.binary_location = browser_info["path"]
330362
webdriver_options.add_argument("start-maximized")
331363
webdriver_options.add_argument("disable-infobars")
332364
# Doesn't seem to be needed.
333365
# webdriver_options.add_argument('--disable-gpu') # noqa: ERA001
334366
webdriver_options.add_argument("--disable-extensions")
335-
webdriver_options.add_argument("--headless=chrome")
367+
# Use --headless=new, as it seems to be more stable on Windows (available since Chrome 109).
368+
# see https://www.selenium.dev/blog/2023/headless-is-going-away/
369+
webdriver_options.add_argument("--headless=new")
336370
# FIXME: This is not nice but otherwise it does not work in Ubuntu 24-based Docker image.
337371
# https://github.com/SeleniumHQ/selenium/issues/15327#issuecomment-2689287561
338372
webdriver_options.add_argument("--no-sandbox")
@@ -441,16 +475,31 @@ def main():
441475

442476
args = parser.parse_args()
443477

478+
# Look for Chrome on the System...
479+
browser_info = ChromeDriverManager.get_browser_info()
480+
444481
path_to_cache_dir: str
445482
if args.command == "get_driver":
446483
path_to_cache_dir = (
447484
args.cache_dir if args.cache_dir is not None else DEFAULT_CACHE_DIR
448485
)
449486

450-
path_to_chrome = ChromeDriverManager().get_chrome_driver(
451-
path_to_cache_dir
487+
path_to_chrome_browser = browser_info["path"]
488+
print( # noqa: T201
489+
f"html2print: Chrome available at path: {path_to_chrome_browser}"
490+
)
491+
chrome_version = browser_info["version"]
492+
print( # noqa: T201
493+
f"html2print: Chrome version : {chrome_version}"
494+
)
495+
496+
path_to_chrome_driver = ChromeDriverManager().get_chrome_driver(
497+
chrome_version=browser_info["version"],
498+
path_to_cache_dir=path_to_cache_dir,
499+
)
500+
print( # noqa: T201
501+
f"html2print: ChromeDriver available at path: {path_to_chrome_driver}"
452502
)
453-
print(f"html2print: ChromeDriver available at path: {path_to_chrome}") # noqa: T201
454503
sys.exit(0)
455504

456505
elif args.command == "print":
@@ -462,6 +511,7 @@ def main():
462511
args.cache_dir if args.cache_dir is not None else DEFAULT_CACHE_DIR
463512
)
464513
driver = create_webdriver(
514+
browser_info,
465515
args.chromedriver,
466516
path_to_cache_dir,
467517
page_load_timeout,

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,12 @@ classifiers = [
5050
dependencies = [
5151
# HTML2PDF dependencies
5252
"selenium",
53-
"webdriver-manager",
5453

5554
# requests is used by HTML2PDF_HTTPClient.
5655
"requests",
56+
57+
# to detect the browers path (needed on windows)
58+
"pybrowsers",
5759
]
5860

5961
[project.optional-dependencies]

tests/integration/lit.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,6 @@ config.suffixes = ['.itest', '.c']
2323
config.is_windows = lit_config.isWindows
2424
if not lit_config.isWindows:
2525
config.available_features.add('PLATFORM_IS_NOT_WINDOWS')
26+
27+
# In Linux CI, $HOME is required for chrome as it needs to access things in ~/.local
28+
config.environment['HOME'] = os.environ.get('HOME', '/tmp')

0 commit comments

Comments
 (0)