Coverage for src/backend/InvenTree/plugin/staticfiles.py: 14%

62 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 17:47 +0000

1"""Static files management for InvenTree plugins.""" 

2 

3from django.contrib.staticfiles.storage import staticfiles_storage 

4 

5import structlog 

6 

7from plugin.registry import registry 

8 

9logger = structlog.get_logger('inventree') 

10 

11 

12def clear_static_dir(path, recursive=True): 

13 """Clear the specified directory from the 'static' output directory. 

14 

15 Arguments: 

16 path: The path to the directory to clear 

17 recursive: If True, clear the directory recursively 

18 """ 

19 if not staticfiles_storage.exists(path): 

20 return 

21 

22 dirs, files = staticfiles_storage.listdir(path) 

23 

24 for f in files: 

25 staticfiles_storage.delete(f'{path}{f}') 

26 

27 if recursive: 

28 for d in dirs: 

29 clear_static_dir(f'{path}{d}/', recursive=True) 

30 staticfiles_storage.delete(f'{path}{d}') 

31 

32 # Finally, delete the directory itself to remove orphan folders when uninstalling a plugin 

33 staticfiles_storage.delete(path) 

34 

35 logger.info('Cleared static directory: %s', path) 

36 

37 

38def collect_plugins_static_files(): 

39 """Copy static files from all installed plugins into the static directory.""" 

40 registry.check_reload() 

41 

42 logger.info('Collecting static files for all installed plugins.') 

43 

44 for slug in registry.plugins: 44 ↛ 45line 44 didn't jump to line 45 because the loop on line 44 never started

45 copy_plugin_static_files(slug, check_reload=False) 

46 

47 

48def clear_plugins_static_files(): 

49 """Clear out static files for plugins which are no longer active.""" 

50 installed_plugins = set(registry.plugins.keys()) 

51 

52 path = 'plugins/' 

53 

54 # Check that the directory actually exists 

55 if not staticfiles_storage.exists(path): 

56 return 

57 

58 # Get all static files in the 'plugins' static directory 

59 dirs, _files = staticfiles_storage.listdir('plugins/') 

60 

61 for d in dirs: 

62 # Check if the directory is a plugin directory 

63 if d not in installed_plugins: 

64 # Clear out the static files for this plugin 

65 clear_static_dir(f'plugins/{d}/', recursive=True) 

66 

67 

68def copy_plugin_static_files(slug, check_reload=True): 

69 """Copy static files for the specified plugin.""" 

70 if check_reload: 

71 registry.check_reload() 

72 

73 plugin = registry.get_plugin(slug) 

74 

75 if not plugin: 

76 return 

77 

78 logger.info("Collecting static files for plugin '%s'", slug) 

79 

80 # Get the source path for the plugin 

81 source_path = plugin.path().joinpath('static') 

82 

83 if not source_path.is_dir(): 

84 return 

85 

86 # Create prefix for the destination path 

87 destination_prefix = f'plugins/{slug}/' 

88 

89 # Clear the destination path 

90 clear_static_dir(destination_prefix) 

91 

92 items = list(source_path.glob('*')) 

93 

94 idx = 0 

95 copied = 0 

96 

97 while idx < len(items): 

98 item = items[idx] 

99 

100 idx += 1 

101 

102 if item.is_dir(): 

103 items.extend(item.glob('*')) 

104 continue 

105 

106 if item.is_file(): 

107 relative_path = item.relative_to(source_path) 

108 

109 destination_path = f'{destination_prefix}{relative_path}' 

110 

111 with item.open('rb') as src: 

112 staticfiles_storage.save(destination_path, src) 

113 

114 logger.debug('- copied %s to %s', item, destination_path) 

115 copied += 1 

116 

117 if copied > 0: 

118 logger.info("Copied %s static files for plugin '%s'.", copied, slug) 

119 

120 

121def clear_plugin_static_files(slug: str, recursive: bool = True): 

122 """Clear static files for the specified plugin.""" 

123 clear_static_dir(f'plugins/{slug}/', recursive=recursive)