Files
edx-platform/openedx/core/djangoapps/theming/finders.py
Usama Sadiq 24272e5caa refactor: ran pyupgrade on openedx/core/djangoapps (#26956)
Ran pyupgrade on openedx/core/djangoapps/{system_wide_roles, theming}
2021-04-01 19:27:38 +05:00

98 lines
3.7 KiB
Python

"""
Static file finders for Django.
https://docs.djangoproject.com/en/1.8/ref/settings/#std:setting-STATICFILES_FINDERS
Yes, this interface is private and undocumented, but we need to access it anyway.
In order to deploy Open edX in production, it's important to be able to collect
and process static assets: images, CSS, JS, fonts, etc. Django's collectstatic
system is the accepted way to do that in Django-based projects, but that system
doesn't handle every kind of collection and processing that web developers need.
Other open source projects like `Django-Pipeline`_ and `Django-Require`_ hook
into Django's collectstatic system to provide features like minification,
compression, Sass pre-processing, and require.js optimization for assets before
they are pushed to production. To make sure that themed assets are collected
and served by the system (in addition to core assets), we need to extend this
interface, as well.
.. _Django-Pipeline: https://django-pipeline.readthedocs.org/
.. _Django-Require: https://github.com/etianen/django-require
"""
import os
from collections import OrderedDict
from django.contrib.staticfiles import utils
from django.contrib.staticfiles.finders import BaseFinder
from openedx.core.djangoapps.theming.helpers import get_themes
from openedx.core.djangoapps.theming.storage import ThemeStorage
class ThemeFilesFinder(BaseFinder): # lint-amnesty, pylint: disable=abstract-method
"""
A static files finder that looks in the directory of each theme as
specified in the source_dir attribute.
"""
storage_class = ThemeStorage
source_dir = 'static'
def __init__(self, *args, **kwargs):
# The list of themes that are handled
self.themes = []
# Mapping of theme names to storage instances
self.storages = OrderedDict()
themes = get_themes()
for theme in themes:
theme_storage = self.storage_class(
location=os.path.join(theme.path, self.source_dir),
prefix=theme.theme_dir_name,
)
self.storages[theme.theme_dir_name] = theme_storage
if theme.theme_dir_name not in self.themes:
self.themes.append(theme.theme_dir_name)
super().__init__(*args, **kwargs)
def list(self, ignore_patterns):
"""
List all files in all app storages.
"""
for storage in self.storages.values():
if storage.exists(''): # check if storage location exists
for path in utils.get_files(storage, ignore_patterns):
yield path, storage
def find(self, path, all=False): # pylint: disable=redefined-builtin
"""
Looks for files in the theme directories.
"""
matches = []
theme_dir_name = path.split("/", 1)[0]
themes = {t.theme_dir_name: t for t in get_themes()}
# if path is prefixed by theme name then search in the corresponding storage other wise search all storages.
if theme_dir_name in themes:
theme = themes[theme_dir_name]
path = "/".join(path.split("/")[1:])
match = self.find_in_theme(theme.theme_dir_name, path)
if match:
if not all:
return match
matches.append(match)
return matches
def find_in_theme(self, theme, path):
"""
Find a requested static file in an theme's static locations.
"""
storage = self.storages.get(theme, None)
if storage:
# only try to find a file if the source dir actually exists
if storage.exists(path):
matched_path = storage.path(path)
if matched_path:
return matched_path