# Path: src/jinja2/exceptions.py
# class TemplateNotFound(IOError, LookupError, TemplateError):
#     """Raised if a template does not exist.
# 
#     .. versionchanged:: 2.11
#         If the given name is :class:`Undefined` and no message was
#         provided, an :exc:`UndefinedError` is raised.
#     """
# 
#     # Silence the Python warning about message being deprecated since
#     # it's not valid here.
#     message: t.Optional[str] = None
# 
#     def __init__(
#         self,
#         name: t.Optional[t.Union[str, "Undefined"]],
#         message: t.Optional[str] = None,
#     ) -> None:
#         IOError.__init__(self, name)
# 
#         if message is None:
#             from .runtime import Undefined
# 
#             if isinstance(name, Undefined):
#                 name._fail_with_undefined_error()
# 
#             message = name
# 
#         self.message = message
#         self.name = name
#         self.templates = [name]
# 
#     def __str__(self) -> str:
#         return str(self.message)
# 
# Path: src/jinja2/utils.py
# def internalcode(f: F) -> F:
#     """Marks the function as internally used"""
#     internal_code.add(f.__code__)
#     return f
# 
# Path: src/jinja2/utils.py
# def open_if_exists(filename: str, mode: str = "rb") -> t.Optional[t.IO]:
#     """Returns a file descriptor for the filename if that file exists,
#     otherwise ``None``.
#     """
#     if not os.path.isfile(filename):
#         return None
# 
#     return open(filename, mode)


import importlib.util
import os
import sys
import typing as t
import weakref
import zipimport
from collections import abc
from hashlib import sha1
from importlib import import_module
from types import ModuleType
from .exceptions import TemplateNotFound
from .utils import internalcode
from .utils import open_if_exists
    from .environment import Environment
    from .environment import Template
    ) -> None:
        package_name = f"_jinja2_module_templates_{id(self):x}"

        # create a fake module that looks for the templates in the
        # path given.
        mod = _TemplateModule(package_name)

        if not isinstance(path, abc.Iterable) or isinstance(path, str):
            path = [path]

        mod.__path__ = [os.fspath(p) for p in path]

        sys.modules[package_name] = weakref.proxy(
            mod, lambda x: sys.modules.pop(package_name, None)
        )

        # the only strong reference, the sys.modules entry is weak
        # so that the garbage collector can remove it once the
        # loader that created it goes out of business.
        self.module = mod
        self.package_name = package_name

    @staticmethod
    def get_template_key(name: str) -> str:
        return "tmpl_" + sha1(name.encode("utf-8")).hexdigest()

    @staticmethod
    def get_module_filename(name: str) -> str:
        return ModuleLoader.get_template_key(name) + ".py"


# Path: src/jinja2/exceptions.py
# class TemplateNotFound(IOError, LookupError, TemplateError):
#     """Raised if a template does not exist.
# 
#     .. versionchanged:: 2.11
#         If the given name is :class:`Undefined` and no message was
#         provided, an :exc:`UndefinedError` is raised.
#     """
# 
#     # Silence the Python warning about message being deprecated since
#     # it's not valid here.
#     message: t.Optional[str] = None
# 
#     def __init__(
#         self,
#         name: t.Optional[t.Union[str, "Undefined"]],
#         message: t.Optional[str] = None,
#     ) -> None:
#         IOError.__init__(self, name)
# 
#         if message is None:
#             from .runtime import Undefined
# 
#             if isinstance(name, Undefined):
#                 name._fail_with_undefined_error()
# 
#             message = name
# 
#         self.message = message
#         self.name = name
#         self.templates = [name]
# 
#     def __str__(self) -> str:
#         return str(self.message)
# 
# Path: src/jinja2/utils.py
# def internalcode(f: F) -> F:
#     """Marks the function as internally used"""
#     internal_code.add(f.__code__)
#     return f
# 
# Path: src/jinja2/utils.py
# def open_if_exists(filename: str, mode: str = "rb") -> t.Optional[t.IO]:
#     """Returns a file descriptor for the filename if that file exists,
#     otherwise ``None``.
#     """
#     if not os.path.isfile(filename):
#         return None
# 
#     return open(filename, mode)


# Path: src/jinja2/loaders.py
import importlib.util
import os
import sys
import typing as t
import weakref
import zipimport
from collections import abc
from hashlib import sha1
from importlib import import_module
from types import ModuleType
from .exceptions import TemplateNotFound
from .utils import internalcode
from .utils import open_if_exists
    from .environment import Environment
    from .environment import Template

    ) -> None:
        package_name = f"_jinja2_module_templates_{id(self):x}"

        # create a fake module that looks for the templates in the
        # path given.
        mod = _TemplateModule(package_name)

        if not isinstance(path, abc.Iterable) or isinstance(path, str):
            path = [path]

        mod.__path__ = [os.fspath(p) for p in path]

        sys.modules[package_name] = weakref.proxy(
            mod, lambda x: sys.modules.pop(package_name, None)
        )

        # the only strong reference, the sys.modules entry is weak
        # so that the garbage collector can remove it once the
        # loader that created it goes out of business.
        self.module = mod
        self.package_name = package_name

    @staticmethod
    def get_template_key(name: str) -> str:
        return "tmpl_" + sha1(name.encode("utf-8")).hexdigest()

    @staticmethod
    def get_module_filename(name: str) -> str:
        return ModuleLoader.get_template_key(name) + ".py"


    @internalcode