blueprints.py 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from __future__ import annotations
  2. import os
  3. import typing as t
  4. from datetime import timedelta
  5. from .globals import current_app
  6. from .helpers import send_from_directory
  7. from .sansio.blueprints import Blueprint as SansioBlueprint
  8. from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa
  9. if t.TYPE_CHECKING: # pragma: no cover
  10. from .wrappers import Response
  11. class Blueprint(SansioBlueprint):
  12. def get_send_file_max_age(self, filename: str | None) -> int | None:
  13. """Used by :func:`send_file` to determine the ``max_age`` cache
  14. value for a given file path if it wasn't passed.
  15. By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from
  16. the configuration of :data:`~flask.current_app`. This defaults
  17. to ``None``, which tells the browser to use conditional requests
  18. instead of a timed cache, which is usually preferable.
  19. Note this is a duplicate of the same method in the Flask
  20. class.
  21. .. versionchanged:: 2.0
  22. The default configuration is ``None`` instead of 12 hours.
  23. .. versionadded:: 0.9
  24. """
  25. value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"]
  26. if value is None:
  27. return None
  28. if isinstance(value, timedelta):
  29. return int(value.total_seconds())
  30. return value
  31. def send_static_file(self, filename: str) -> Response:
  32. """The view function used to serve files from
  33. :attr:`static_folder`. A route is automatically registered for
  34. this view at :attr:`static_url_path` if :attr:`static_folder` is
  35. set.
  36. Note this is a duplicate of the same method in the Flask
  37. class.
  38. .. versionadded:: 0.5
  39. """
  40. if not self.has_static_folder:
  41. raise RuntimeError("'static_folder' must be set to serve static_files.")
  42. # send_file only knows to call get_send_file_max_age on the app,
  43. # call it here so it works for blueprints too.
  44. max_age = self.get_send_file_max_age(filename)
  45. return send_from_directory(
  46. t.cast(str, self.static_folder), filename, max_age=max_age
  47. )
  48. def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]:
  49. """Open a resource file relative to :attr:`root_path` for
  50. reading.
  51. For example, if the file ``schema.sql`` is next to the file
  52. ``app.py`` where the ``Flask`` app is defined, it can be opened
  53. with:
  54. .. code-block:: python
  55. with app.open_resource("schema.sql") as f:
  56. conn.executescript(f.read())
  57. :param resource: Path to the resource relative to
  58. :attr:`root_path`.
  59. :param mode: Open the file in this mode. Only reading is
  60. supported, valid values are "r" (or "rt") and "rb".
  61. Note this is a duplicate of the same method in the Flask
  62. class.
  63. """
  64. if mode not in {"r", "rt", "rb"}:
  65. raise ValueError("Resources can only be opened for reading.")
  66. return open(os.path.join(self.root_path, resource), mode)