Skip to content

Commit bcdf0ad

Browse files
fix IndexError in TemplateResponse (encode#2909)
1 parent c8a4692 commit bcdf0ad

File tree

2 files changed

+124
-3
lines changed

2 files changed

+124
-3
lines changed

starlette/templating.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ def TemplateResponse(self, *args: typing.Any, **kwargs: typing.Any) -> _Template
168168
name = args[0]
169169
context = args[1] if len(args) > 1 else kwargs.get("context", {})
170170
status_code = args[2] if len(args) > 2 else kwargs.get("status_code", 200)
171-
headers = args[2] if len(args) > 2 else kwargs.get("headers")
172-
media_type = args[3] if len(args) > 3 else kwargs.get("media_type")
173-
background = args[4] if len(args) > 4 else kwargs.get("background")
171+
headers = args[3] if len(args) > 3 else kwargs.get("headers")
172+
media_type = args[4] if len(args) > 4 else kwargs.get("media_type")
173+
background = args[5] if len(args) > 5 else kwargs.get("background")
174174

175175
if "request" not in context:
176176
raise ValueError('context must include a "request" key')

tests/test_templates.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,127 @@ def page(request: Request) -> Response:
279279
spy.assert_called()
280280

281281

282+
class TestTemplatesArgsOnly:
283+
# MAINTAINERS: remove after 1.0
284+
def test_name_and_context(self, tmpdir: Path, test_client_factory: TestClientFactory) -> None:
285+
path = os.path.join(tmpdir, "index.html")
286+
with open(path, "w") as file:
287+
file.write("value: {{ a }}")
288+
templates = Jinja2Templates(directory=str(tmpdir))
289+
290+
def page(request: Request) -> Response:
291+
return templates.TemplateResponse(
292+
"index.html",
293+
{"a": "b", "request": request},
294+
)
295+
296+
app = Starlette(routes=[Route("/", page)])
297+
client = test_client_factory(app)
298+
with pytest.warns(DeprecationWarning):
299+
response = client.get("/")
300+
301+
assert response.text == "value: b" # context was rendered
302+
assert response.status_code == 200
303+
304+
def test_status_code(self, tmpdir: Path, test_client_factory: TestClientFactory) -> None:
305+
path = os.path.join(tmpdir, "index.html")
306+
with open(path, "w") as file:
307+
file.write("value: {{ a }}")
308+
templates = Jinja2Templates(directory=str(tmpdir))
309+
310+
def page(request: Request) -> Response:
311+
return templates.TemplateResponse(
312+
"index.html",
313+
{"a": "b", "request": request},
314+
201,
315+
)
316+
317+
app = Starlette(routes=[Route("/", page)])
318+
client = test_client_factory(app)
319+
with pytest.warns(DeprecationWarning):
320+
response = client.get("/")
321+
322+
assert response.text == "value: b" # context was rendered
323+
assert response.status_code == 201
324+
325+
def test_headers(self, tmpdir: Path, test_client_factory: TestClientFactory) -> None:
326+
path = os.path.join(tmpdir, "index.html")
327+
with open(path, "w") as file:
328+
file.write("value: {{ a }}")
329+
templates = Jinja2Templates(directory=str(tmpdir))
330+
331+
def page(request: Request) -> Response:
332+
return templates.TemplateResponse(
333+
"index.html",
334+
{"a": "b", "request": request},
335+
201,
336+
{"x-key": "value"},
337+
)
338+
339+
app = Starlette(routes=[Route("/", page)])
340+
client = test_client_factory(app)
341+
with pytest.warns(DeprecationWarning):
342+
response = client.get("/")
343+
344+
assert response.text == "value: b" # context was rendered
345+
assert response.status_code == 201
346+
assert response.headers["x-key"] == "value"
347+
348+
def test_media_type(self, tmpdir: Path, test_client_factory: TestClientFactory) -> None:
349+
path = os.path.join(tmpdir, "index.html")
350+
with open(path, "w") as file:
351+
file.write("value: {{ a }}")
352+
templates = Jinja2Templates(directory=str(tmpdir))
353+
354+
def page(request: Request) -> Response:
355+
return templates.TemplateResponse(
356+
"index.html",
357+
{"a": "b", "request": request},
358+
201,
359+
{"x-key": "value"},
360+
"text/plain",
361+
)
362+
363+
app = Starlette(routes=[Route("/", page)])
364+
client = test_client_factory(app)
365+
with pytest.warns(DeprecationWarning):
366+
response = client.get("/")
367+
368+
assert response.text == "value: b" # context was rendered
369+
assert response.status_code == 201
370+
assert response.headers["x-key"] == "value"
371+
assert response.headers["content-type"] == "text/plain; charset=utf-8"
372+
373+
def test_all_args(self, tmpdir: Path, test_client_factory: TestClientFactory) -> None:
374+
path = os.path.join(tmpdir, "index.html")
375+
with open(path, "w") as file:
376+
file.write("value: {{ a }}")
377+
templates = Jinja2Templates(directory=str(tmpdir))
378+
379+
spy = mock.MagicMock()
380+
381+
def page(request: Request) -> Response:
382+
return templates.TemplateResponse(
383+
"index.html",
384+
{"a": "b", "request": request},
385+
201,
386+
{"x-key": "value"},
387+
"text/plain",
388+
BackgroundTask(func=spy),
389+
)
390+
391+
app = Starlette(routes=[Route("/", page)])
392+
client = test_client_factory(app)
393+
with pytest.warns(DeprecationWarning):
394+
response = client.get("/")
395+
396+
assert response.text == "value: b" # context was rendered
397+
assert response.status_code == 201
398+
assert response.headers["x-key"] == "value"
399+
assert response.headers["content-type"] == "text/plain; charset=utf-8"
400+
spy.assert_called()
401+
402+
282403
def test_templates_when_first_argument_is_request(tmpdir: Path, test_client_factory: TestClientFactory) -> None:
283404
# MAINTAINERS: remove after 1.0
284405
path = os.path.join(tmpdir, "index.html")

0 commit comments

Comments
 (0)