Coverage for an_website/utils/fix_static_path_impl.py: 93.750%

48 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-01 14:47 +0000

1# This program is free software: you can redistribute it and/or modify 

2# it under the terms of the GNU Affero General Public License as 

3# published by the Free Software Foundation, either version 3 of the 

4# License, or (at your option) any later version. 

5# 

6# This program is distributed in the hope that it will be useful, 

7# but WITHOUT ANY WARRANTY; without even the implied warranty of 

8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

9# GNU Affero General Public License for more details. 

10# 

11# You should have received a copy of the GNU Affero General Public License 

12# along with this program. If not, see <https://www.gnu.org/licenses/>. 

13 

14"""The module containing the impl of the fix_static_path function.""" 

15 

16import logging 

17import os 

18from collections.abc import Callable, Iterable, Mapping 

19from importlib.resources.abc import Traversable 

20from pathlib import Path 

21from typing import Final 

22 

23from blake3 import blake3 

24from openmoji_dist import VERSION as OPENMOJI_VERSION 

25 

26if "STATIC_DIR" not in locals(): 

27 from .. import STATIC_DIR 

28 

29LOGGER: Final = logging.getLogger(__name__) 

30 

31 

32def recurse_directory( 

33 root: Traversable, 

34 # pylint: disable-next=redefined-builtin 

35 filter: Callable[[Traversable], bool] = lambda _: True, 

36) -> Iterable[str]: 

37 """Recursively iterate over entries in a directory.""" 

38 dirs: list[str] = ["."] 

39 while dirs: # pylint: disable=while-used 

40 curr_dir = dirs.pop() 

41 for path in (root if curr_dir == "." else root / curr_dir).iterdir(): 

42 current: str = ( 

43 path.name 

44 if curr_dir == "." 

45 else os.path.join(curr_dir, path.name) 

46 ) 

47 if path.is_dir(): 

48 dirs.append(current) 

49 if filter(path): 

50 yield current 

51 

52 

53def hash_file(path: Traversable) -> str: 

54 """Hash a file with BLAKE3.""" 

55 hasher = blake3() 

56 with path.open("rb") as file: 

57 for data in file: 

58 hasher.update(data) 

59 return hasher.hexdigest(8) 

60 

61 

62def create_file_hashes_dict( 

63 filter_path_fun: Callable[[str], bool] | None = None 

64) -> dict[str, str]: 

65 """Create a dict of file hashes.""" 

66 static = Path("/static") 

67 file_hashes_dict = { 

68 f"{(static / path).as_posix()}": hash_file(STATIC_DIR / path) 

69 for path in recurse_directory(STATIC_DIR, lambda path: path.is_file()) 

70 if not path.endswith((".map", ".gz", ".zst")) 

71 if filter_path_fun is None or filter_path_fun(path) 

72 } 

73 if filter_path_fun is None: 

74 file_hashes_dict["/favicon.png"] = file_hashes_dict[ 

75 "/static/favicon.png" 

76 ] 

77 file_hashes_dict["/favicon.jxl"] = file_hashes_dict[ 

78 "/static/favicon.jxl" 

79 ] 

80 file_hashes_dict["/humans.txt"] = file_hashes_dict["/static/humans.txt"] 

81 return file_hashes_dict 

82 

83 

84def fix_static_path_impl(path: str, file_hashes_dict: Mapping[str, str]) -> str: 

85 """Fix the path for static files.""" 

86 if not path.startswith("/"): 

87 path = f"/static/{path}" 

88 if "?" in path: 

89 path = path.split("?")[0] 

90 if path.startswith("/static/openmoji/"): 

91 return f"{path}?v={OPENMOJI_VERSION}" 

92 path = path.lower() 

93 if path in file_hashes_dict: 

94 hash_ = file_hashes_dict[path] 

95 return f"{path}?v={hash_}" 

96 LOGGER.warning("%s not in FILE_HASHES_DICT", path) 

97 return path