Skip to content

Commit 04420df

Browse files
committed
chore: implement get_source_async for fsspec loaders
1 parent e9d3f2e commit 04420df

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ keywords = [
3737
]
3838

3939
requires-python = ">=3.12"
40-
dependencies = ["jinja2", "fsspec", "universal_pathlib"]
40+
dependencies = ["jinja2", "fsspec", "universal_pathlib", "upathtools"]
4141
license = "MIT"
4242

4343
[project.optional-dependencies]

src/jinjarope/fsspecloaders.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from __future__ import annotations
22

3+
import functools
34
import pathlib
45
from typing import TYPE_CHECKING, Any
56

67
import jinja2
8+
import upathtools
79

810
from jinjarope import envglobals, loaders as loaders_, utils
911

@@ -14,6 +16,11 @@
1416
import fsspec
1517

1618

19+
@functools.cache
20+
async def get_template(path: str) -> str:
21+
return await upathtools.read_path(path)
22+
23+
1724
class FsSpecProtocolPathLoader(loaders_.LoaderMixin, jinja2.BaseLoader):
1825
"""A jinja loader for fsspec filesystems.
1926
@@ -48,6 +55,18 @@ def get_source(
4855
path = pathlib.Path(template).as_posix()
4956
return src, path, lambda: True
5057

58+
async def get_source_async(
59+
self,
60+
environment: jinja2.Environment | None,
61+
template: str,
62+
) -> tuple[str, str, Callable[[], bool] | None]:
63+
try:
64+
src = await get_template(template)
65+
except FileNotFoundError as e:
66+
raise jinja2.TemplateNotFound(template) from e
67+
path = pathlib.Path(template).as_posix()
68+
return src, path, lambda: True
69+
5170
def list_templates(self) -> list[str]:
5271
return []
5372

@@ -153,6 +172,23 @@ def get_source(
153172
path = pathlib.Path(template).as_posix()
154173
return src, path, lambda: True
155174

175+
async def get_source_async(
176+
self,
177+
environment: jinja2.Environment,
178+
template: str,
179+
) -> tuple[str, str, Callable[[], bool] | None]:
180+
from upathtools.async_ops import get_async_fs
181+
182+
fs = await get_async_fs(self.fs)
183+
try:
184+
file = await fs.open_async(template)
185+
async with file:
186+
src = await file.read().decode() # pyright: ignore
187+
except FileNotFoundError as e:
188+
raise jinja2.TemplateNotFound(template) from e
189+
path = pathlib.Path(template).as_posix()
190+
return src, path, lambda: True
191+
156192

157193
if __name__ == "__main__":
158194
from jinjarope import Environment

0 commit comments

Comments
 (0)