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
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""Static files management for InvenTree plugins."""
3from django.contrib.staticfiles.storage import staticfiles_storage
5import structlog
7from plugin.registry import registry
9logger = structlog.get_logger('inventree')
12def clear_static_dir(path, recursive=True):
13 """Clear the specified directory from the 'static' output directory.
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
22 dirs, files = staticfiles_storage.listdir(path)
24 for f in files:
25 staticfiles_storage.delete(f'{path}{f}')
27 if recursive:
28 for d in dirs:
29 clear_static_dir(f'{path}{d}/', recursive=True)
30 staticfiles_storage.delete(f'{path}{d}')
32 # Finally, delete the directory itself to remove orphan folders when uninstalling a plugin
33 staticfiles_storage.delete(path)
35 logger.info('Cleared static directory: %s', path)
38def collect_plugins_static_files():
39 """Copy static files from all installed plugins into the static directory."""
40 registry.check_reload()
42 logger.info('Collecting static files for all installed plugins.')
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)
48def clear_plugins_static_files():
49 """Clear out static files for plugins which are no longer active."""
50 installed_plugins = set(registry.plugins.keys())
52 path = 'plugins/'
54 # Check that the directory actually exists
55 if not staticfiles_storage.exists(path):
56 return
58 # Get all static files in the 'plugins' static directory
59 dirs, _files = staticfiles_storage.listdir('plugins/')
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)
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()
73 plugin = registry.get_plugin(slug)
75 if not plugin:
76 return
78 logger.info("Collecting static files for plugin '%s'", slug)
80 # Get the source path for the plugin
81 source_path = plugin.path().joinpath('static')
83 if not source_path.is_dir():
84 return
86 # Create prefix for the destination path
87 destination_prefix = f'plugins/{slug}/'
89 # Clear the destination path
90 clear_static_dir(destination_prefix)
92 items = list(source_path.glob('*'))
94 idx = 0
95 copied = 0
97 while idx < len(items):
98 item = items[idx]
100 idx += 1
102 if item.is_dir():
103 items.extend(item.glob('*'))
104 continue
106 if item.is_file():
107 relative_path = item.relative_to(source_path)
109 destination_path = f'{destination_prefix}{relative_path}'
111 with item.open('rb') as src:
112 staticfiles_storage.save(destination_path, src)
114 logger.debug('- copied %s to %s', item, destination_path)
115 copied += 1
117 if copied > 0:
118 logger.info("Copied %s static files for plugin '%s'.", copied, slug)
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)