Coverage for liitos / placeholder.py: 92.39%

70 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-02-03 22:54:48 +00:00

1"""Loader function for placeholders (mostly images).""" 

2 

3import pathlib 

4import pkgutil 

5 

6from liitos import ENCODING, PathLike, log 

7 

8RESOURCES = ( 

9 'placeholders/this-resource-is-missing.jpg', 

10 'placeholders/this-resource-is-missing.pdf', 

11 'placeholders/this-resource-is-missing.png', 

12 'placeholders/this-resource-is-missing.svg', 

13 'placeholders/this-resource-is-missing.tiff', 

14 'placeholders/this-resource-is-missing.webp', 

15) 

16 

17READING_OPTIONS: dict[str, dict[str, list[str] | dict[str, str] | None]] = { 

18 '.jpg': {'args': ['rb'], 'kwargs': None}, 

19 '.pdf': {'args': ['rb'], 'kwargs': None}, 

20 '.png': {'args': ['rb'], 'kwargs': None}, 

21 '.svg': {'args': ['rt'], 'kwargs': {'encoding': ENCODING}}, 

22 '.tiff': {'args': ['rb'], 'kwargs': None}, 

23 '.webp': {'args': ['rb'], 'kwargs': None}, 

24} 

25 

26WRITING_OPTIONS: dict[str, dict[str, list[str] | dict[str, str] | None]] = { 

27 '.jpg': {'args': ['wb'], 'kwargs': None}, 

28 '.pdf': {'args': ['wb'], 'kwargs': None}, 

29 '.png': {'args': ['wb'], 'kwargs': None}, 

30 '.svg': {'args': ['wt'], 'kwargs': {'encoding': ENCODING}}, 

31 '.tiff': {'args': ['wb'], 'kwargs': None}, 

32 '.webp': {'args': ['wb'], 'kwargs': None}, 

33} 

34 

35 

36def load_resource(resource: PathLike, is_complete_path: bool = False) -> tuple[str, bytes | str]: 

37 """Load the template either from the package resources or an external path.""" 

38 from_path = pathlib.Path(resource) 

39 suffix = from_path.suffix 

40 if is_complete_path: 

41 if suffix and suffix in READING_OPTIONS: 

42 args = READING_OPTIONS[suffix].get('args') 

43 kwargs = READING_OPTIONS[suffix].get('kwargs') 

44 if READING_OPTIONS[suffix].get('kwargs'): 44 ↛ 47line 44 didn't jump to line 47 because the condition on line 44 was always true

45 with open(from_path, *args, **kwargs) as handle: # type: ignore 

46 return 'str', handle.read() 

47 with open(from_path, *args) as handle: # type: ignore 

48 return 'bytes', handle.read() 

49 with open(from_path, 'rb') as handle: 

50 return 'bytes', handle.read() 

51 

52 if suffix and suffix in READING_OPTIONS: 52 ↛ 59line 52 didn't jump to line 59 because the condition on line 52 was always true

53 args = READING_OPTIONS[suffix].get('args') 

54 kwargs = READING_OPTIONS[suffix].get('kwargs') 

55 if READING_OPTIONS[suffix].get('kwargs'): 

56 return 'str', pkgutil.get_data(__package__, str(resource)).decode(**kwargs) # type: ignore 

57 return 'bytes', pkgutil.get_data(__package__, str(resource)) # type: ignore 

58 

59 return 'bytes', pkgutil.get_data(__package__, str(resource)) # type: ignore 

60 

61 

62def eject(argv: list[str] | None = None) -> int: 

63 """Eject the templates into the folder given (default MISSING) and create the folder if it does not exist.""" 

64 argv = argv if argv else [''] 

65 into = argv[0] 

66 if not into.strip(): 

67 into = 'MISSING' 

68 into_path = pathlib.Path(into) 

69 (into_path / 'placeholders').mkdir(parents=True, exist_ok=True) 

70 for resource in RESOURCES: 

71 write_to = into_path / resource 

72 suffix = write_to.suffix 

73 log.info(f'{resource} -> {write_to}') 

74 if suffix and suffix in WRITING_OPTIONS: 74 ↛ 88line 74 didn't jump to line 88 because the condition on line 74 was always true

75 args = WRITING_OPTIONS[suffix].get('args') 

76 kwargs = WRITING_OPTIONS[suffix].get('kwargs') 

77 if WRITING_OPTIONS[suffix].get('kwargs'): 

78 log.info(f'text({resource}) per ({args=}) and ({kwargs=})') 

79 data = pkgutil.get_data(__package__, resource).decode(**kwargs) # type: ignore 

80 with open(write_to, *args, **kwargs) as target: # type: ignore 

81 target.write(data) 

82 continue 

83 log.info(f'binary({resource}) per ({args=})') 

84 data = pkgutil.get_data(__package__, resource) 

85 with open(write_to, *args) as target: # type: ignore 

86 target.write(data) # type: ignore 

87 continue 

88 log.warning(f'suffix ({suffix}) empty or not in ({", ".join(WRITING_OPTIONS.keys())})') 

89 

90 return 0 

91 

92 

93def dump_placeholder(target: PathLike) -> tuple[int, str]: 

94 """Write out the placeholder matching the file type per suffix.""" 

95 suffix = pathlib.Path(target).suffix 

96 proof = f'matching suffix ({suffix}) derived from target({target})' 

97 if suffix in WRITING_OPTIONS: 

98 args = WRITING_OPTIONS[suffix].get('args') 

99 kwargs = WRITING_OPTIONS[suffix].get('kwargs') 

100 resource = [res for res in RESOURCES if res.endswith(suffix)][0] 

101 kind, data = load_resource(resource) 

102 if kind == 'str': 

103 with open(target, *args, **kwargs) as handle: # type: ignore 

104 handle.write(data) # type: ignore 

105 return 0, f'wrote text mode placeholder {proof}' 

106 with open(target, *args) as handle: # type: ignore 

107 handle.write(data) # type: ignore 

108 return 0, f'wrote binary mode placeholder {proof}' 

109 

110 return 1, f'no placeholder found {proof}'