Coverage for src / ocarina / infra / driver_builder.py: 0.00%

31 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-06-04 15:56 +0200

1"""Generic driver builder with profile/temp dir lifecycle management.""" 

2 

3import shutil 

4import tempfile 

5from contextlib import suppress 

6from pathlib import Path 

7from typing import TYPE_CHECKING 

8 

9if TYPE_CHECKING: 

10 from collections.abc import Callable 

11 

12 from ocarina.custom_types.built_web_driver import BuiltWebDriver 

13 

14 

15class DriverBuilder[Driver]: 

16 """Manages temp profile dir lifecycle and builds (driver, dispose) pair. 

17 

18 build_driver receives the profile directory path and returns a ready driver. 

19 All setup (implicit wait, options, etc.) belongs in build_driver. 

20 """ 

21 

22 def __init__( # noqa: D107 

23 self, 

24 *, 

25 build_driver: Callable[[str], Driver], 

26 profile_path: str | None = None, 

27 tmp_dir_prefix: str = ".driver_profile_", 

28 ) -> None: 

29 self._build_driver = build_driver 

30 self._profile_path = profile_path 

31 self._tmp_dir_prefix = tmp_dir_prefix 

32 self._tmp_dir: tempfile.TemporaryDirectory[str] | None = None 

33 

34 def build(self) -> BuiltWebDriver[Driver]: 

35 """Return (driver, dispose). dispose() quits driver and cleans temp dir.""" 

36 tmp_dir, profile_path = self._prepare_profile() 

37 

38 driver = self._build_driver(profile_path) 

39 

40 def dispose() -> None: 

41 with suppress(Exception): 

42 driver.quit() # type: ignore[attr-defined] 

43 with suppress(Exception): 

44 tmp_dir.cleanup() 

45 

46 return driver, dispose 

47 

48 def _prepare_profile(self) -> tuple[tempfile.TemporaryDirectory[str], str]: 

49 """Create temp dir, optionally copying an existing profile into it.""" 

50 try: 

51 tmp_dir = tempfile.TemporaryDirectory( 

52 prefix=self._tmp_dir_prefix, dir=str(Path.cwd()) 

53 ) 

54 if self._profile_path is not None: 

55 shutil.copytree(self._profile_path, tmp_dir.name, dirs_exist_ok=True) 

56 except Exception as exc: 

57 with suppress(Exception): 

58 tmp_dir.cleanup() 

59 msg = "Failed to prepare driver profile directory." 

60 raise RuntimeError(msg) from exc 

61 else: 

62 return tmp_dir, tmp_dir.name