Skip to content

FsSpecFileSystemLoader

Base classes

Name Children Inherits
LoaderMixin
jinjarope.loaders
Loader mixin which allows to OR loaders into a choice loader.
BaseLoader
jinja2.loaders
Baseclass for all loaders. Subclass this and override `get_source` to

⋔ Inheritance diagram

graph TD
  94173638369200["fsspecloaders.FsSpecFileSystemLoader"]
  94173637890544["loaders.LoaderMixin"]
  139866058043616["builtins.object"]
  94173636407456["loaders.BaseLoader"]
  94173637890544 --> 94173638369200
  139866058043616 --> 94173637890544
  94173636407456 --> 94173638369200
  139866058043616 --> 94173636407456

🛈 DocStrings

Bases: LoaderMixin, BaseLoader

A jinja loader for fsspec filesystems.

This loader allows to access templates from an fsspec filesystem.

Template paths must be relative to the filesystem root. In order to access templates via protocol path, see FsSpecProtocolPathLoader.

Examples:

# protocol path
loader = FsSpecFileSystemLoader("dir::github://phil65:mknodes@main/docs")
env = Environment(loader=loader)
env.get_template("icons.jinja").render()

# protocol and storage options
loader = FsSpecFileSystemLoader("github", org="phil65", repo="mknodes")
env = Environment(loader=loader)
env.get_template("docs/icons.jinja").render()

# fsspec filesystem
fs = fsspec.filesystem("github", org="phil65", repo="mknodes")
loader = FsSpecFileSystemLoader(fs)
env = Environment(loader=loader)
env.get_template("docs/icons.jinja").render()
Source code in src/jinjarope/fsspecloaders.py
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
class FsSpecFileSystemLoader(loaders_.LoaderMixin, jinja2.BaseLoader):
    """A jinja loader for fsspec filesystems.

    This loader allows to access templates from an fsspec filesystem.

    Template paths must be relative to the filesystem root.
    In order to access templates via protocol path, see `FsSpecProtocolPathLoader`.

    Examples:
        ``` py
        # protocol path
        loader = FsSpecFileSystemLoader("dir::github://phil65:mknodes@main/docs")
        env = Environment(loader=loader)
        env.get_template("icons.jinja").render()

        # protocol and storage options
        loader = FsSpecFileSystemLoader("github", org="phil65", repo="mknodes")
        env = Environment(loader=loader)
        env.get_template("docs/icons.jinja").render()

        # fsspec filesystem
        fs = fsspec.filesystem("github", org="phil65", repo="mknodes")
        loader = FsSpecFileSystemLoader(fs)
        env = Environment(loader=loader)
        env.get_template("docs/icons.jinja").render()
        ```

    """

    ID = "fsspec"

    def __init__(self, fs: fsspec.AbstractFileSystem | str, **kwargs: Any):
        """Constructor.

        Args:
            fs: Either a protocol path string or an fsspec filesystem instance.
                Also supports "::dir" prefix to set the root path.
            kwargs: Optional storage options for the filesystem.
        """
        super().__init__()
        match fs:
            case str() if "://" in fs:
                self.fs, self.path = fsspec.core.url_to_fs(fs, **kwargs)
            case str():
                self.fs, self.path = fsspec.filesystem(fs, **kwargs), ""
            case _:
                self.fs, self.path = fs, ""
        self.storage_options = kwargs

    def __repr__(self):
        return utils.get_repr(self, fs=self.fs)

    def __eq__(self, other):
        return (
            type(self) is type(other)
            and self.storage_options == other.storage_options
            and self.fs == other.fs
            and self.path == other.path
        )

    def __hash__(self):
        return (
            hash(tuple(sorted(self.storage_options.items())))
            + hash(self.fs)
            + hash(self.path)
        )

    def list_templates(self) -> list[str]:
        return [
            f"{path}{self.fs.sep}{f}" if path else f
            for path, _dirs, files in self.fs.walk(self.fs.root_marker)
            for f in files
        ]

    def get_source(
        self,
        environment: jinja2.Environment,
        template: str,
    ) -> tuple[str, str, Callable[[], bool] | None]:
        try:
            with self.fs.open(template) as file:
                src = file.read().decode()  # pyright: ignore
        except FileNotFoundError as e:
            raise jinja2.TemplateNotFound(template) from e
        path = pathlib.Path(template).as_posix()
        return src, path, lambda: True

__init__

__init__(fs: AbstractFileSystem | str, **kwargs: Any)

Constructor.

Parameters:

Name Type Description Default
fs AbstractFileSystem | str

Either a protocol path string or an fsspec filesystem instance. Also supports "::dir" prefix to set the root path.

required
kwargs Any

Optional storage options for the filesystem.

{}
Source code in src/jinjarope/fsspecloaders.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def __init__(self, fs: fsspec.AbstractFileSystem | str, **kwargs: Any):
    """Constructor.

    Args:
        fs: Either a protocol path string or an fsspec filesystem instance.
            Also supports "::dir" prefix to set the root path.
        kwargs: Optional storage options for the filesystem.
    """
    super().__init__()
    match fs:
        case str() if "://" in fs:
            self.fs, self.path = fsspec.core.url_to_fs(fs, **kwargs)
        case str():
            self.fs, self.path = fsspec.filesystem(fs, **kwargs), ""
        case _:
            self.fs, self.path = fs, ""
    self.storage_options = kwargs

Show source on GitHub