# loaders

URL: /kida/api/environment/loaders/
Section: environment
Description: Template loaders for Kida environment.

Loaders provide template source to the Environment. They implement
`get_source(name)` returning `(source, filename)`.

Built-in Loaders:
- `FileSystemLoader`: Load from filesystem directories
- `DictLoader`: Load from in-memory dictionary (testing/embedded)
- `ChoiceLoader`: Try multiple loaders in order (theme fallback)
- `PrefixLoader`: Namespace templates by prefix (plugin architectures)
- `PackageLoader`: Load from installed Python packages (importlib.resources)
- `FunctionLoader`: Wrap a callable as a loader (quick one-offs)

Custom Loaders:
Implement the Loader protocol:
    ```python
    class DatabaseLoader:
        def get_source(self, name: str) -> tuple[str, str | None]:
            row = db.query("SELECT source FROM templates WHERE name = ?", name)
            if not row:
                raise TemplateNotFoundError(f"Template '{name}' not found")
            return row.source, f"db://{name}"

        def list_templates(self) -> list[str]:
            return [r.name for r in db.query("SELECT name FROM templates")]
    ```

Thread-Safety:
Loaders should be thread-safe for concurrent `get_source()` calls.
All built-in loaders are safe (FileSystemLoader reads files atomically,
DictLoader uses immutable dict lookup, ChoiceLoader and PrefixLoader
delegate to their child loaders, PackageLoader reads via importlib,
FunctionLoader delegates to the user-provided callable).

---

> For a complete page index, fetch /kida/llms.txt.

Open LLM text
(/kida/api/environment/loaders/index.txt)

Share with AI

Ask Claude
(https://claude.ai/new?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Fenvironment%2Floaders%2Findex.txt)

Ask ChatGPT
(https://chatgpt.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Fenvironment%2Floaders%2Findex.txt)

Ask Gemini
(https://gemini.google.com/app?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Fenvironment%2Floaders%2Findex.txt)

Ask Copilot
(https://copilot.microsoft.com/?q=Please%20help%20me%20understand%20this%20documentation%3A%20%2Fkida%2Fapi%2Fenvironment%2Floaders%2Findex.txt)

Module

#
`environment.loaders`

Template loaders for Kida environment.

Loaders provide template source to the Environment. They implement
`get_source(name)` returning `(source, filename)`.

Built-in Loaders:

- `FileSystemLoader`: Load from filesystem directories

- `DictLoader`: Load from in-memory dictionary (testing/embedded)

- `ChoiceLoader`: Try multiple loaders in order (theme fallback)

- `PrefixLoader`: Namespace templates by prefix (plugin architectures)

- `PackageLoader`: Load from installed Python packages (importlib.resources)

- `FunctionLoader`: Wrap a callable as a loader (quick one-offs)

Custom Loaders:

Implement the Loader protocol:

```
```python
class DatabaseLoader:
    def get_source(self, name: str) -> tuple[str, str | None]:
        row = db.query("SELECT source FROM templates WHERE name = ?", name)
        if not row:
            raise TemplateNotFoundError(f"Template '{name}' not found")
        return row.source, f"db://{name}"

    def list_templates(self) -> list[str]:
        return [r.name for r in db.query("SELECT name FROM templates")]
```
```

Thread-Safety:
Loaders should be thread-safe for concurrent`get_source()`calls.
All built-in loaders are safe (FileSystemLoader reads files atomically,
DictLoader uses immutable dict lookup, ChoiceLoader and PrefixLoader
delegate to their child loaders, PackageLoader reads via importlib,
FunctionLoader delegates to the user-provided callable).







6Classes










## Classes











        `FileSystemLoader`

5

▼


Load templates from filesystem directories.

Searches one or more directories for templates by name…










Load templates from filesystem directories.


Searches one or more directories for templates by name. The first matching
    file is returned. Supports arbitrary directory structures and file nesting.


Methods:
    get_source(name): Return (source, filename) for template
    list_templates(): Return sorted list of all template names


Search Order:
    Directories are searched in order. First match wins:
`python     loader = FileSystemLoader(["themes/custom/", "themes/default/"])     # Looks in themes/custom/ first, then themes/default/     `






#### Attributes




        Name
        Type
        Description





        `_paths`

  —




List of Path objects to search






  `_encoding`

  —




File encoding (default: utf-8)











#### Methods

















        `get_source`

1


          `tuple[str, str]`


▼


Load template source from filesystem.









      `def get_source(self, name: str) -> tuple[str, str]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, str]`















        `list_templates`

0


          `list[str]`


▼


List all templates in search paths.









      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      1

    ▼













        `__init__`

2

▼










      `def __init__(self, paths: str | Path | list[str | Path], encoding: str = 'utf-8')`




##### Parameters




        Name
        Type
        Description





        `paths`
`—`






  `encoding`
`—`


  Default:`'utf-8'`






























        `DictLoader`

4

▼


Load templates from an in-memory dictionary.

Maps template names to source strings. Useful for tes…










Load templates from an in-memory dictionary.


Maps template names to source strings. Useful for testing, embedded
    templates, or dynamically generated templates.


Methods:
    get_source(name): Return (source, None) for template
    list_templates(): Return sorted list of template names


Testing:



```
>>> loader = DictLoader({"test.html": "{{ x * 2 }}"})
```

```
>>> env = Environment(loader=loader)
>>> assert env.render("test.html", x=21) == "42"
```






#### Attributes




        Name
        Type
        Description





        `_mapping`

  —




Dict mapping template name → source string











#### Methods

















        `get_source`

1


          `tuple[str, None]`


▼










      `def get_source(self, name: str) -> tuple[str, None]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, None]`















        `list_templates`

0


          `list[str]`


▼










      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      1

    ▼













        `__init__`

1

▼










      `def __init__(self, mapping: dict[str, str])`




##### Parameters




        Name
        Type
        Description





        `mapping`
`—`































        `ChoiceLoader`

3

▼


Try multiple loaders in order, returning the first match.

Useful for theme fallback patterns where…










Try multiple loaders in order, returning the first match.


Useful for theme fallback patterns where a custom theme overrides
    a subset of templates and the default theme provides the rest.


Search Order:
    Loaders are tried in order. First successful`get_source()`wins:
`python     loader = ChoiceLoader([         FileSystemLoader("themes/custom/"),         FileSystemLoader("themes/default/"),     ])     # Looks in custom/ first, then default/     `






#### Methods

















        `get_source`

1


          `tuple[str, str | None]`


▼


Try each loader in order, return first match.









      `def get_source(self, name: str) -> tuple[str, str | None]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, str | None]`















        `list_templates`

0


          `list[str]`


▼


Merge template lists from all loaders (deduplicated, sorted).









      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      1

    ▼













        `__init__`

1

▼










      `def __init__(self, loaders: list[FileSystemLoader | DictLoader | ChoiceLoader | PrefixLoader | PackageLoader | FunctionLoader])`




##### Parameters




        Name
        Type
        Description





        `loaders`
`—`































        `PrefixLoader`

3

▼


Namespace templates by prefix, delegating to per-prefix loaders.

Template names are split on a del…










Namespace templates by prefix, delegating to per-prefix loaders.


Template names are split on a delimiter (default`/`) and the first
segment is used to select the appropriate loader. This enables plugin
and theme architectures where different template sources are isolated
by namespace.






#### Methods

















        `get_source`

1


          `tuple[str, str | None]`


▼


Split name on delimiter, look up prefix, delegate to loader.









      `def get_source(self, name: str) -> tuple[str, str | None]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, str | None]`















        `list_templates`

0


          `list[str]`


▼


List all templates across all prefixes, with prefix prepended.









      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      1

    ▼













        `__init__`

2

▼










      `def __init__(self, mapping: dict[str, FileSystemLoader | DictLoader | ChoiceLoader | PrefixLoader | PackageLoader | FunctionLoader], delimiter: str = '/')`




##### Parameters




        Name
        Type
        Description





        `mapping`
`—`






  `delimiter`
`—`


  Default:`'/'`






























        `PackageLoader`

5

▼


Load templates from an installed Python package.

Uses ``importlib.resources`` to locate template f…










Load templates from an installed Python package.


Uses`importlib.resources`to locate template files inside a package's
directory tree. This enables pip-installable packages to ship templates
that are loadable without knowing the installation path.

Use Cases:



- Framework default templates (admin panels, error pages)


- Distributable themes (`pip install my-theme`)

- Plugin/extension templates namespaced by package







#### Methods

















        `get_source`

1


          `tuple[str, str | None]`


▼


Load template source from package resources.









      `def get_source(self, name: str) -> tuple[str, str | None]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, str | None]`















        `list_templates`

0


          `list[str]`


▼


List all templates in the package directory.









      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      3

    ▼













        `__init__`

3

▼










      `def __init__(self, package_name: str, package_path: str = 'templates', encoding: str = 'utf-8')`




##### Parameters




        Name
        Type
        Description





        `package_name`
`—`






  `package_path`
`—`


  Default:`'templates'`





  `encoding`
`—`


  Default:`'utf-8'`




















        `_get_root`

0


          `importlib.resources.abc.…`


▼


Get the traversable root for the template directory.









      `def _get_root(self) -> importlib.resources.abc.Traversable`




##### Returns

      `importlib.resources.abc.Traversable`















        `_walk`

2


          `list[str]`


▼


Recursively walk a traversable, collecting file paths.









      `def _walk(self, traversable: importlib.resources.abc.Traversable, prefix: str) -> list[str]`




##### Parameters




        Name
        Type
        Description





        `traversable`
`—`






  `prefix`
`—`











##### Returns

      `list[str]`

























        `FunctionLoader`

3

▼


Wrap a callable as a template loader.

The simplest way to create a custom loader. Pass a function …










Wrap a callable as a template loader.


The simplest way to create a custom loader. Pass a function that takes
    a template name and returns the source (or`None`if not found).

The function can return either:



- `str`: Template source (filename will be `"<function>"`).

- `tuple[str, str | None]`: `(source, filename)`for custom

```
filenames in error messages.
```


- `None`: Template not found (raises `TemplateNotFoundError`).


Use with tuple return for better error messages:


```
>>> def load(name):
```

```
... source = my_cms.get_template(name)
... if source:
... return source, f"cms://{name}"
... return None
>>> env = Environment(loader=FunctionLoader(load))
```






#### Methods

















        `get_source`

1


          `tuple[str, str | None]`


▼


Call the load function and normalize the result.









      `def get_source(self, name: str) -> tuple[str, str | None]`




##### Parameters




        Name
        Type
        Description





        `name`
`—`











##### Returns

      `tuple[str, str | None]`















        `list_templates`

0


          `list[str]`


▼


FunctionLoader cannot enumerate templates.









      `def list_templates(self) -> list[str]`




##### Returns

      `list[str]`











      Internal Methods
      1

    ▼













        `__init__`

1

▼










      `def __init__(self, load_func: Callable[[str], str | tuple[str, str | None] | None])`




##### Parameters




        Name
        Type
        Description





        `load_func`
`—`
