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

49 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-26 12:07 +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 types import MappingProxyType 

22from typing import Final 

23 

24from blake3 import blake3 

25from openmoji_dist import VERSION as OPENMOJI_VERSION 

26 

27if "STATIC_DIR" not in locals(): 

28 from .. import STATIC_DIR 

29 

30LOGGER: Final = logging.getLogger(__name__) 

31 

32 

33def recurse_directory( 

34 root: Traversable, 

35 # pylint: disable-next=redefined-builtin 

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

37) -> Iterable[str]: 

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

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

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

41 curr_dir = dirs.pop() 

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

43 current: str = ( 

44 path.name 

45 if curr_dir == "." 

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

47 ) 

48 if path.is_dir(): 

49 dirs.append(current) 

50 if filter(path): 

51 yield current 

52 

53 

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

55 """Hash a file with BLAKE3.""" 

56 hasher = blake3() 

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

58 for data in file: 

59 hasher.update(data) 

60 return hasher.hexdigest(8) 

61 

62 

63def create_file_hashes_dict( 

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

65) -> Mapping[str, str]: 

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

67 static = Path("/static") 

68 file_hashes_dict = { 

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

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

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

72 if filter_path_fun is None or filter_path_fun(path) 

73 } 

74 if filter_path_fun is None: 

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

76 "/static/favicon.png" 

77 ] 

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

79 "/static/favicon.jxl" 

80 ] 

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

82 return MappingProxyType(file_hashes_dict) 

83 

84 

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

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

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

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

89 if "?" in path: 

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

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

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

93 path = path.lower() 

94 if path in file_hashes_dict: 

95 hash_ = file_hashes_dict[path] 

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

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

98 return path