Skip to content

Commit d8c37f4

Browse files
authored
Merge pull request #4026 from greyli/improve-type-hints
Improve type hints for send_file and send_from_directory
2 parents 6414df9 + d5aadba commit d8c37f4

File tree

3 files changed

+32
-22
lines changed

3 files changed

+32
-22
lines changed

CHANGES.rst

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Unreleased
1313
- Fix type annotation for ``g`` and inform mypy that it is a namespace
1414
object that has arbitrary attributes. :issue:`4020`
1515
- Fix some types that weren't available in Python 3.6.0. :issue:`4040`
16+
- Improve typing for ``send_file``, ``send_from_directory``, and
17+
``get_send_file_max_age``. :issue:`4044`, :pr:`4026`
1618

1719

1820
Version 2.0.0

src/flask/helpers.py

+29-21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import sys
55
import typing as t
66
import warnings
7+
from datetime import datetime
78
from datetime import timedelta
89
from functools import update_wrapper
910
from threading import RLock
@@ -436,14 +437,16 @@ def get_flashed_messages(
436437

437438

438439
def _prepare_send_file_kwargs(
439-
download_name=None,
440-
attachment_filename=None,
441-
etag=None,
442-
add_etags=None,
443-
max_age=None,
444-
cache_timeout=None,
445-
**kwargs,
446-
):
440+
download_name: t.Optional[str] = None,
441+
attachment_filename: t.Optional[str] = None,
442+
etag: t.Optional[t.Union[bool, str]] = None,
443+
add_etags: t.Optional[t.Union[bool]] = None,
444+
max_age: t.Optional[
445+
t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]]
446+
] = None,
447+
cache_timeout: t.Optional[int] = None,
448+
**kwargs: t.Any,
449+
) -> t.Dict[str, t.Any]:
447450
if attachment_filename is not None:
448451
warnings.warn(
449452
"The 'attachment_filename' parameter has been renamed to"
@@ -482,23 +485,25 @@ def _prepare_send_file_kwargs(
482485
max_age=max_age,
483486
use_x_sendfile=current_app.use_x_sendfile,
484487
response_class=current_app.response_class,
485-
_root_path=current_app.root_path,
488+
_root_path=current_app.root_path, # type: ignore
486489
)
487490
return kwargs
488491

489492

490493
def send_file(
491-
path_or_file,
492-
mimetype=None,
493-
as_attachment=False,
494-
download_name=None,
495-
attachment_filename=None,
496-
conditional=True,
497-
etag=True,
498-
add_etags=None,
499-
last_modified=None,
500-
max_age=None,
501-
cache_timeout=None,
494+
path_or_file: t.Union[os.PathLike, str, t.BinaryIO],
495+
mimetype: t.Optional[str] = None,
496+
as_attachment: bool = False,
497+
download_name: t.Optional[str] = None,
498+
attachment_filename: t.Optional[str] = None,
499+
conditional: bool = True,
500+
etag: t.Union[bool, str] = True,
501+
add_etags: t.Optional[bool] = None,
502+
last_modified: t.Optional[t.Union[datetime, int, float]] = None,
503+
max_age: t.Optional[
504+
t.Union[int, t.Callable[[t.Optional[str]], t.Optional[int]]]
505+
] = None,
506+
cache_timeout: t.Optional[int] = None,
502507
):
503508
"""Send the contents of a file to the client.
504509
@@ -643,7 +648,10 @@ def safe_join(directory: str, *pathnames: str) -> str:
643648

644649

645650
def send_from_directory(
646-
directory: str, path: str, filename: t.Optional[str] = None, **kwargs: t.Any
651+
directory: t.Union[os.PathLike, str],
652+
path: t.Union[os.PathLike, str],
653+
filename: t.Optional[str] = None,
654+
**kwargs: t.Any,
647655
) -> "Response":
648656
"""Send a file from within a directory using :func:`send_file`.
649657

src/flask/scaffold.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def static_url_path(self, value: t.Optional[str]) -> None:
288288

289289
self._static_url_path = value
290290

291-
def get_send_file_max_age(self, filename: str) -> t.Optional[int]:
291+
def get_send_file_max_age(self, filename: t.Optional[str]) -> t.Optional[int]:
292292
"""Used by :func:`send_file` to determine the ``max_age`` cache
293293
value for a given file path if it wasn't passed.
294294

0 commit comments

Comments
 (0)