--- contrib/python/Jinja2/py3/jinja2/loaders.py (index) +++ contrib/python/Jinja2/py3/jinja2/loaders.py (working tree) @@ -5,6 +5,7 @@ sources. import os import posixpath import sys +import pkgutil import typing as t import weakref import zipimport @@ -21,6 +22,8 @@ if t.TYPE_CHECKING: from .environment import Environment from .environment import Template +import __res as arcadia_res + def split_template_path(template: str) -> t.List[str]: """Split a path into segments and perform a sanity check. If it detects @@ -288,19 +291,22 @@ class PackageLoader(BaseLoader): # Make sure the package exists. This also makes namespace # packages work, otherwise get_loader returns None. - import_module(package_name) + package = import_module(package_name) spec = importlib.util.find_spec(package_name) assert spec is not None, "An import spec was not found for the package." loader = spec.loader assert loader is not None, "A loader was not found for the package." self._loader = loader self._archive = None + self._package = package template_root = None if isinstance(loader, zipimport.zipimporter): self._archive = loader.archive pkgdir = next(iter(spec.submodule_search_locations)) # type: ignore template_root = os.path.join(pkgdir, package_path).rstrip(os.path.sep) + elif hasattr(loader, "arcadia_source_finder"): + template_root = os.path.dirname(package.__file__).rstrip(os.path.sep) else: roots: t.List[str] = [] @@ -338,7 +341,16 @@ class PackageLoader(BaseLoader): p = posixpath.join(self._template_root, *split_template_path(template)) up_to_date: t.Optional[t.Callable[[], bool]] - if self._archive is None: + if self._archive is None and hasattr(self, "_package"): + try: + source = pkgutil.get_data(self.package_name, os.path.join(self.package_path, *split_template_path(template))) + except OSError: + raise TemplateNotFound(template) + + def up_to_date() -> bool: + return True + + elif self._archive is None: # Package is a directory. if not os.path.isfile(p): raise TemplateNotFound(template) @@ -368,7 +380,12 @@ class PackageLoader(BaseLoader): def list_templates(self) -> t.List[str]: results: t.List[str] = [] - if self._archive is None: + if self._archive is None and hasattr(self, "_package"): + prefix = os.path.join(self._template_root, self.package_path).encode() + b"/" + for name in arcadia_res.resfs_files(prefix): + results.append(name.removeprefix(prefix).decode()) + + elif self._archive is None: # Package is a directory. offset = len(self._template_root) --- contrib/python/Jinja2/py3/jinja2/loaders.py (index) +++ contrib/python/Jinja2/py3/jinja2/loaders.py (working tree) @@ -279,6 +279,7 @@ class PackageLoader(BaseLoader): package_name: str, package_path: "str" = "templates", encoding: str = "utf-8", + skip_unknown_package: bool = False, ) -> None: package_path = os.path.normpath(package_path).rstrip(os.path.sep) @@ -291,6 +292,7 @@ class PackageLoader(BaseLoader): self.package_path = package_path self.package_name = package_name self.encoding = encoding + self.skip_unknown_package = skip_unknown_package # Make sure the package exists. This also makes namespace # packages work, otherwise get_loader returns None. @@ -339,6 +341,9 @@ class PackageLoader(BaseLoader): def get_source( self, environment: "Environment", template: str ) -> t.Tuple[str, str, t.Optional[t.Callable[[], bool]]]: + if self._template_root is None and self.skip_unknown_package: + raise TemplateNotFound(template) + # Use posixpath even on Windows to avoid "drive:" or UNC # segments breaking out of the search directory. Use normpath to # convert Windows altsep to sep. @@ -386,6 +391,9 @@ class PackageLoader(BaseLoader): def list_templates(self) -> t.List[str]: results: t.List[str] = [] + if self._template_root is None and self.skip_unknown_package: + return results + if self._archive is None and hasattr(self, "_package"): prefix = os.path.join(self._template_root, self.package_path).encode() + b"/" for name in arcadia_res.resfs_files(prefix): --- contrib/python/Jinja2/py3/jinja2/loaders.py (index) +++ contrib/python/Jinja2/py3/jinja2/loaders.py (working tree) @@ -296,7 +296,13 @@ class PackageLoader(BaseLoader): # Make sure the package exists. This also makes namespace # packages work, otherwise get_loader returns None. - package = import_module(package_name) + try: + package = import_module(package_name) + except ModuleNotFoundError: + if skip_unknown_package: + self._template_root = None + return + raise spec = importlib.util.find_spec(package_name) assert spec is not None, "An import spec was not found for the package." loader = spec.loader