Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/flask/app.py: 25%

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

390 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import os 

5import sys 

6import typing as t 

7import weakref 

8from datetime import timedelta 

9from inspect import iscoroutinefunction 

10from itertools import chain 

11from types import TracebackType 

12from urllib.parse import quote as _url_quote 

13 

14import click 

15from werkzeug.datastructures import Headers 

16from werkzeug.datastructures import ImmutableDict 

17from werkzeug.exceptions import BadRequestKeyError 

18from werkzeug.exceptions import HTTPException 

19from werkzeug.exceptions import InternalServerError 

20from werkzeug.routing import BuildError 

21from werkzeug.routing import MapAdapter 

22from werkzeug.routing import RequestRedirect 

23from werkzeug.routing import RoutingException 

24from werkzeug.routing import Rule 

25from werkzeug.serving import is_running_from_reloader 

26from werkzeug.wrappers import Response as BaseResponse 

27 

28from . import cli 

29from . import typing as ft 

30from .ctx import AppContext 

31from .ctx import RequestContext 

32from .globals import _cv_app 

33from .globals import _cv_request 

34from .globals import current_app 

35from .globals import g 

36from .globals import request 

37from .globals import request_ctx 

38from .globals import session 

39from .helpers import get_debug_flag 

40from .helpers import get_flashed_messages 

41from .helpers import get_load_dotenv 

42from .helpers import send_from_directory 

43from .sansio.app import App 

44from .sansio.scaffold import _sentinel 

45from .sessions import SecureCookieSessionInterface 

46from .sessions import SessionInterface 

47from .signals import appcontext_tearing_down 

48from .signals import got_request_exception 

49from .signals import request_finished 

50from .signals import request_started 

51from .signals import request_tearing_down 

52from .templating import Environment 

53from .wrappers import Request 

54from .wrappers import Response 

55 

56if t.TYPE_CHECKING: # pragma: no cover 

57 from _typeshed.wsgi import StartResponse 

58 from _typeshed.wsgi import WSGIEnvironment 

59 

60 from .testing import FlaskClient 

61 from .testing import FlaskCliRunner 

62 

63T_shell_context_processor = t.TypeVar( 

64 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable 

65) 

66T_teardown = t.TypeVar("T_teardown", bound=ft.TeardownCallable) 

67T_template_filter = t.TypeVar("T_template_filter", bound=ft.TemplateFilterCallable) 

68T_template_global = t.TypeVar("T_template_global", bound=ft.TemplateGlobalCallable) 

69T_template_test = t.TypeVar("T_template_test", bound=ft.TemplateTestCallable) 

70 

71 

72def _make_timedelta(value: timedelta | int | None) -> timedelta | None: 

73 if value is None or isinstance(value, timedelta): 

74 return value 

75 

76 return timedelta(seconds=value) 

77 

78 

79class Flask(App): 

80 """The flask object implements a WSGI application and acts as the central 

81 object. It is passed the name of the module or package of the 

82 application. Once it is created it will act as a central registry for 

83 the view functions, the URL rules, template configuration and much more. 

84 

85 The name of the package is used to resolve resources from inside the 

86 package or the folder the module is contained in depending on if the 

87 package parameter resolves to an actual python package (a folder with 

88 an :file:`__init__.py` file inside) or a standard module (just a ``.py`` file). 

89 

90 For more information about resource loading, see :func:`open_resource`. 

91 

92 Usually you create a :class:`Flask` instance in your main module or 

93 in the :file:`__init__.py` file of your package like this:: 

94 

95 from flask import Flask 

96 app = Flask(__name__) 

97 

98 .. admonition:: About the First Parameter 

99 

100 The idea of the first parameter is to give Flask an idea of what 

101 belongs to your application. This name is used to find resources 

102 on the filesystem, can be used by extensions to improve debugging 

103 information and a lot more. 

104 

105 So it's important what you provide there. If you are using a single 

106 module, `__name__` is always the correct value. If you however are 

107 using a package, it's usually recommended to hardcode the name of 

108 your package there. 

109 

110 For example if your application is defined in :file:`yourapplication/app.py` 

111 you should create it with one of the two versions below:: 

112 

113 app = Flask('yourapplication') 

114 app = Flask(__name__.split('.')[0]) 

115 

116 Why is that? The application will work even with `__name__`, thanks 

117 to how resources are looked up. However it will make debugging more 

118 painful. Certain extensions can make assumptions based on the 

119 import name of your application. For example the Flask-SQLAlchemy 

120 extension will look for the code in your application that triggered 

121 an SQL query in debug mode. If the import name is not properly set 

122 up, that debugging information is lost. (For example it would only 

123 pick up SQL queries in `yourapplication.app` and not 

124 `yourapplication.views.frontend`) 

125 

126 .. versionadded:: 0.7 

127 The `static_url_path`, `static_folder`, and `template_folder` 

128 parameters were added. 

129 

130 .. versionadded:: 0.8 

131 The `instance_path` and `instance_relative_config` parameters were 

132 added. 

133 

134 .. versionadded:: 0.11 

135 The `root_path` parameter was added. 

136 

137 .. versionadded:: 1.0 

138 The ``host_matching`` and ``static_host`` parameters were added. 

139 

140 .. versionadded:: 1.0 

141 The ``subdomain_matching`` parameter was added. Subdomain 

142 matching needs to be enabled manually now. Setting 

143 :data:`SERVER_NAME` does not implicitly enable it. 

144 

145 :param import_name: the name of the application package 

146 :param static_url_path: can be used to specify a different path for the 

147 static files on the web. Defaults to the name 

148 of the `static_folder` folder. 

149 :param static_folder: The folder with static files that is served at 

150 ``static_url_path``. Relative to the application ``root_path`` 

151 or an absolute path. Defaults to ``'static'``. 

152 :param static_host: the host to use when adding the static route. 

153 Defaults to None. Required when using ``host_matching=True`` 

154 with a ``static_folder`` configured. 

155 :param host_matching: set ``url_map.host_matching`` attribute. 

156 Defaults to False. 

157 :param subdomain_matching: consider the subdomain relative to 

158 :data:`SERVER_NAME` when matching routes. Defaults to False. 

159 :param template_folder: the folder that contains the templates that should 

160 be used by the application. Defaults to 

161 ``'templates'`` folder in the root path of the 

162 application. 

163 :param instance_path: An alternative instance path for the application. 

164 By default the folder ``'instance'`` next to the 

165 package or module is assumed to be the instance 

166 path. 

167 :param instance_relative_config: if set to ``True`` relative filenames 

168 for loading the config are assumed to 

169 be relative to the instance path instead 

170 of the application root. 

171 :param root_path: The path to the root of the application files. 

172 This should only be set manually when it can't be detected 

173 automatically, such as for namespace packages. 

174 """ 

175 

176 default_config = ImmutableDict( 

177 { 

178 "DEBUG": None, 

179 "TESTING": False, 

180 "PROPAGATE_EXCEPTIONS": None, 

181 "SECRET_KEY": None, 

182 "PERMANENT_SESSION_LIFETIME": timedelta(days=31), 

183 "USE_X_SENDFILE": False, 

184 "SERVER_NAME": None, 

185 "APPLICATION_ROOT": "/", 

186 "SESSION_COOKIE_NAME": "session", 

187 "SESSION_COOKIE_DOMAIN": None, 

188 "SESSION_COOKIE_PATH": None, 

189 "SESSION_COOKIE_HTTPONLY": True, 

190 "SESSION_COOKIE_SECURE": False, 

191 "SESSION_COOKIE_SAMESITE": None, 

192 "SESSION_REFRESH_EACH_REQUEST": True, 

193 "MAX_CONTENT_LENGTH": None, 

194 "SEND_FILE_MAX_AGE_DEFAULT": None, 

195 "TRAP_BAD_REQUEST_ERRORS": None, 

196 "TRAP_HTTP_EXCEPTIONS": False, 

197 "EXPLAIN_TEMPLATE_LOADING": False, 

198 "PREFERRED_URL_SCHEME": "http", 

199 "TEMPLATES_AUTO_RELOAD": None, 

200 "MAX_COOKIE_SIZE": 4093, 

201 } 

202 ) 

203 

204 #: The class that is used for request objects. See :class:`~flask.Request` 

205 #: for more information. 

206 request_class: type[Request] = Request 

207 

208 #: The class that is used for response objects. See 

209 #: :class:`~flask.Response` for more information. 

210 response_class: type[Response] = Response 

211 

212 #: the session interface to use. By default an instance of 

213 #: :class:`~flask.sessions.SecureCookieSessionInterface` is used here. 

214 #: 

215 #: .. versionadded:: 0.8 

216 session_interface: SessionInterface = SecureCookieSessionInterface() 

217 

218 def __init__( 

219 self, 

220 import_name: str, 

221 static_url_path: str | None = None, 

222 static_folder: str | os.PathLike[str] | None = "static", 

223 static_host: str | None = None, 

224 host_matching: bool = False, 

225 subdomain_matching: bool = False, 

226 template_folder: str | os.PathLike[str] | None = "templates", 

227 instance_path: str | None = None, 

228 instance_relative_config: bool = False, 

229 root_path: str | None = None, 

230 ): 

231 super().__init__( 

232 import_name=import_name, 

233 static_url_path=static_url_path, 

234 static_folder=static_folder, 

235 static_host=static_host, 

236 host_matching=host_matching, 

237 subdomain_matching=subdomain_matching, 

238 template_folder=template_folder, 

239 instance_path=instance_path, 

240 instance_relative_config=instance_relative_config, 

241 root_path=root_path, 

242 ) 

243 

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

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

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

247 #: been registered. 

248 self.cli = cli.AppGroup() 

249 

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

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

252 self.cli.name = self.name 

253 

254 # Add a static route using the provided static_url_path, static_host, 

255 # and static_folder if there is a configured static_folder. 

256 # Note we do this without checking if static_folder exists. 

257 # For one, it might be created while the server is running (e.g. during 

258 # development). Also, Google App Engine stores static files somewhere 

259 if self.has_static_folder: 

260 assert ( 

261 bool(static_host) == host_matching 

262 ), "Invalid static_host/host_matching combination" 

263 # Use a weakref to avoid creating a reference cycle between the app 

264 # and the view function (see #3761). 

265 self_ref = weakref.ref(self) 

266 self.add_url_rule( 

267 f"{self.static_url_path}/<path:filename>", 

268 endpoint="static", 

269 host=static_host, 

270 view_func=lambda **kw: self_ref().send_static_file(**kw), # type: ignore # noqa: B950 

271 ) 

272 

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

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

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

276 

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

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

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

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

281 

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

283 class. 

284 

285 .. versionchanged:: 2.0 

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

287 

288 .. versionadded:: 0.9 

289 """ 

290 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] 

291 

292 if value is None: 

293 return None 

294 

295 if isinstance(value, timedelta): 

296 return int(value.total_seconds()) 

297 

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

299 

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

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

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

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

304 set. 

305 

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

307 class. 

308 

309 .. versionadded:: 0.5 

310 

311 """ 

312 if not self.has_static_folder: 

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

314 

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

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

317 max_age = self.get_send_file_max_age(filename) 

318 return send_from_directory( 

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

320 ) 

321 

322 def open_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: 

323 """Open a resource file relative to :attr:`root_path` for 

324 reading. 

325 

326 For example, if the file ``schema.sql`` is next to the file 

327 ``app.py`` where the ``Flask`` app is defined, it can be opened 

328 with: 

329 

330 .. code-block:: python 

331 

332 with app.open_resource("schema.sql") as f: 

333 conn.executescript(f.read()) 

334 

335 :param resource: Path to the resource relative to 

336 :attr:`root_path`. 

337 :param mode: Open the file in this mode. Only reading is 

338 supported, valid values are "r" (or "rt") and "rb". 

339 

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

341 class. 

342 

343 """ 

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

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

346 

347 return open(os.path.join(self.root_path, resource), mode) 

348 

349 def open_instance_resource(self, resource: str, mode: str = "rb") -> t.IO[t.AnyStr]: 

350 """Opens a resource from the application's instance folder 

351 (:attr:`instance_path`). Otherwise works like 

352 :meth:`open_resource`. Instance resources can also be opened for 

353 writing. 

354 

355 :param resource: the name of the resource. To access resources within 

356 subfolders use forward slashes as separator. 

357 :param mode: resource file opening mode, default is 'rb'. 

358 """ 

359 return open(os.path.join(self.instance_path, resource), mode) 

360 

361 def create_jinja_environment(self) -> Environment: 

362 """Create the Jinja environment based on :attr:`jinja_options` 

363 and the various Jinja-related methods of the app. Changing 

364 :attr:`jinja_options` after this will have no effect. Also adds 

365 Flask-related globals and filters to the environment. 

366 

367 .. versionchanged:: 0.11 

368 ``Environment.auto_reload`` set in accordance with 

369 ``TEMPLATES_AUTO_RELOAD`` configuration option. 

370 

371 .. versionadded:: 0.5 

372 """ 

373 options = dict(self.jinja_options) 

374 

375 if "autoescape" not in options: 

376 options["autoescape"] = self.select_jinja_autoescape 

377 

378 if "auto_reload" not in options: 

379 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] 

380 

381 if auto_reload is None: 

382 auto_reload = self.debug 

383 

384 options["auto_reload"] = auto_reload 

385 

386 rv = self.jinja_environment(self, **options) 

387 rv.globals.update( 

388 url_for=self.url_for, 

389 get_flashed_messages=get_flashed_messages, 

390 config=self.config, 

391 # request, session and g are normally added with the 

392 # context processor for efficiency reasons but for imported 

393 # templates we also want the proxies in there. 

394 request=request, 

395 session=session, 

396 g=g, 

397 ) 

398 rv.policies["json.dumps_function"] = self.json.dumps 

399 return rv 

400 

401 def create_url_adapter(self, request: Request | None) -> MapAdapter | None: 

402 """Creates a URL adapter for the given request. The URL adapter 

403 is created at a point where the request context is not yet set 

404 up so the request is passed explicitly. 

405 

406 .. versionadded:: 0.6 

407 

408 .. versionchanged:: 0.9 

409 This can now also be called without a request object when the 

410 URL adapter is created for the application context. 

411 

412 .. versionchanged:: 1.0 

413 :data:`SERVER_NAME` no longer implicitly enables subdomain 

414 matching. Use :attr:`subdomain_matching` instead. 

415 """ 

416 if request is not None: 

417 # If subdomain matching is disabled (the default), use the 

418 # default subdomain in all cases. This should be the default 

419 # in Werkzeug but it currently does not have that feature. 

420 if not self.subdomain_matching: 

421 subdomain = self.url_map.default_subdomain or None 

422 else: 

423 subdomain = None 

424 

425 return self.url_map.bind_to_environ( 

426 request.environ, 

427 server_name=self.config["SERVER_NAME"], 

428 subdomain=subdomain, 

429 ) 

430 # We need at the very least the server name to be set for this 

431 # to work. 

432 if self.config["SERVER_NAME"] is not None: 

433 return self.url_map.bind( 

434 self.config["SERVER_NAME"], 

435 script_name=self.config["APPLICATION_ROOT"], 

436 url_scheme=self.config["PREFERRED_URL_SCHEME"], 

437 ) 

438 

439 return None 

440 

441 def raise_routing_exception(self, request: Request) -> t.NoReturn: 

442 """Intercept routing exceptions and possibly do something else. 

443 

444 In debug mode, intercept a routing redirect and replace it with 

445 an error if the body will be discarded. 

446 

447 With modern Werkzeug this shouldn't occur, since it now uses a 

448 308 status which tells the browser to resend the method and 

449 body. 

450 

451 .. versionchanged:: 2.1 

452 Don't intercept 307 and 308 redirects. 

453 

454 :meta private: 

455 :internal: 

456 """ 

457 if ( 

458 not self.debug 

459 or not isinstance(request.routing_exception, RequestRedirect) 

460 or request.routing_exception.code in {307, 308} 

461 or request.method in {"GET", "HEAD", "OPTIONS"} 

462 ): 

463 raise request.routing_exception # type: ignore[misc] 

464 

465 from .debughelpers import FormDataRoutingRedirect 

466 

467 raise FormDataRoutingRedirect(request) 

468 

469 def update_template_context(self, context: dict[str, t.Any]) -> None: 

470 """Update the template context with some commonly used variables. 

471 This injects request, session, config and g into the template 

472 context as well as everything template context processors want 

473 to inject. Note that the as of Flask 0.6, the original values 

474 in the context will not be overridden if a context processor 

475 decides to return a value with the same key. 

476 

477 :param context: the context as a dictionary that is updated in place 

478 to add extra variables. 

479 """ 

480 names: t.Iterable[str | None] = (None,) 

481 

482 # A template may be rendered outside a request context. 

483 if request: 

484 names = chain(names, reversed(request.blueprints)) 

485 

486 # The values passed to render_template take precedence. Keep a 

487 # copy to re-apply after all context functions. 

488 orig_ctx = context.copy() 

489 

490 for name in names: 

491 if name in self.template_context_processors: 

492 for func in self.template_context_processors[name]: 

493 context.update(self.ensure_sync(func)()) 

494 

495 context.update(orig_ctx) 

496 

497 def make_shell_context(self) -> dict[str, t.Any]: 

498 """Returns the shell context for an interactive shell for this 

499 application. This runs all the registered shell context 

500 processors. 

501 

502 .. versionadded:: 0.11 

503 """ 

504 rv = {"app": self, "g": g} 

505 for processor in self.shell_context_processors: 

506 rv.update(processor()) 

507 return rv 

508 

509 def run( 

510 self, 

511 host: str | None = None, 

512 port: int | None = None, 

513 debug: bool | None = None, 

514 load_dotenv: bool = True, 

515 **options: t.Any, 

516 ) -> None: 

517 """Runs the application on a local development server. 

518 

519 Do not use ``run()`` in a production setting. It is not intended to 

520 meet security and performance requirements for a production server. 

521 Instead, see :doc:`/deploying/index` for WSGI server recommendations. 

522 

523 If the :attr:`debug` flag is set the server will automatically reload 

524 for code changes and show a debugger in case an exception happened. 

525 

526 If you want to run the application in debug mode, but disable the 

527 code execution on the interactive debugger, you can pass 

528 ``use_evalex=False`` as parameter. This will keep the debugger's 

529 traceback screen active, but disable code execution. 

530 

531 It is not recommended to use this function for development with 

532 automatic reloading as this is badly supported. Instead you should 

533 be using the :command:`flask` command line script's ``run`` support. 

534 

535 .. admonition:: Keep in Mind 

536 

537 Flask will suppress any server error with a generic error page 

538 unless it is in debug mode. As such to enable just the 

539 interactive debugger without the code reloading, you have to 

540 invoke :meth:`run` with ``debug=True`` and ``use_reloader=False``. 

541 Setting ``use_debugger`` to ``True`` without being in debug mode 

542 won't catch any exceptions because there won't be any to 

543 catch. 

544 

545 :param host: the hostname to listen on. Set this to ``'0.0.0.0'`` to 

546 have the server available externally as well. Defaults to 

547 ``'127.0.0.1'`` or the host in the ``SERVER_NAME`` config variable 

548 if present. 

549 :param port: the port of the webserver. Defaults to ``5000`` or the 

550 port defined in the ``SERVER_NAME`` config variable if present. 

551 :param debug: if given, enable or disable debug mode. See 

552 :attr:`debug`. 

553 :param load_dotenv: Load the nearest :file:`.env` and :file:`.flaskenv` 

554 files to set environment variables. Will also change the working 

555 directory to the directory containing the first file found. 

556 :param options: the options to be forwarded to the underlying Werkzeug 

557 server. See :func:`werkzeug.serving.run_simple` for more 

558 information. 

559 

560 .. versionchanged:: 1.0 

561 If installed, python-dotenv will be used to load environment 

562 variables from :file:`.env` and :file:`.flaskenv` files. 

563 

564 The :envvar:`FLASK_DEBUG` environment variable will override :attr:`debug`. 

565 

566 Threaded mode is enabled by default. 

567 

568 .. versionchanged:: 0.10 

569 The default port is now picked from the ``SERVER_NAME`` 

570 variable. 

571 """ 

572 # Ignore this call so that it doesn't start another server if 

573 # the 'flask run' command is used. 

574 if os.environ.get("FLASK_RUN_FROM_CLI") == "true": 

575 if not is_running_from_reloader(): 

576 click.secho( 

577 " * Ignoring a call to 'app.run()' that would block" 

578 " the current 'flask' CLI command.\n" 

579 " Only call 'app.run()' in an 'if __name__ ==" 

580 ' "__main__"\' guard.', 

581 fg="red", 

582 ) 

583 

584 return 

585 

586 if get_load_dotenv(load_dotenv): 

587 cli.load_dotenv() 

588 

589 # if set, env var overrides existing value 

590 if "FLASK_DEBUG" in os.environ: 

591 self.debug = get_debug_flag() 

592 

593 # debug passed to method overrides all other sources 

594 if debug is not None: 

595 self.debug = bool(debug) 

596 

597 server_name = self.config.get("SERVER_NAME") 

598 sn_host = sn_port = None 

599 

600 if server_name: 

601 sn_host, _, sn_port = server_name.partition(":") 

602 

603 if not host: 

604 if sn_host: 

605 host = sn_host 

606 else: 

607 host = "127.0.0.1" 

608 

609 if port or port == 0: 

610 port = int(port) 

611 elif sn_port: 

612 port = int(sn_port) 

613 else: 

614 port = 5000 

615 

616 options.setdefault("use_reloader", self.debug) 

617 options.setdefault("use_debugger", self.debug) 

618 options.setdefault("threaded", True) 

619 

620 cli.show_server_banner(self.debug, self.name) 

621 

622 from werkzeug.serving import run_simple 

623 

624 try: 

625 run_simple(t.cast(str, host), port, self, **options) 

626 finally: 

627 # reset the first request information if the development server 

628 # reset normally. This makes it possible to restart the server 

629 # without reloader and that stuff from an interactive shell. 

630 self._got_first_request = False 

631 

632 def test_client(self, use_cookies: bool = True, **kwargs: t.Any) -> FlaskClient: 

633 """Creates a test client for this application. For information 

634 about unit testing head over to :doc:`/testing`. 

635 

636 Note that if you are testing for assertions or exceptions in your 

637 application code, you must set ``app.testing = True`` in order for the 

638 exceptions to propagate to the test client. Otherwise, the exception 

639 will be handled by the application (not visible to the test client) and 

640 the only indication of an AssertionError or other exception will be a 

641 500 status code response to the test client. See the :attr:`testing` 

642 attribute. For example:: 

643 

644 app.testing = True 

645 client = app.test_client() 

646 

647 The test client can be used in a ``with`` block to defer the closing down 

648 of the context until the end of the ``with`` block. This is useful if 

649 you want to access the context locals for testing:: 

650 

651 with app.test_client() as c: 

652 rv = c.get('/?vodka=42') 

653 assert request.args['vodka'] == '42' 

654 

655 Additionally, you may pass optional keyword arguments that will then 

656 be passed to the application's :attr:`test_client_class` constructor. 

657 For example:: 

658 

659 from flask.testing import FlaskClient 

660 

661 class CustomClient(FlaskClient): 

662 def __init__(self, *args, **kwargs): 

663 self._authentication = kwargs.pop("authentication") 

664 super(CustomClient,self).__init__( *args, **kwargs) 

665 

666 app.test_client_class = CustomClient 

667 client = app.test_client(authentication='Basic ....') 

668 

669 See :class:`~flask.testing.FlaskClient` for more information. 

670 

671 .. versionchanged:: 0.4 

672 added support for ``with`` block usage for the client. 

673 

674 .. versionadded:: 0.7 

675 The `use_cookies` parameter was added as well as the ability 

676 to override the client to be used by setting the 

677 :attr:`test_client_class` attribute. 

678 

679 .. versionchanged:: 0.11 

680 Added `**kwargs` to support passing additional keyword arguments to 

681 the constructor of :attr:`test_client_class`. 

682 """ 

683 cls = self.test_client_class 

684 if cls is None: 

685 from .testing import FlaskClient as cls 

686 return cls( # type: ignore 

687 self, self.response_class, use_cookies=use_cookies, **kwargs 

688 ) 

689 

690 def test_cli_runner(self, **kwargs: t.Any) -> FlaskCliRunner: 

691 """Create a CLI runner for testing CLI commands. 

692 See :ref:`testing-cli`. 

693 

694 Returns an instance of :attr:`test_cli_runner_class`, by default 

695 :class:`~flask.testing.FlaskCliRunner`. The Flask app object is 

696 passed as the first argument. 

697 

698 .. versionadded:: 1.0 

699 """ 

700 cls = self.test_cli_runner_class 

701 

702 if cls is None: 

703 from .testing import FlaskCliRunner as cls 

704 

705 return cls(self, **kwargs) # type: ignore 

706 

707 def handle_http_exception( 

708 self, e: HTTPException 

709 ) -> HTTPException | ft.ResponseReturnValue: 

710 """Handles an HTTP exception. By default this will invoke the 

711 registered error handlers and fall back to returning the 

712 exception as response. 

713 

714 .. versionchanged:: 1.0.3 

715 ``RoutingException``, used internally for actions such as 

716 slash redirects during routing, is not passed to error 

717 handlers. 

718 

719 .. versionchanged:: 1.0 

720 Exceptions are looked up by code *and* by MRO, so 

721 ``HTTPException`` subclasses can be handled with a catch-all 

722 handler for the base ``HTTPException``. 

723 

724 .. versionadded:: 0.3 

725 """ 

726 # Proxy exceptions don't have error codes. We want to always return 

727 # those unchanged as errors 

728 if e.code is None: 

729 return e 

730 

731 # RoutingExceptions are used internally to trigger routing 

732 # actions, such as slash redirects raising RequestRedirect. They 

733 # are not raised or handled in user code. 

734 if isinstance(e, RoutingException): 

735 return e 

736 

737 handler = self._find_error_handler(e, request.blueprints) 

738 if handler is None: 

739 return e 

740 return self.ensure_sync(handler)(e) # type: ignore[no-any-return] 

741 

742 def handle_user_exception( 

743 self, e: Exception 

744 ) -> HTTPException | ft.ResponseReturnValue: 

745 """This method is called whenever an exception occurs that 

746 should be handled. A special case is :class:`~werkzeug 

747 .exceptions.HTTPException` which is forwarded to the 

748 :meth:`handle_http_exception` method. This function will either 

749 return a response value or reraise the exception with the same 

750 traceback. 

751 

752 .. versionchanged:: 1.0 

753 Key errors raised from request data like ``form`` show the 

754 bad key in debug mode rather than a generic bad request 

755 message. 

756 

757 .. versionadded:: 0.7 

758 """ 

759 if isinstance(e, BadRequestKeyError) and ( 

760 self.debug or self.config["TRAP_BAD_REQUEST_ERRORS"] 

761 ): 

762 e.show_exception = True 

763 

764 if isinstance(e, HTTPException) and not self.trap_http_exception(e): 

765 return self.handle_http_exception(e) 

766 

767 handler = self._find_error_handler(e, request.blueprints) 

768 

769 if handler is None: 

770 raise 

771 

772 return self.ensure_sync(handler)(e) # type: ignore[no-any-return] 

773 

774 def handle_exception(self, e: Exception) -> Response: 

775 """Handle an exception that did not have an error handler 

776 associated with it, or that was raised from an error handler. 

777 This always causes a 500 ``InternalServerError``. 

778 

779 Always sends the :data:`got_request_exception` signal. 

780 

781 If :data:`PROPAGATE_EXCEPTIONS` is ``True``, such as in debug 

782 mode, the error will be re-raised so that the debugger can 

783 display it. Otherwise, the original exception is logged, and 

784 an :exc:`~werkzeug.exceptions.InternalServerError` is returned. 

785 

786 If an error handler is registered for ``InternalServerError`` or 

787 ``500``, it will be used. For consistency, the handler will 

788 always receive the ``InternalServerError``. The original 

789 unhandled exception is available as ``e.original_exception``. 

790 

791 .. versionchanged:: 1.1.0 

792 Always passes the ``InternalServerError`` instance to the 

793 handler, setting ``original_exception`` to the unhandled 

794 error. 

795 

796 .. versionchanged:: 1.1.0 

797 ``after_request`` functions and other finalization is done 

798 even for the default 500 response when there is no handler. 

799 

800 .. versionadded:: 0.3 

801 """ 

802 exc_info = sys.exc_info() 

803 got_request_exception.send(self, _async_wrapper=self.ensure_sync, exception=e) 

804 propagate = self.config["PROPAGATE_EXCEPTIONS"] 

805 

806 if propagate is None: 

807 propagate = self.testing or self.debug 

808 

809 if propagate: 

810 # Re-raise if called with an active exception, otherwise 

811 # raise the passed in exception. 

812 if exc_info[1] is e: 

813 raise 

814 

815 raise e 

816 

817 self.log_exception(exc_info) 

818 server_error: InternalServerError | ft.ResponseReturnValue 

819 server_error = InternalServerError(original_exception=e) 

820 handler = self._find_error_handler(server_error, request.blueprints) 

821 

822 if handler is not None: 

823 server_error = self.ensure_sync(handler)(server_error) 

824 

825 return self.finalize_request(server_error, from_error_handler=True) 

826 

827 def log_exception( 

828 self, 

829 exc_info: (tuple[type, BaseException, TracebackType] | tuple[None, None, None]), 

830 ) -> None: 

831 """Logs an exception. This is called by :meth:`handle_exception` 

832 if debugging is disabled and right before the handler is called. 

833 The default implementation logs the exception as error on the 

834 :attr:`logger`. 

835 

836 .. versionadded:: 0.8 

837 """ 

838 self.logger.error( 

839 f"Exception on {request.path} [{request.method}]", exc_info=exc_info 

840 ) 

841 

842 def dispatch_request(self) -> ft.ResponseReturnValue: 

843 """Does the request dispatching. Matches the URL and returns the 

844 return value of the view or error handler. This does not have to 

845 be a response object. In order to convert the return value to a 

846 proper response object, call :func:`make_response`. 

847 

848 .. versionchanged:: 0.7 

849 This no longer does the exception handling, this code was 

850 moved to the new :meth:`full_dispatch_request`. 

851 """ 

852 req = request_ctx.request 

853 if req.routing_exception is not None: 

854 self.raise_routing_exception(req) 

855 rule: Rule = req.url_rule # type: ignore[assignment] 

856 # if we provide automatic options for this URL and the 

857 # request came with the OPTIONS method, reply automatically 

858 if ( 

859 getattr(rule, "provide_automatic_options", False) 

860 and req.method == "OPTIONS" 

861 ): 

862 return self.make_default_options_response() 

863 # otherwise dispatch to the handler for that endpoint 

864 view_args: dict[str, t.Any] = req.view_args # type: ignore[assignment] 

865 return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] 

866 

867 def full_dispatch_request(self) -> Response: 

868 """Dispatches the request and on top of that performs request 

869 pre and postprocessing as well as HTTP exception catching and 

870 error handling. 

871 

872 .. versionadded:: 0.7 

873 """ 

874 self._got_first_request = True 

875 

876 try: 

877 request_started.send(self, _async_wrapper=self.ensure_sync) 

878 rv = self.preprocess_request() 

879 if rv is None: 

880 rv = self.dispatch_request() 

881 except Exception as e: 

882 rv = self.handle_user_exception(e) 

883 return self.finalize_request(rv) 

884 

885 def finalize_request( 

886 self, 

887 rv: ft.ResponseReturnValue | HTTPException, 

888 from_error_handler: bool = False, 

889 ) -> Response: 

890 """Given the return value from a view function this finalizes 

891 the request by converting it into a response and invoking the 

892 postprocessing functions. This is invoked for both normal 

893 request dispatching as well as error handlers. 

894 

895 Because this means that it might be called as a result of a 

896 failure a special safe mode is available which can be enabled 

897 with the `from_error_handler` flag. If enabled, failures in 

898 response processing will be logged and otherwise ignored. 

899 

900 :internal: 

901 """ 

902 response = self.make_response(rv) 

903 try: 

904 response = self.process_response(response) 

905 request_finished.send( 

906 self, _async_wrapper=self.ensure_sync, response=response 

907 ) 

908 except Exception: 

909 if not from_error_handler: 

910 raise 

911 self.logger.exception( 

912 "Request finalizing failed with an error while handling an error" 

913 ) 

914 return response 

915 

916 def make_default_options_response(self) -> Response: 

917 """This method is called to create the default ``OPTIONS`` response. 

918 This can be changed through subclassing to change the default 

919 behavior of ``OPTIONS`` responses. 

920 

921 .. versionadded:: 0.7 

922 """ 

923 adapter = request_ctx.url_adapter 

924 methods = adapter.allowed_methods() # type: ignore[union-attr] 

925 rv = self.response_class() 

926 rv.allow.update(methods) 

927 return rv 

928 

929 def ensure_sync(self, func: t.Callable[..., t.Any]) -> t.Callable[..., t.Any]: 

930 """Ensure that the function is synchronous for WSGI workers. 

931 Plain ``def`` functions are returned as-is. ``async def`` 

932 functions are wrapped to run and wait for the response. 

933 

934 Override this method to change how the app runs async views. 

935 

936 .. versionadded:: 2.0 

937 """ 

938 if iscoroutinefunction(func): 

939 return self.async_to_sync(func) 

940 

941 return func 

942 

943 def async_to_sync( 

944 self, func: t.Callable[..., t.Coroutine[t.Any, t.Any, t.Any]] 

945 ) -> t.Callable[..., t.Any]: 

946 """Return a sync function that will run the coroutine function. 

947 

948 .. code-block:: python 

949 

950 result = app.async_to_sync(func)(*args, **kwargs) 

951 

952 Override this method to change how the app converts async code 

953 to be synchronously callable. 

954 

955 .. versionadded:: 2.0 

956 """ 

957 try: 

958 from asgiref.sync import async_to_sync as asgiref_async_to_sync 

959 except ImportError: 

960 raise RuntimeError( 

961 "Install Flask with the 'async' extra in order to use async views." 

962 ) from None 

963 

964 return asgiref_async_to_sync(func) 

965 

966 def url_for( 

967 self, 

968 /, 

969 endpoint: str, 

970 *, 

971 _anchor: str | None = None, 

972 _method: str | None = None, 

973 _scheme: str | None = None, 

974 _external: bool | None = None, 

975 **values: t.Any, 

976 ) -> str: 

977 """Generate a URL to the given endpoint with the given values. 

978 

979 This is called by :func:`flask.url_for`, and can be called 

980 directly as well. 

981 

982 An *endpoint* is the name of a URL rule, usually added with 

983 :meth:`@app.route() <route>`, and usually the same name as the 

984 view function. A route defined in a :class:`~flask.Blueprint` 

985 will prepend the blueprint's name separated by a ``.`` to the 

986 endpoint. 

987 

988 In some cases, such as email messages, you want URLs to include 

989 the scheme and domain, like ``https://example.com/hello``. When 

990 not in an active request, URLs will be external by default, but 

991 this requires setting :data:`SERVER_NAME` so Flask knows what 

992 domain to use. :data:`APPLICATION_ROOT` and 

993 :data:`PREFERRED_URL_SCHEME` should also be configured as 

994 needed. This config is only used when not in an active request. 

995 

996 Functions can be decorated with :meth:`url_defaults` to modify 

997 keyword arguments before the URL is built. 

998 

999 If building fails for some reason, such as an unknown endpoint 

1000 or incorrect values, the app's :meth:`handle_url_build_error` 

1001 method is called. If that returns a string, that is returned, 

1002 otherwise a :exc:`~werkzeug.routing.BuildError` is raised. 

1003 

1004 :param endpoint: The endpoint name associated with the URL to 

1005 generate. If this starts with a ``.``, the current blueprint 

1006 name (if any) will be used. 

1007 :param _anchor: If given, append this as ``#anchor`` to the URL. 

1008 :param _method: If given, generate the URL associated with this 

1009 method for the endpoint. 

1010 :param _scheme: If given, the URL will have this scheme if it 

1011 is external. 

1012 :param _external: If given, prefer the URL to be internal 

1013 (False) or require it to be external (True). External URLs 

1014 include the scheme and domain. When not in an active 

1015 request, URLs are external by default. 

1016 :param values: Values to use for the variable parts of the URL 

1017 rule. Unknown keys are appended as query string arguments, 

1018 like ``?a=b&c=d``. 

1019 

1020 .. versionadded:: 2.2 

1021 Moved from ``flask.url_for``, which calls this method. 

1022 """ 

1023 req_ctx = _cv_request.get(None) 

1024 

1025 if req_ctx is not None: 

1026 url_adapter = req_ctx.url_adapter 

1027 blueprint_name = req_ctx.request.blueprint 

1028 

1029 # If the endpoint starts with "." and the request matches a 

1030 # blueprint, the endpoint is relative to the blueprint. 

1031 if endpoint[:1] == ".": 

1032 if blueprint_name is not None: 

1033 endpoint = f"{blueprint_name}{endpoint}" 

1034 else: 

1035 endpoint = endpoint[1:] 

1036 

1037 # When in a request, generate a URL without scheme and 

1038 # domain by default, unless a scheme is given. 

1039 if _external is None: 

1040 _external = _scheme is not None 

1041 else: 

1042 app_ctx = _cv_app.get(None) 

1043 

1044 # If called by helpers.url_for, an app context is active, 

1045 # use its url_adapter. Otherwise, app.url_for was called 

1046 # directly, build an adapter. 

1047 if app_ctx is not None: 

1048 url_adapter = app_ctx.url_adapter 

1049 else: 

1050 url_adapter = self.create_url_adapter(None) 

1051 

1052 if url_adapter is None: 

1053 raise RuntimeError( 

1054 "Unable to build URLs outside an active request" 

1055 " without 'SERVER_NAME' configured. Also configure" 

1056 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" 

1057 " needed." 

1058 ) 

1059 

1060 # When outside a request, generate a URL with scheme and 

1061 # domain by default. 

1062 if _external is None: 

1063 _external = True 

1064 

1065 # It is an error to set _scheme when _external=False, in order 

1066 # to avoid accidental insecure URLs. 

1067 if _scheme is not None and not _external: 

1068 raise ValueError("When specifying '_scheme', '_external' must be True.") 

1069 

1070 self.inject_url_defaults(endpoint, values) 

1071 

1072 try: 

1073 rv = url_adapter.build( # type: ignore[union-attr] 

1074 endpoint, 

1075 values, 

1076 method=_method, 

1077 url_scheme=_scheme, 

1078 force_external=_external, 

1079 ) 

1080 except BuildError as error: 

1081 values.update( 

1082 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external 

1083 ) 

1084 return self.handle_url_build_error(error, endpoint, values) 

1085 

1086 if _anchor is not None: 

1087 _anchor = _url_quote(_anchor, safe="%!#$&'()*+,/:;=?@") 

1088 rv = f"{rv}#{_anchor}" 

1089 

1090 return rv 

1091 

1092 def make_response(self, rv: ft.ResponseReturnValue) -> Response: 

1093 """Convert the return value from a view function to an instance of 

1094 :attr:`response_class`. 

1095 

1096 :param rv: the return value from the view function. The view function 

1097 must return a response. Returning ``None``, or the view ending 

1098 without returning, is not allowed. The following types are allowed 

1099 for ``view_rv``: 

1100 

1101 ``str`` 

1102 A response object is created with the string encoded to UTF-8 

1103 as the body. 

1104 

1105 ``bytes`` 

1106 A response object is created with the bytes as the body. 

1107 

1108 ``dict`` 

1109 A dictionary that will be jsonify'd before being returned. 

1110 

1111 ``list`` 

1112 A list that will be jsonify'd before being returned. 

1113 

1114 ``generator`` or ``iterator`` 

1115 A generator that returns ``str`` or ``bytes`` to be 

1116 streamed as the response. 

1117 

1118 ``tuple`` 

1119 Either ``(body, status, headers)``, ``(body, status)``, or 

1120 ``(body, headers)``, where ``body`` is any of the other types 

1121 allowed here, ``status`` is a string or an integer, and 

1122 ``headers`` is a dictionary or a list of ``(key, value)`` 

1123 tuples. If ``body`` is a :attr:`response_class` instance, 

1124 ``status`` overwrites the exiting value and ``headers`` are 

1125 extended. 

1126 

1127 :attr:`response_class` 

1128 The object is returned unchanged. 

1129 

1130 other :class:`~werkzeug.wrappers.Response` class 

1131 The object is coerced to :attr:`response_class`. 

1132 

1133 :func:`callable` 

1134 The function is called as a WSGI application. The result is 

1135 used to create a response object. 

1136 

1137 .. versionchanged:: 2.2 

1138 A generator will be converted to a streaming response. 

1139 A list will be converted to a JSON response. 

1140 

1141 .. versionchanged:: 1.1 

1142 A dict will be converted to a JSON response. 

1143 

1144 .. versionchanged:: 0.9 

1145 Previously a tuple was interpreted as the arguments for the 

1146 response object. 

1147 """ 

1148 

1149 status = headers = None 

1150 

1151 # unpack tuple returns 

1152 if isinstance(rv, tuple): 

1153 len_rv = len(rv) 

1154 

1155 # a 3-tuple is unpacked directly 

1156 if len_rv == 3: 

1157 rv, status, headers = rv # type: ignore[misc] 

1158 # decide if a 2-tuple has status or headers 

1159 elif len_rv == 2: 

1160 if isinstance(rv[1], (Headers, dict, tuple, list)): 

1161 rv, headers = rv 

1162 else: 

1163 rv, status = rv # type: ignore[assignment,misc] 

1164 # other sized tuples are not allowed 

1165 else: 

1166 raise TypeError( 

1167 "The view function did not return a valid response tuple." 

1168 " The tuple must have the form (body, status, headers)," 

1169 " (body, status), or (body, headers)." 

1170 ) 

1171 

1172 # the body must not be None 

1173 if rv is None: 

1174 raise TypeError( 

1175 f"The view function for {request.endpoint!r} did not" 

1176 " return a valid response. The function either returned" 

1177 " None or ended without a return statement." 

1178 ) 

1179 

1180 # make sure the body is an instance of the response class 

1181 if not isinstance(rv, self.response_class): 

1182 if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, cabc.Iterator): 

1183 # let the response class set the status and headers instead of 

1184 # waiting to do it manually, so that the class can handle any 

1185 # special logic 

1186 rv = self.response_class( 

1187 rv, 

1188 status=status, 

1189 headers=headers, # type: ignore[arg-type] 

1190 ) 

1191 status = headers = None 

1192 elif isinstance(rv, (dict, list)): 

1193 rv = self.json.response(rv) 

1194 elif isinstance(rv, BaseResponse) or callable(rv): 

1195 # evaluate a WSGI callable, or coerce a different response 

1196 # class to the correct type 

1197 try: 

1198 rv = self.response_class.force_type( 

1199 rv, # type: ignore[arg-type] 

1200 request.environ, 

1201 ) 

1202 except TypeError as e: 

1203 raise TypeError( 

1204 f"{e}\nThe view function did not return a valid" 

1205 " response. The return type must be a string," 

1206 " dict, list, tuple with headers or status," 

1207 " Response instance, or WSGI callable, but it" 

1208 f" was a {type(rv).__name__}." 

1209 ).with_traceback(sys.exc_info()[2]) from None 

1210 else: 

1211 raise TypeError( 

1212 "The view function did not return a valid" 

1213 " response. The return type must be a string," 

1214 " dict, list, tuple with headers or status," 

1215 " Response instance, or WSGI callable, but it was a" 

1216 f" {type(rv).__name__}." 

1217 ) 

1218 

1219 rv = t.cast(Response, rv) 

1220 # prefer the status if it was provided 

1221 if status is not None: 

1222 if isinstance(status, (str, bytes, bytearray)): 

1223 rv.status = status 

1224 else: 

1225 rv.status_code = status 

1226 

1227 # extend existing headers with provided headers 

1228 if headers: 

1229 rv.headers.update(headers) # type: ignore[arg-type] 

1230 

1231 return rv 

1232 

1233 def preprocess_request(self) -> ft.ResponseReturnValue | None: 

1234 """Called before the request is dispatched. Calls 

1235 :attr:`url_value_preprocessors` registered with the app and the 

1236 current blueprint (if any). Then calls :attr:`before_request_funcs` 

1237 registered with the app and the blueprint. 

1238 

1239 If any :meth:`before_request` handler returns a non-None value, the 

1240 value is handled as if it was the return value from the view, and 

1241 further request handling is stopped. 

1242 """ 

1243 names = (None, *reversed(request.blueprints)) 

1244 

1245 for name in names: 

1246 if name in self.url_value_preprocessors: 

1247 for url_func in self.url_value_preprocessors[name]: 

1248 url_func(request.endpoint, request.view_args) 

1249 

1250 for name in names: 

1251 if name in self.before_request_funcs: 

1252 for before_func in self.before_request_funcs[name]: 

1253 rv = self.ensure_sync(before_func)() 

1254 

1255 if rv is not None: 

1256 return rv # type: ignore[no-any-return] 

1257 

1258 return None 

1259 

1260 def process_response(self, response: Response) -> Response: 

1261 """Can be overridden in order to modify the response object 

1262 before it's sent to the WSGI server. By default this will 

1263 call all the :meth:`after_request` decorated functions. 

1264 

1265 .. versionchanged:: 0.5 

1266 As of Flask 0.5 the functions registered for after request 

1267 execution are called in reverse order of registration. 

1268 

1269 :param response: a :attr:`response_class` object. 

1270 :return: a new response object or the same, has to be an 

1271 instance of :attr:`response_class`. 

1272 """ 

1273 ctx = request_ctx._get_current_object() # type: ignore[attr-defined] 

1274 

1275 for func in ctx._after_request_functions: 

1276 response = self.ensure_sync(func)(response) 

1277 

1278 for name in chain(request.blueprints, (None,)): 

1279 if name in self.after_request_funcs: 

1280 for func in reversed(self.after_request_funcs[name]): 

1281 response = self.ensure_sync(func)(response) 

1282 

1283 if not self.session_interface.is_null_session(ctx.session): 

1284 self.session_interface.save_session(self, ctx.session, response) 

1285 

1286 return response 

1287 

1288 def do_teardown_request( 

1289 self, 

1290 exc: BaseException | None = _sentinel, # type: ignore[assignment] 

1291 ) -> None: 

1292 """Called after the request is dispatched and the response is 

1293 returned, right before the request context is popped. 

1294 

1295 This calls all functions decorated with 

1296 :meth:`teardown_request`, and :meth:`Blueprint.teardown_request` 

1297 if a blueprint handled the request. Finally, the 

1298 :data:`request_tearing_down` signal is sent. 

1299 

1300 This is called by 

1301 :meth:`RequestContext.pop() <flask.ctx.RequestContext.pop>`, 

1302 which may be delayed during testing to maintain access to 

1303 resources. 

1304 

1305 :param exc: An unhandled exception raised while dispatching the 

1306 request. Detected from the current exception information if 

1307 not passed. Passed to each teardown function. 

1308 

1309 .. versionchanged:: 0.9 

1310 Added the ``exc`` argument. 

1311 """ 

1312 if exc is _sentinel: 

1313 exc = sys.exc_info()[1] 

1314 

1315 for name in chain(request.blueprints, (None,)): 

1316 if name in self.teardown_request_funcs: 

1317 for func in reversed(self.teardown_request_funcs[name]): 

1318 self.ensure_sync(func)(exc) 

1319 

1320 request_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) 

1321 

1322 def do_teardown_appcontext( 

1323 self, 

1324 exc: BaseException | None = _sentinel, # type: ignore[assignment] 

1325 ) -> None: 

1326 """Called right before the application context is popped. 

1327 

1328 When handling a request, the application context is popped 

1329 after the request context. See :meth:`do_teardown_request`. 

1330 

1331 This calls all functions decorated with 

1332 :meth:`teardown_appcontext`. Then the 

1333 :data:`appcontext_tearing_down` signal is sent. 

1334 

1335 This is called by 

1336 :meth:`AppContext.pop() <flask.ctx.AppContext.pop>`. 

1337 

1338 .. versionadded:: 0.9 

1339 """ 

1340 if exc is _sentinel: 

1341 exc = sys.exc_info()[1] 

1342 

1343 for func in reversed(self.teardown_appcontext_funcs): 

1344 self.ensure_sync(func)(exc) 

1345 

1346 appcontext_tearing_down.send(self, _async_wrapper=self.ensure_sync, exc=exc) 

1347 

1348 def app_context(self) -> AppContext: 

1349 """Create an :class:`~flask.ctx.AppContext`. Use as a ``with`` 

1350 block to push the context, which will make :data:`current_app` 

1351 point at this application. 

1352 

1353 An application context is automatically pushed by 

1354 :meth:`RequestContext.push() <flask.ctx.RequestContext.push>` 

1355 when handling a request, and when running a CLI command. Use 

1356 this to manually create a context outside of these situations. 

1357 

1358 :: 

1359 

1360 with app.app_context(): 

1361 init_db() 

1362 

1363 See :doc:`/appcontext`. 

1364 

1365 .. versionadded:: 0.9 

1366 """ 

1367 return AppContext(self) 

1368 

1369 def request_context(self, environ: WSGIEnvironment) -> RequestContext: 

1370 """Create a :class:`~flask.ctx.RequestContext` representing a 

1371 WSGI environment. Use a ``with`` block to push the context, 

1372 which will make :data:`request` point at this request. 

1373 

1374 See :doc:`/reqcontext`. 

1375 

1376 Typically you should not call this from your own code. A request 

1377 context is automatically pushed by the :meth:`wsgi_app` when 

1378 handling a request. Use :meth:`test_request_context` to create 

1379 an environment and context instead of this method. 

1380 

1381 :param environ: a WSGI environment 

1382 """ 

1383 return RequestContext(self, environ) 

1384 

1385 def test_request_context(self, *args: t.Any, **kwargs: t.Any) -> RequestContext: 

1386 """Create a :class:`~flask.ctx.RequestContext` for a WSGI 

1387 environment created from the given values. This is mostly useful 

1388 during testing, where you may want to run a function that uses 

1389 request data without dispatching a full request. 

1390 

1391 See :doc:`/reqcontext`. 

1392 

1393 Use a ``with`` block to push the context, which will make 

1394 :data:`request` point at the request for the created 

1395 environment. :: 

1396 

1397 with app.test_request_context(...): 

1398 generate_report() 

1399 

1400 When using the shell, it may be easier to push and pop the 

1401 context manually to avoid indentation. :: 

1402 

1403 ctx = app.test_request_context(...) 

1404 ctx.push() 

1405 ... 

1406 ctx.pop() 

1407 

1408 Takes the same arguments as Werkzeug's 

1409 :class:`~werkzeug.test.EnvironBuilder`, with some defaults from 

1410 the application. See the linked Werkzeug docs for most of the 

1411 available arguments. Flask-specific behavior is listed here. 

1412 

1413 :param path: URL path being requested. 

1414 :param base_url: Base URL where the app is being served, which 

1415 ``path`` is relative to. If not given, built from 

1416 :data:`PREFERRED_URL_SCHEME`, ``subdomain``, 

1417 :data:`SERVER_NAME`, and :data:`APPLICATION_ROOT`. 

1418 :param subdomain: Subdomain name to append to 

1419 :data:`SERVER_NAME`. 

1420 :param url_scheme: Scheme to use instead of 

1421 :data:`PREFERRED_URL_SCHEME`. 

1422 :param data: The request body, either as a string or a dict of 

1423 form keys and values. 

1424 :param json: If given, this is serialized as JSON and passed as 

1425 ``data``. Also defaults ``content_type`` to 

1426 ``application/json``. 

1427 :param args: other positional arguments passed to 

1428 :class:`~werkzeug.test.EnvironBuilder`. 

1429 :param kwargs: other keyword arguments passed to 

1430 :class:`~werkzeug.test.EnvironBuilder`. 

1431 """ 

1432 from .testing import EnvironBuilder 

1433 

1434 builder = EnvironBuilder(self, *args, **kwargs) 

1435 

1436 try: 

1437 return self.request_context(builder.get_environ()) 

1438 finally: 

1439 builder.close() 

1440 

1441 def wsgi_app( 

1442 self, environ: WSGIEnvironment, start_response: StartResponse 

1443 ) -> cabc.Iterable[bytes]: 

1444 """The actual WSGI application. This is not implemented in 

1445 :meth:`__call__` so that middlewares can be applied without 

1446 losing a reference to the app object. Instead of doing this:: 

1447 

1448 app = MyMiddleware(app) 

1449 

1450 It's a better idea to do this instead:: 

1451 

1452 app.wsgi_app = MyMiddleware(app.wsgi_app) 

1453 

1454 Then you still have the original application object around and 

1455 can continue to call methods on it. 

1456 

1457 .. versionchanged:: 0.7 

1458 Teardown events for the request and app contexts are called 

1459 even if an unhandled error occurs. Other events may not be 

1460 called depending on when an error occurs during dispatch. 

1461 See :ref:`callbacks-and-errors`. 

1462 

1463 :param environ: A WSGI environment. 

1464 :param start_response: A callable accepting a status code, 

1465 a list of headers, and an optional exception context to 

1466 start the response. 

1467 """ 

1468 ctx = self.request_context(environ) 

1469 error: BaseException | None = None 

1470 try: 

1471 try: 

1472 ctx.push() 

1473 response = self.full_dispatch_request() 

1474 except Exception as e: 

1475 error = e 

1476 response = self.handle_exception(e) 

1477 except: # noqa: B001 

1478 error = sys.exc_info()[1] 

1479 raise 

1480 return response(environ, start_response) 

1481 finally: 

1482 if "werkzeug.debug.preserve_context" in environ: 

1483 environ["werkzeug.debug.preserve_context"](_cv_app.get()) 

1484 environ["werkzeug.debug.preserve_context"](_cv_request.get()) 

1485 

1486 if error is not None and self.should_ignore_error(error): 

1487 error = None 

1488 

1489 ctx.pop(error) 

1490 

1491 def __call__( 

1492 self, environ: WSGIEnvironment, start_response: StartResponse 

1493 ) -> cabc.Iterable[bytes]: 

1494 """The WSGI server calls the Flask application object as the 

1495 WSGI application. This calls :meth:`wsgi_app`, which can be 

1496 wrapped to apply middleware. 

1497 """ 

1498 return self.wsgi_app(environ, start_response)