Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pdfplumber/repair.py: 29%

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

28 statements  

1import pathlib 

2import shutil 

3import subprocess 

4from io import BufferedReader, BytesIO 

5from typing import Literal, Optional, Union 

6 

7T_repair_setting = Literal["default", "prepress", "printer", "ebook", "screen"] 

8 

9 

10def _repair( 

11 path_or_fp: Union[str, pathlib.Path, BufferedReader, BytesIO], 

12 password: Optional[str] = None, 

13 gs_path: Optional[Union[str, pathlib.Path]] = None, 

14 setting: T_repair_setting = "default", 

15) -> BytesIO: 

16 

17 executable = ( 

18 gs_path 

19 or shutil.which("gs") 

20 or shutil.which("gswin32c") 

21 or shutil.which("gswin64c") 

22 ) 

23 if executable is None: # pragma: nocover 

24 raise Exception( 

25 "Cannot find Ghostscript, which is required for repairs.\n" 

26 "Visit https://www.ghostscript.com/ for installation instructions." 

27 ) 

28 

29 repair_args = [ 

30 executable, 

31 "-sstdout=%stderr", 

32 "-o", 

33 "-", 

34 "-sDEVICE=pdfwrite", 

35 f"-dPDFSETTINGS=/{setting}", 

36 ] 

37 

38 if password: 

39 repair_args += [f"-sPDFPassword={password}"] 

40 

41 if isinstance(path_or_fp, (str, pathlib.Path)): 

42 stdin = None 

43 repair_args += [str(pathlib.Path(path_or_fp).absolute())] 

44 else: 

45 stdin = path_or_fp 

46 repair_args += ["-"] 

47 

48 proc = subprocess.Popen( 

49 repair_args, 

50 stdin=subprocess.PIPE if stdin else None, 

51 stdout=subprocess.PIPE, 

52 stderr=subprocess.PIPE, 

53 ) 

54 

55 stdout, stderr = proc.communicate(stdin.read() if stdin else None) 

56 

57 if proc.returncode: 

58 raise Exception(f"{stderr.decode('utf-8')}") 

59 

60 return BytesIO(stdout) 

61 

62 

63def repair( 

64 path_or_fp: Union[str, pathlib.Path, BufferedReader, BytesIO], 

65 outfile: Optional[Union[str, pathlib.Path]] = None, 

66 password: Optional[str] = None, 

67 gs_path: Optional[Union[str, pathlib.Path]] = None, 

68 setting: T_repair_setting = "default", 

69) -> Optional[BytesIO]: 

70 repaired = _repair(path_or_fp, password, gs_path=gs_path, setting=setting) 

71 if outfile: 

72 with open(outfile, "wb") as f: 

73 f.write(repaired.read()) 

74 return None 

75 else: 

76 return repaired