Coverage for liitos/placeholder.py: 91.59%

71 statements  

« prev     ^ index     » next       coverage.py v7.4.1, created at 2024-02-13 17:41:25 +00:00

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

2 

3import pathlib 

4import pkgutil 

5from typing import Union 

6 

7from liitos import ENCODING, PathLike, log 

8 

9RESOURCES = ( 

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

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

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

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

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

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

16) 

17 

18READING_OPTIONS: dict[str, dict[str, Union[list[str], dict[str, str], None]]] = { 

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

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

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

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

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

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

25} 

26 

27WRITING_OPTIONS: dict[str, dict[str, Union[list[str], dict[str, str], None]]] = { 

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

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

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

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

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

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

34} 

35 

36 

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

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

39 from_path = pathlib.Path(resource) 

40 suffix = from_path.suffix 

41 if is_complete_path: 

42 if suffix and suffix in READING_OPTIONS: 

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

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

45 if READING_OPTIONS[suffix].get('kwargs'): 45 ↛ 48line 45 didn't jump to line 48, because the condition on line 45 was never false

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

47 return 'str', handle.read() 

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

49 return 'bytes', handle.read() 

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

51 return 'bytes', handle.read() 

52 

53 if suffix and suffix in READING_OPTIONS: 53 ↛ 60line 53 didn't jump to line 60, because the condition on line 53 was never false

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

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

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

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

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

59 

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

61 

62 

63def eject(argv: Union[list[str], None] = None) -> int: 

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

65 argv = argv if argv else [''] 

66 into = argv[0] 

67 if not into.strip(): 

68 into = 'MISSING' 

69 into_path = pathlib.Path(into) 

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

71 for resource in RESOURCES: 

72 write_to = into_path / resource 

73 suffix = write_to.suffix 

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

75 if suffix and suffix in WRITING_OPTIONS: 75 ↛ 89line 75 didn't jump to line 89, because the condition on line 75 was never false

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

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

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

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

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

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

82 target.write(data) 

83 continue 

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

85 data = pkgutil.get_data(__package__, resource) 

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

87 target.write(data) # type: ignore 

88 continue 

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

90 

91 return 0 

92 

93 

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

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

96 suffix = pathlib.Path(target).suffix 

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

98 if suffix in WRITING_OPTIONS: 

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

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

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

102 kind, data = load_resource(resource) 

103 if kind == 'str': 

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

105 handle.write(data) # type: ignore 

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

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

108 handle.write(data) # type: ignore 

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

110 

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