Skip to content

Commit

Permalink
Remove env_options parameter from Jinja2Templates
Browse files Browse the repository at this point in the history
  • Loading branch information
Kludex committed Jan 11, 2024
1 parent 2fac3d1 commit 2b5225b
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 71 deletions.
25 changes: 4 additions & 21 deletions docs/templates.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ Jinja2 provides an excellent choice.

### Jinja2Templates

Signature: `Jinja2Templates(directory, context_processors=None, **env_options)`
Signature: `Jinja2Templates(directory, context_processors=None, env=None)`

* `directory` - A string, [os.Pathlike][pathlike] or a list of strings or [os.Pathlike][pathlike] denoting a directory path.
* `context_processors` - A list of functions that return a dictionary to add to the template context.
* `**env_options` - Additional keyword arguments to pass to the Jinja2 environment.
* `env` - A preconfigured [`jinja2.Environment`](https://jinja.palletsprojects.com/en/3.0.x/api/#api) instance.

Starlette provides a simple way to get `jinja2` configured. This is probably
what you want to use by default.
Expand Down Expand Up @@ -58,11 +58,9 @@ templates = Jinja2Templates(directory='templates')
templates.env.filters['marked'] = marked_filter
```

## Using custom `jinja2.Environment` instance

## Using custom jinja2.Environment instance

Starlette also accepts a preconfigured [`jinja2.Environment`](https://jinja.palletsprojects.com/en/3.0.x/api/#api) instance.

Starlette accepts a preconfigured [`jinja2.Environment`](https://jinja.palletsprojects.com/en/3.0.x/api/#api) instance.

```python
import jinja2
Expand All @@ -72,7 +70,6 @@ env = jinja2.Environment(...)
templates = Jinja2Templates(env=env)
```


## Context processors

A context processor is a function that returns a dictionary to be merged into a template context.
Expand Down Expand Up @@ -126,20 +123,6 @@ def test_homepage():
assert "request" in response.context
```

## Customizing Jinja2 Environment

`Jinja2Templates` accepts all options supported by Jinja2 `Environment`.
This will allow more control over the `Environment` instance created by Starlette.

For the list of options available to `Environment` you can check Jinja2 documentation [here](https://jinja.palletsprojects.com/en/3.0.x/api/#jinja2.Environment)

```python
from starlette.templating import Jinja2Templates


templates = Jinja2Templates(directory='templates', autoescape=False, auto_reload=True)
```

## Asynchronous template rendering

Jinja2 supports async template rendering, however as a general rule
Expand Down
50 changes: 6 additions & 44 deletions starlette/templating.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import typing
import warnings
from os import PathLike

from starlette.background import BackgroundTask
Expand All @@ -20,7 +19,11 @@
else: # pragma: nocover
pass_context = jinja2.contextfunction # type: ignore[attr-defined]
except ModuleNotFoundError: # pragma: nocover
jinja2 = None # type: ignore[assignment]
raise RuntimeError(
"The starlette.templating module requires the `jinja2` package to be installed."
"\nYou can install this with:\n"
" $ pip install jinja2\n"
)


class _TemplateResponse(HTMLResponse):
Expand Down Expand Up @@ -61,29 +64,6 @@ class Jinja2Templates:
return templates.TemplateResponse("index.html", {"request": request})
"""

@typing.overload
def __init__(
self,
directory: "typing.Union[str, PathLike[typing.AnyStr], typing.Sequence[typing.Union[str, PathLike[typing.AnyStr]]]]", # noqa: E501
*,
context_processors: typing.Optional[
typing.List[typing.Callable[[Request], typing.Dict[str, typing.Any]]]
] = None,
**env_options: typing.Any,
) -> None:
...

@typing.overload
def __init__(
self,
*,
env: "jinja2.Environment",
context_processors: typing.Optional[
typing.List[typing.Callable[[Request], typing.Dict[str, typing.Any]]]
] = None,
) -> None:
...

def __init__(
self,
directory: "typing.Union[str, PathLike[typing.AnyStr], typing.Sequence[typing.Union[str, PathLike[typing.AnyStr]]], None]" = None, # noqa: E501
Expand All @@ -92,34 +72,16 @@ def __init__(
typing.List[typing.Callable[[Request], typing.Dict[str, typing.Any]]]
] = None,
env: typing.Optional["jinja2.Environment"] = None,
**env_options: typing.Any,
) -> None:
if env_options:
warnings.warn(
"Extra environment options are deprecated. Use a preconfigured jinja2.Environment instead.", # noqa: E501
DeprecationWarning,
)
assert jinja2 is not None, "jinja2 must be installed to use Jinja2Templates"
assert directory or env, "either 'directory' or 'env' arguments must be passed"
self.context_processors = context_processors or []
if directory is not None:
self.env = self._create_env(directory, **env_options)
self.env = jinja2.Environment(loader=jinja2.FileSystemLoader(directory))
elif env is not None:
self.env = env

self._setup_env_defaults(self.env)

def _create_env(
self,
directory: "typing.Union[str, PathLike[typing.AnyStr], typing.Sequence[typing.Union[str, PathLike[typing.AnyStr]]]]", # noqa: E501
**env_options: typing.Any,
) -> "jinja2.Environment":
loader = jinja2.FileSystemLoader(directory)
env_options.setdefault("loader", loader)
env_options.setdefault("autoescape", True)

return jinja2.Environment(**env_options)

def _setup_env_defaults(self, env: "jinja2.Environment") -> None:
@pass_context
def url_for(
Expand Down
7 changes: 1 addition & 6 deletions tests/test_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def test_templates_require_directory_or_environment():
with pytest.raises(
AssertionError, match="either 'directory' or 'env' arguments must be passed"
):
Jinja2Templates() # type: ignore[call-overload]
Jinja2Templates()


def test_templates_with_directory(tmpdir):
Expand Down Expand Up @@ -161,11 +161,6 @@ async def homepage(request):
assert set(response.context.keys()) == {"request"}


def test_templates_with_environment_options_emit_warning(tmpdir):
with pytest.warns(DeprecationWarning):
Jinja2Templates(str(tmpdir), autoescape=True)


def test_templates_with_kwargs_only(tmpdir, test_client_factory):
# MAINTAINERS: remove after 1.0
path = os.path.join(tmpdir, "index.html")
Expand Down

0 comments on commit 2b5225b

Please sign in to comment.