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

388 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-22 06:29 +0000

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 # Add a static route using the provided static_url_path, static_host, 

245 # and static_folder if there is a configured static_folder. 

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

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

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

249 if self.has_static_folder: 

250 assert ( 

251 bool(static_host) == host_matching 

252 ), "Invalid static_host/host_matching combination" 

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

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

255 self_ref = weakref.ref(self) 

256 self.add_url_rule( 

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

258 endpoint="static", 

259 host=static_host, 

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

261 ) 

262 

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

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

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

266 

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

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

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

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

271 

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

273 class. 

274 

275 .. versionchanged:: 2.0 

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

277 

278 .. versionadded:: 0.9 

279 """ 

280 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] 

281 

282 if value is None: 

283 return None 

284 

285 if isinstance(value, timedelta): 

286 return int(value.total_seconds()) 

287 

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

289 

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

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

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

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

294 set. 

295 

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

297 class. 

298 

299 .. versionadded:: 0.5 

300 

301 """ 

302 if not self.has_static_folder: 

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

304 

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

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

307 max_age = self.get_send_file_max_age(filename) 

308 return send_from_directory( 

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

310 ) 

311 

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

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

314 reading. 

315 

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

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

318 with: 

319 

320 .. code-block:: python 

321 

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

323 conn.executescript(f.read()) 

324 

325 :param resource: Path to the resource relative to 

326 :attr:`root_path`. 

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

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

329 

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

331 class. 

332 

333 """ 

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

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

336 

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

338 

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

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

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

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

343 writing. 

344 

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

346 subfolders use forward slashes as separator. 

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

348 """ 

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

350 

351 def create_jinja_environment(self) -> Environment: 

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

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

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

355 Flask-related globals and filters to the environment. 

356 

357 .. versionchanged:: 0.11 

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

359 ``TEMPLATES_AUTO_RELOAD`` configuration option. 

360 

361 .. versionadded:: 0.5 

362 """ 

363 options = dict(self.jinja_options) 

364 

365 if "autoescape" not in options: 

366 options["autoescape"] = self.select_jinja_autoescape 

367 

368 if "auto_reload" not in options: 

369 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] 

370 

371 if auto_reload is None: 

372 auto_reload = self.debug 

373 

374 options["auto_reload"] = auto_reload 

375 

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

377 rv.globals.update( 

378 url_for=self.url_for, 

379 get_flashed_messages=get_flashed_messages, 

380 config=self.config, 

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

382 # context processor for efficiency reasons but for imported 

383 # templates we also want the proxies in there. 

384 request=request, 

385 session=session, 

386 g=g, 

387 ) 

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

389 return rv 

390 

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

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

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

394 up so the request is passed explicitly. 

395 

396 .. versionadded:: 0.6 

397 

398 .. versionchanged:: 0.9 

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

400 URL adapter is created for the application context. 

401 

402 .. versionchanged:: 1.0 

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

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

405 """ 

406 if request is not None: 

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

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

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

410 if not self.subdomain_matching: 

411 subdomain = self.url_map.default_subdomain or None 

412 else: 

413 subdomain = None 

414 

415 return self.url_map.bind_to_environ( 

416 request.environ, 

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

418 subdomain=subdomain, 

419 ) 

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

421 # to work. 

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

423 return self.url_map.bind( 

424 self.config["SERVER_NAME"], 

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

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

427 ) 

428 

429 return None 

430 

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

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

433 

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

435 an error if the body will be discarded. 

436 

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

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

439 body. 

440 

441 .. versionchanged:: 2.1 

442 Don't intercept 307 and 308 redirects. 

443 

444 :meta private: 

445 :internal: 

446 """ 

447 if ( 

448 not self.debug 

449 or not isinstance(request.routing_exception, RequestRedirect) 

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

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

452 ): 

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

454 

455 from .debughelpers import FormDataRoutingRedirect 

456 

457 raise FormDataRoutingRedirect(request) 

458 

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

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

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

462 context as well as everything template context processors want 

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

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

465 decides to return a value with the same key. 

466 

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

468 to add extra variables. 

469 """ 

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

471 

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

473 if request: 

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

475 

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

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

478 orig_ctx = context.copy() 

479 

480 for name in names: 

481 if name in self.template_context_processors: 

482 for func in self.template_context_processors[name]: 

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

484 

485 context.update(orig_ctx) 

486 

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

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

489 application. This runs all the registered shell context 

490 processors. 

491 

492 .. versionadded:: 0.11 

493 """ 

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

495 for processor in self.shell_context_processors: 

496 rv.update(processor()) 

497 return rv 

498 

499 def run( 

500 self, 

501 host: str | None = None, 

502 port: int | None = None, 

503 debug: bool | None = None, 

504 load_dotenv: bool = True, 

505 **options: t.Any, 

506 ) -> None: 

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

508 

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

510 meet security and performance requirements for a production server. 

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

512 

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

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

515 

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

517 code execution on the interactive debugger, you can pass 

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

519 traceback screen active, but disable code execution. 

520 

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

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

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

524 

525 .. admonition:: Keep in Mind 

526 

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

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

529 interactive debugger without the code reloading, you have to 

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

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

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

533 catch. 

534 

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

536 have the server available externally as well. Defaults to 

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

538 if present. 

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

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

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

542 :attr:`debug`. 

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

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

545 directory to the directory containing the first file found. 

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

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

548 information. 

549 

550 .. versionchanged:: 1.0 

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

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

553 

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

555 

556 Threaded mode is enabled by default. 

557 

558 .. versionchanged:: 0.10 

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

560 variable. 

561 """ 

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

563 # the 'flask run' command is used. 

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

565 if not is_running_from_reloader(): 

566 click.secho( 

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

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

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

570 ' "__main__"\' guard.', 

571 fg="red", 

572 ) 

573 

574 return 

575 

576 if get_load_dotenv(load_dotenv): 

577 cli.load_dotenv() 

578 

579 # if set, env var overrides existing value 

580 if "FLASK_DEBUG" in os.environ: 

581 self.debug = get_debug_flag() 

582 

583 # debug passed to method overrides all other sources 

584 if debug is not None: 

585 self.debug = bool(debug) 

586 

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

588 sn_host = sn_port = None 

589 

590 if server_name: 

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

592 

593 if not host: 

594 if sn_host: 

595 host = sn_host 

596 else: 

597 host = "127.0.0.1" 

598 

599 if port or port == 0: 

600 port = int(port) 

601 elif sn_port: 

602 port = int(sn_port) 

603 else: 

604 port = 5000 

605 

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

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

608 options.setdefault("threaded", True) 

609 

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

611 

612 from werkzeug.serving import run_simple 

613 

614 try: 

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

616 finally: 

617 # reset the first request information if the development server 

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

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

620 self._got_first_request = False 

621 

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

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

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

625 

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

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

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

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

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

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

632 attribute. For example:: 

633 

634 app.testing = True 

635 client = app.test_client() 

636 

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

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

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

640 

641 with app.test_client() as c: 

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

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

644 

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

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

647 For example:: 

648 

649 from flask.testing import FlaskClient 

650 

651 class CustomClient(FlaskClient): 

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

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

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

655 

656 app.test_client_class = CustomClient 

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

658 

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

660 

661 .. versionchanged:: 0.4 

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

663 

664 .. versionadded:: 0.7 

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

666 to override the client to be used by setting the 

667 :attr:`test_client_class` attribute. 

668 

669 .. versionchanged:: 0.11 

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

671 the constructor of :attr:`test_client_class`. 

672 """ 

673 cls = self.test_client_class 

674 if cls is None: 

675 from .testing import FlaskClient as cls 

676 return cls( # type: ignore 

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

678 ) 

679 

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

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

682 See :ref:`testing-cli`. 

683 

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

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

686 passed as the first argument. 

687 

688 .. versionadded:: 1.0 

689 """ 

690 cls = self.test_cli_runner_class 

691 

692 if cls is None: 

693 from .testing import FlaskCliRunner as cls 

694 

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

696 

697 def handle_http_exception( 

698 self, e: HTTPException 

699 ) -> HTTPException | ft.ResponseReturnValue: 

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

701 registered error handlers and fall back to returning the 

702 exception as response. 

703 

704 .. versionchanged:: 1.0.3 

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

706 slash redirects during routing, is not passed to error 

707 handlers. 

708 

709 .. versionchanged:: 1.0 

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

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

712 handler for the base ``HTTPException``. 

713 

714 .. versionadded:: 0.3 

715 """ 

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

717 # those unchanged as errors 

718 if e.code is None: 

719 return e 

720 

721 # RoutingExceptions are used internally to trigger routing 

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

723 # are not raised or handled in user code. 

724 if isinstance(e, RoutingException): 

725 return e 

726 

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

728 if handler is None: 

729 return e 

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

731 

732 def handle_user_exception( 

733 self, e: Exception 

734 ) -> HTTPException | ft.ResponseReturnValue: 

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

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

737 .exceptions.HTTPException` which is forwarded to the 

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

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

740 traceback. 

741 

742 .. versionchanged:: 1.0 

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

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

745 message. 

746 

747 .. versionadded:: 0.7 

748 """ 

749 if isinstance(e, BadRequestKeyError) and ( 

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

751 ): 

752 e.show_exception = True 

753 

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

755 return self.handle_http_exception(e) 

756 

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

758 

759 if handler is None: 

760 raise 

761 

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

763 

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

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

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

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

768 

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

770 

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

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

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

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

775 

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

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

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

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

780 

781 .. versionchanged:: 1.1.0 

782 Always passes the ``InternalServerError`` instance to the 

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

784 error. 

785 

786 .. versionchanged:: 1.1.0 

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

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

789 

790 .. versionadded:: 0.3 

791 """ 

792 exc_info = sys.exc_info() 

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

794 propagate = self.config["PROPAGATE_EXCEPTIONS"] 

795 

796 if propagate is None: 

797 propagate = self.testing or self.debug 

798 

799 if propagate: 

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

801 # raise the passed in exception. 

802 if exc_info[1] is e: 

803 raise 

804 

805 raise e 

806 

807 self.log_exception(exc_info) 

808 server_error: InternalServerError | ft.ResponseReturnValue 

809 server_error = InternalServerError(original_exception=e) 

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

811 

812 if handler is not None: 

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

814 

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

816 

817 def log_exception( 

818 self, 

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

820 ) -> None: 

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

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

823 The default implementation logs the exception as error on the 

824 :attr:`logger`. 

825 

826 .. versionadded:: 0.8 

827 """ 

828 self.logger.error( 

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

830 ) 

831 

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

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

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

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

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

837 

838 .. versionchanged:: 0.7 

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

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

841 """ 

842 req = request_ctx.request 

843 if req.routing_exception is not None: 

844 self.raise_routing_exception(req) 

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

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

847 # request came with the OPTIONS method, reply automatically 

848 if ( 

849 getattr(rule, "provide_automatic_options", False) 

850 and req.method == "OPTIONS" 

851 ): 

852 return self.make_default_options_response() 

853 # otherwise dispatch to the handler for that endpoint 

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

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

856 

857 def full_dispatch_request(self) -> Response: 

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

859 pre and postprocessing as well as HTTP exception catching and 

860 error handling. 

861 

862 .. versionadded:: 0.7 

863 """ 

864 self._got_first_request = True 

865 

866 try: 

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

868 rv = self.preprocess_request() 

869 if rv is None: 

870 rv = self.dispatch_request() 

871 except Exception as e: 

872 rv = self.handle_user_exception(e) 

873 return self.finalize_request(rv) 

874 

875 def finalize_request( 

876 self, 

877 rv: ft.ResponseReturnValue | HTTPException, 

878 from_error_handler: bool = False, 

879 ) -> Response: 

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

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

882 postprocessing functions. This is invoked for both normal 

883 request dispatching as well as error handlers. 

884 

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

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

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

888 response processing will be logged and otherwise ignored. 

889 

890 :internal: 

891 """ 

892 response = self.make_response(rv) 

893 try: 

894 response = self.process_response(response) 

895 request_finished.send( 

896 self, _async_wrapper=self.ensure_sync, response=response 

897 ) 

898 except Exception: 

899 if not from_error_handler: 

900 raise 

901 self.logger.exception( 

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

903 ) 

904 return response 

905 

906 def make_default_options_response(self) -> Response: 

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

908 This can be changed through subclassing to change the default 

909 behavior of ``OPTIONS`` responses. 

910 

911 .. versionadded:: 0.7 

912 """ 

913 adapter = request_ctx.url_adapter 

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

915 rv = self.response_class() 

916 rv.allow.update(methods) 

917 return rv 

918 

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

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

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

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

923 

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

925 

926 .. versionadded:: 2.0 

927 """ 

928 if iscoroutinefunction(func): 

929 return self.async_to_sync(func) 

930 

931 return func 

932 

933 def async_to_sync( 

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

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

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

937 

938 .. code-block:: python 

939 

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

941 

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

943 to be synchronously callable. 

944 

945 .. versionadded:: 2.0 

946 """ 

947 try: 

948 from asgiref.sync import async_to_sync as asgiref_async_to_sync 

949 except ImportError: 

950 raise RuntimeError( 

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

952 ) from None 

953 

954 return asgiref_async_to_sync(func) 

955 

956 def url_for( 

957 self, 

958 /, 

959 endpoint: str, 

960 *, 

961 _anchor: str | None = None, 

962 _method: str | None = None, 

963 _scheme: str | None = None, 

964 _external: bool | None = None, 

965 **values: t.Any, 

966 ) -> str: 

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

968 

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

970 directly as well. 

971 

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

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

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

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

976 endpoint. 

977 

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

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

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

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

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

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

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

985 

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

987 keyword arguments before the URL is built. 

988 

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

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

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

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

993 

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

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

996 name (if any) will be used. 

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

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

999 method for the endpoint. 

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

1001 is external. 

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

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

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

1005 request, URLs are external by default. 

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

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

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

1009 

1010 .. versionadded:: 2.2 

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

1012 """ 

1013 req_ctx = _cv_request.get(None) 

1014 

1015 if req_ctx is not None: 

1016 url_adapter = req_ctx.url_adapter 

1017 blueprint_name = req_ctx.request.blueprint 

1018 

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

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

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

1022 if blueprint_name is not None: 

1023 endpoint = f"{blueprint_name}{endpoint}" 

1024 else: 

1025 endpoint = endpoint[1:] 

1026 

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

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

1029 if _external is None: 

1030 _external = _scheme is not None 

1031 else: 

1032 app_ctx = _cv_app.get(None) 

1033 

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

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

1036 # directly, build an adapter. 

1037 if app_ctx is not None: 

1038 url_adapter = app_ctx.url_adapter 

1039 else: 

1040 url_adapter = self.create_url_adapter(None) 

1041 

1042 if url_adapter is None: 

1043 raise RuntimeError( 

1044 "Unable to build URLs outside an active request" 

1045 " without 'SERVER_NAME' configured. Also configure" 

1046 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" 

1047 " needed." 

1048 ) 

1049 

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

1051 # domain by default. 

1052 if _external is None: 

1053 _external = True 

1054 

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

1056 # to avoid accidental insecure URLs. 

1057 if _scheme is not None and not _external: 

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

1059 

1060 self.inject_url_defaults(endpoint, values) 

1061 

1062 try: 

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

1064 endpoint, 

1065 values, 

1066 method=_method, 

1067 url_scheme=_scheme, 

1068 force_external=_external, 

1069 ) 

1070 except BuildError as error: 

1071 values.update( 

1072 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external 

1073 ) 

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

1075 

1076 if _anchor is not None: 

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

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

1079 

1080 return rv 

1081 

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

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

1084 :attr:`response_class`. 

1085 

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

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

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

1089 for ``view_rv``: 

1090 

1091 ``str`` 

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

1093 as the body. 

1094 

1095 ``bytes`` 

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

1097 

1098 ``dict`` 

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

1100 

1101 ``list`` 

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

1103 

1104 ``generator`` or ``iterator`` 

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

1106 streamed as the response. 

1107 

1108 ``tuple`` 

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

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

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

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

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

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

1115 extended. 

1116 

1117 :attr:`response_class` 

1118 The object is returned unchanged. 

1119 

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

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

1122 

1123 :func:`callable` 

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

1125 used to create a response object. 

1126 

1127 .. versionchanged:: 2.2 

1128 A generator will be converted to a streaming response. 

1129 A list will be converted to a JSON response. 

1130 

1131 .. versionchanged:: 1.1 

1132 A dict will be converted to a JSON response. 

1133 

1134 .. versionchanged:: 0.9 

1135 Previously a tuple was interpreted as the arguments for the 

1136 response object. 

1137 """ 

1138 

1139 status = headers = None 

1140 

1141 # unpack tuple returns 

1142 if isinstance(rv, tuple): 

1143 len_rv = len(rv) 

1144 

1145 # a 3-tuple is unpacked directly 

1146 if len_rv == 3: 

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

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

1149 elif len_rv == 2: 

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

1151 rv, headers = rv 

1152 else: 

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

1154 # other sized tuples are not allowed 

1155 else: 

1156 raise TypeError( 

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

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

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

1160 ) 

1161 

1162 # the body must not be None 

1163 if rv is None: 

1164 raise TypeError( 

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

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

1167 " None or ended without a return statement." 

1168 ) 

1169 

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

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

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

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

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

1175 # special logic 

1176 rv = self.response_class( 

1177 rv, 

1178 status=status, 

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

1180 ) 

1181 status = headers = None 

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

1183 rv = self.json.response(rv) 

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

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

1186 # class to the correct type 

1187 try: 

1188 rv = self.response_class.force_type( 

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

1190 request.environ, 

1191 ) 

1192 except TypeError as e: 

1193 raise TypeError( 

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

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

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

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

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

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

1200 else: 

1201 raise TypeError( 

1202 "The view function did not return a valid" 

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

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

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

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

1207 ) 

1208 

1209 rv = t.cast(Response, rv) 

1210 # prefer the status if it was provided 

1211 if status is not None: 

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

1213 rv.status = status 

1214 else: 

1215 rv.status_code = status 

1216 

1217 # extend existing headers with provided headers 

1218 if headers: 

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

1220 

1221 return rv 

1222 

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

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

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

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

1227 registered with the app and the blueprint. 

1228 

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

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

1231 further request handling is stopped. 

1232 """ 

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

1234 

1235 for name in names: 

1236 if name in self.url_value_preprocessors: 

1237 for url_func in self.url_value_preprocessors[name]: 

1238 url_func(request.endpoint, request.view_args) 

1239 

1240 for name in names: 

1241 if name in self.before_request_funcs: 

1242 for before_func in self.before_request_funcs[name]: 

1243 rv = self.ensure_sync(before_func)() 

1244 

1245 if rv is not None: 

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

1247 

1248 return None 

1249 

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

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

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

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

1254 

1255 .. versionchanged:: 0.5 

1256 As of Flask 0.5 the functions registered for after request 

1257 execution are called in reverse order of registration. 

1258 

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

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

1261 instance of :attr:`response_class`. 

1262 """ 

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

1264 

1265 for func in ctx._after_request_functions: 

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

1267 

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

1269 if name in self.after_request_funcs: 

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

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

1272 

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

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

1275 

1276 return response 

1277 

1278 def do_teardown_request( 

1279 self, 

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

1281 ) -> None: 

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

1283 returned, right before the request context is popped. 

1284 

1285 This calls all functions decorated with 

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

1287 if a blueprint handled the request. Finally, the 

1288 :data:`request_tearing_down` signal is sent. 

1289 

1290 This is called by 

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

1292 which may be delayed during testing to maintain access to 

1293 resources. 

1294 

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

1296 request. Detected from the current exception information if 

1297 not passed. Passed to each teardown function. 

1298 

1299 .. versionchanged:: 0.9 

1300 Added the ``exc`` argument. 

1301 """ 

1302 if exc is _sentinel: 

1303 exc = sys.exc_info()[1] 

1304 

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

1306 if name in self.teardown_request_funcs: 

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

1308 self.ensure_sync(func)(exc) 

1309 

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

1311 

1312 def do_teardown_appcontext( 

1313 self, 

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

1315 ) -> None: 

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

1317 

1318 When handling a request, the application context is popped 

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

1320 

1321 This calls all functions decorated with 

1322 :meth:`teardown_appcontext`. Then the 

1323 :data:`appcontext_tearing_down` signal is sent. 

1324 

1325 This is called by 

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

1327 

1328 .. versionadded:: 0.9 

1329 """ 

1330 if exc is _sentinel: 

1331 exc = sys.exc_info()[1] 

1332 

1333 for func in reversed(self.teardown_appcontext_funcs): 

1334 self.ensure_sync(func)(exc) 

1335 

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

1337 

1338 def app_context(self) -> AppContext: 

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

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

1341 point at this application. 

1342 

1343 An application context is automatically pushed by 

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

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

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

1347 

1348 :: 

1349 

1350 with app.app_context(): 

1351 init_db() 

1352 

1353 See :doc:`/appcontext`. 

1354 

1355 .. versionadded:: 0.9 

1356 """ 

1357 return AppContext(self) 

1358 

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

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

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

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

1363 

1364 See :doc:`/reqcontext`. 

1365 

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

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

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

1369 an environment and context instead of this method. 

1370 

1371 :param environ: a WSGI environment 

1372 """ 

1373 return RequestContext(self, environ) 

1374 

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

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

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

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

1379 request data without dispatching a full request. 

1380 

1381 See :doc:`/reqcontext`. 

1382 

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

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

1385 environment. :: 

1386 

1387 with app.test_request_context(...): 

1388 generate_report() 

1389 

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

1391 context manually to avoid indentation. :: 

1392 

1393 ctx = app.test_request_context(...) 

1394 ctx.push() 

1395 ... 

1396 ctx.pop() 

1397 

1398 Takes the same arguments as Werkzeug's 

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

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

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

1402 

1403 :param path: URL path being requested. 

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

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

1406 :data:`PREFERRED_URL_SCHEME`, ``subdomain``, 

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

1408 :param subdomain: Subdomain name to append to 

1409 :data:`SERVER_NAME`. 

1410 :param url_scheme: Scheme to use instead of 

1411 :data:`PREFERRED_URL_SCHEME`. 

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

1413 form keys and values. 

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

1415 ``data``. Also defaults ``content_type`` to 

1416 ``application/json``. 

1417 :param args: other positional arguments passed to 

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

1419 :param kwargs: other keyword arguments passed to 

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

1421 """ 

1422 from .testing import EnvironBuilder 

1423 

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

1425 

1426 try: 

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

1428 finally: 

1429 builder.close() 

1430 

1431 def wsgi_app( 

1432 self, environ: WSGIEnvironment, start_response: StartResponse 

1433 ) -> cabc.Iterable[bytes]: 

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

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

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

1437 

1438 app = MyMiddleware(app) 

1439 

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

1441 

1442 app.wsgi_app = MyMiddleware(app.wsgi_app) 

1443 

1444 Then you still have the original application object around and 

1445 can continue to call methods on it. 

1446 

1447 .. versionchanged:: 0.7 

1448 Teardown events for the request and app contexts are called 

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

1450 called depending on when an error occurs during dispatch. 

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

1452 

1453 :param environ: A WSGI environment. 

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

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

1456 start the response. 

1457 """ 

1458 ctx = self.request_context(environ) 

1459 error: BaseException | None = None 

1460 try: 

1461 try: 

1462 ctx.push() 

1463 response = self.full_dispatch_request() 

1464 except Exception as e: 

1465 error = e 

1466 response = self.handle_exception(e) 

1467 except: # noqa: B001 

1468 error = sys.exc_info()[1] 

1469 raise 

1470 return response(environ, start_response) 

1471 finally: 

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

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

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

1475 

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

1477 error = None 

1478 

1479 ctx.pop(error) 

1480 

1481 def __call__( 

1482 self, environ: WSGIEnvironment, start_response: StartResponse 

1483 ) -> cabc.Iterable[bytes]: 

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

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

1486 wrapped to apply middleware. 

1487 """ 

1488 return self.wsgi_app(environ, start_response)