core methods engines have to provide their own implementation except for fromstring which is optional initialize the template engine params is a dict of configuration settings create and return a template for the given source code this method is optional load and return a template for the given name raise templatedoesnotexist if no such template exists utility methods they are provided to minimize code duplication and security issues in thirdparty backends return a list of directories to search for templates immutable return value because it s cached and shared by callers iterate over candidate files for templatename ignore files that don t lie inside configured template dirs to avoid directory traversal attacks the joined path was located outside of this templatedir it might be inside another one so this isn t fatal core methods engines have to provide their own implementation except for from_string which is optional initialize the template engine params is a dict of configuration settings create and return a template for the given source code this method is optional load and return a template for the given name raise templatedoesnotexist if no such template exists utility methods they are provided to minimize code duplication and security issues in third party backends return a list of directories to search for templates immutable return value because it s cached and shared by callers iterate over candidate files for template_name ignore files that don t lie inside configured template dirs to avoid directory traversal attacks the joined path was located outside of this template_dir it might be inside another one so this isn t fatal
from django.core.exceptions import ImproperlyConfigured, SuspiciousFileOperation
from django.template.utils import get_app_template_dirs
from django.utils._os import safe_join
from django.utils.functional import cached_property


class BaseEngine:
    
    

    def __init__(self, params):
        
        params = params.copy()
        self.name = params.pop("NAME")
        self.dirs = list(params.pop("DIRS"))
        self.app_dirs = params.pop("APP_DIRS")
        if params:
            raise ImproperlyConfigured(
                "Unknown parameters: {}".format(", ".join(params))
            )

    @property
    def app_dirname(self):
        raise ImproperlyConfigured(
            "{} doesn't support loading templates from installed "
            "applications.".format(self.__class__.__name__)
        )

    def from_string(self, template_code):
        
        raise NotImplementedError(
            "subclasses of BaseEngine should provide a from_string() method"
        )

    def get_template(self, template_name):
        
        raise NotImplementedError(
            "subclasses of BaseEngine must provide a get_template() method"
        )

    
    

    @cached_property
    def template_dirs(self):
        
        
        template_dirs = tuple(self.dirs)
        if self.app_dirs:
            template_dirs += get_app_template_dirs(self.app_dirname)
        return template_dirs

    def iter_template_filenames(self, template_name):
        
        for template_dir in self.template_dirs:
            try:
                yield safe_join(template_dir, template_name)
            except SuspiciousFileOperation:
                
                
                pass