Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/flask/blueprints.py: 44%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

34 statements  

1from __future__ import annotations 

2 

3import os 

4import typing as t 

5from datetime import timedelta 

6 

7from .cli import AppGroup 

8from .globals import current_app 

9from .helpers import send_from_directory 

10from .sansio.blueprints import Blueprint as SansioBlueprint 

11from .sansio.blueprints import BlueprintSetupState as BlueprintSetupState # noqa 

12from .sansio.scaffold import _sentinel 

13 

14if t.TYPE_CHECKING: # pragma: no cover 

15 from .wrappers import Response 

16 

17 

18class Blueprint(SansioBlueprint): 

19 def __init__( 

20 self, 

21 name: str, 

22 import_name: str, 

23 static_folder: str | os.PathLike[str] | None = None, 

24 static_url_path: str | None = None, 

25 template_folder: str | os.PathLike[str] | None = None, 

26 url_prefix: str | None = None, 

27 subdomain: str | None = None, 

28 url_defaults: dict[str, t.Any] | None = None, 

29 root_path: str | None = None, 

30 cli_group: str | None = _sentinel, # type: ignore 

31 ) -> None: 

32 super().__init__( 

33 name, 

34 import_name, 

35 static_folder, 

36 static_url_path, 

37 template_folder, 

38 url_prefix, 

39 subdomain, 

40 url_defaults, 

41 root_path, 

42 cli_group, 

43 ) 

44 

45 #: The Click command group for registering CLI commands for this 

46 #: object. The commands are available from the ``flask`` command 

47 #: once the application has been discovered and blueprints have 

48 #: been registered. 

49 self.cli = AppGroup() 

50 

51 # Set the name of the Click group in case someone wants to add 

52 # the app's commands to another CLI tool. 

53 self.cli.name = self.name 

54 

55 def get_send_file_max_age(self, filename: str | None) -> int | None: 

56 """Used by :func:`send_file` to determine the ``max_age`` cache 

57 value for a given file path if it wasn't passed. 

58 

59 By default, this returns :data:`SEND_FILE_MAX_AGE_DEFAULT` from 

60 the configuration of :data:`~flask.current_app`. This defaults 

61 to ``None``, which tells the browser to use conditional requests 

62 instead of a timed cache, which is usually preferable. 

63 

64 Note this is a duplicate of the same method in the Flask 

65 class. 

66 

67 .. versionchanged:: 2.0 

68 The default configuration is ``None`` instead of 12 hours. 

69 

70 .. versionadded:: 0.9 

71 """ 

72 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] 

73 

74 if value is None: 

75 return None 

76 

77 if isinstance(value, timedelta): 

78 return int(value.total_seconds()) 

79 

80 return value # type: ignore[no-any-return] 

81 

82 def send_static_file(self, filename: str) -> Response: 

83 """The view function used to serve files from 

84 :attr:`static_folder`. A route is automatically registered for 

85 this view at :attr:`static_url_path` if :attr:`static_folder` is 

86 set. 

87 

88 Note this is a duplicate of the same method in the Flask 

89 class. 

90 

91 .. versionadded:: 0.5 

92 

93 """ 

94 if not self.has_static_folder: 

95 raise RuntimeError("'static_folder' must be set to serve static_files.") 

96 

97 # send_file only knows to call get_send_file_max_age on the app, 

98 # call it here so it works for blueprints too. 

99 max_age = self.get_send_file_max_age(filename) 

100 return send_from_directory( 

101 t.cast(str, self.static_folder), filename, max_age=max_age 

102 ) 

103 

104 def open_resource( 

105 self, resource: str, mode: str = "rb", encoding: str | None = "utf-8" 

106 ) -> t.IO[t.AnyStr]: 

107 """Open a resource file relative to :attr:`root_path` for reading. The 

108 blueprint-relative equivalent of the app's :meth:`~.Flask.open_resource` 

109 method. 

110 

111 :param resource: Path to the resource relative to :attr:`root_path`. 

112 :param mode: Open the file in this mode. Only reading is supported, 

113 valid values are ``"r"`` (or ``"rt"``) and ``"rb"``. 

114 :param encoding: Open the file with this encoding when opening in text 

115 mode. This is ignored when opening in binary mode. 

116 

117 .. versionchanged:: 3.1 

118 Added the ``encoding`` parameter. 

119 """ 

120 if mode not in {"r", "rt", "rb"}: 

121 raise ValueError("Resources can only be opened for reading.") 

122 

123 path = os.path.join(self.root_path, resource) 

124 

125 if mode == "rb": 

126 return open(path, mode) # pyright: ignore 

127 

128 return open(path, mode, encoding=encoding)