Source code for moderngl_window.finders.base

"""
Base finders
"""
import functools
import logging

from collections import namedtuple
from pathlib import Path

from moderngl_window.conf import settings
from moderngl_window.exceptions import ImproperlyConfigured
from moderngl_window.utils.module_loading import import_string

FinderEntry = namedtuple('FinderEntry', ['path', 'abspath', 'exists'])

logger = logging.getLogger(__name__)


[docs]class BaseFilesystemFinder: """Base class for searching filesystem directories""" settings_attr = None """str: Name of the attribute in :py:class:`~moderngl_window.conf.Settings` containing a list of paths the finder should seach in. """
[docs] def __init__(self): """Initialize finder class by looking up the paths referenced in ``settings_attr``. """ if not hasattr(settings, self.settings_attr): raise ImproperlyConfigured( "Settings doesn't define {}. " "This is required when using a FileSystemFinder.".format(self.settings_attr) ) self.paths = getattr(settings, self.settings_attr)
[docs] def find(self, path: Path) -> Path: """Finds a file in the configured paths returning its absolute path. Args: path (pathlib.Path): The path to find Returns: The absolute path to the file or None if not found """ # Update paths from settings to make them editable runtime if getattr(self, 'settings_attr', None): self.paths = getattr(settings, self.settings_attr) if not isinstance(path, Path): raise ValueError("FilesystemFinders only take Path instances, not {}".format(type(path))) logger.debug("find %s", path) # Ignore absolute paths so other finder types can pick them up. if path.is_absolute(): logger.debug("Ignoring absolute path: %s", path) return None logger.debug("paths: %s", self.paths) for search_path in self.paths: search_path = Path(search_path) # Keep ensuring all search paths are absolute if not search_path.is_absolute(): raise ImproperlyConfigured("Search search path '{}' is not an absolute path") abspath = search_path / path logger.debug("abspath %s", abspath) if abspath.exists(): logger.debug("found %s", abspath) return abspath return None
@functools.lru_cache(maxsize=None) def get_finder(import_path: str): """ Get a finder class from an import path. This function uses an lru cache. Args: import_path: string representing an import path Return: An instance of the finder Raises: ImproperlyConfigured is the finder is not found """ Finder = import_string(import_path) if not issubclass(Finder, BaseFilesystemFinder): raise ImproperlyConfigured('Finder {} is not a subclass of .finders.FileSystemFinder'.format(import_path)) return Finder()