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

388 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-09 07:17 +0000

1from __future__ import annotations 

2 

3import os 

4import sys 

5import typing as t 

6import weakref 

7from collections.abc import Iterator as _abc_Iterator 

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 .testing import FlaskClient 

58 from .testing import FlaskCliRunner 

59 

60T_shell_context_processor = t.TypeVar( 

61 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable 

62) 

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

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

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

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

67 

68 

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

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

71 return value 

72 

73 return timedelta(seconds=value) 

74 

75 

76class Flask(App): 

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

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

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

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

81 

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

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

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

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

86 

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

88 

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

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

91 

92 from flask import Flask 

93 app = Flask(__name__) 

94 

95 .. admonition:: About the First Parameter 

96 

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

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

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

100 information and a lot more. 

101 

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

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

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

105 your package there. 

106 

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

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

109 

110 app = Flask('yourapplication') 

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

112 

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

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

115 painful. Certain extensions can make assumptions based on the 

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

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

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

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

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

121 `yourapplication.views.frontend`) 

122 

123 .. versionadded:: 0.7 

124 The `static_url_path`, `static_folder`, and `template_folder` 

125 parameters were added. 

126 

127 .. versionadded:: 0.8 

128 The `instance_path` and `instance_relative_config` parameters were 

129 added. 

130 

131 .. versionadded:: 0.11 

132 The `root_path` parameter was added. 

133 

134 .. versionadded:: 1.0 

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

136 

137 .. versionadded:: 1.0 

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

139 matching needs to be enabled manually now. Setting 

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

141 

142 :param import_name: the name of the application package 

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

144 static files on the web. Defaults to the name 

145 of the `static_folder` folder. 

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

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

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

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

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

151 with a ``static_folder`` configured. 

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

153 Defaults to False. 

154 :param subdomain_matching: consider the subdomain relative to 

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

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

157 be used by the application. Defaults to 

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

159 application. 

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

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

162 package or module is assumed to be the instance 

163 path. 

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

165 for loading the config are assumed to 

166 be relative to the instance path instead 

167 of the application root. 

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

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

170 automatically, such as for namespace packages. 

171 """ 

172 

173 default_config = ImmutableDict( 

174 { 

175 "DEBUG": None, 

176 "TESTING": False, 

177 "PROPAGATE_EXCEPTIONS": None, 

178 "SECRET_KEY": None, 

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

180 "USE_X_SENDFILE": False, 

181 "SERVER_NAME": None, 

182 "APPLICATION_ROOT": "/", 

183 "SESSION_COOKIE_NAME": "session", 

184 "SESSION_COOKIE_DOMAIN": None, 

185 "SESSION_COOKIE_PATH": None, 

186 "SESSION_COOKIE_HTTPONLY": True, 

187 "SESSION_COOKIE_SECURE": False, 

188 "SESSION_COOKIE_SAMESITE": None, 

189 "SESSION_REFRESH_EACH_REQUEST": True, 

190 "MAX_CONTENT_LENGTH": None, 

191 "SEND_FILE_MAX_AGE_DEFAULT": None, 

192 "TRAP_BAD_REQUEST_ERRORS": None, 

193 "TRAP_HTTP_EXCEPTIONS": False, 

194 "EXPLAIN_TEMPLATE_LOADING": False, 

195 "PREFERRED_URL_SCHEME": "http", 

196 "TEMPLATES_AUTO_RELOAD": None, 

197 "MAX_COOKIE_SIZE": 4093, 

198 } 

199 ) 

200 

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

202 #: for more information. 

203 request_class = Request 

204 

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

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

207 response_class = Response 

208 

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

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

211 #: 

212 #: .. versionadded:: 0.8 

213 session_interface: SessionInterface = SecureCookieSessionInterface() 

214 

215 def __init__( 

216 self, 

217 import_name: str, 

218 static_url_path: str | None = None, 

219 static_folder: str | os.PathLike | None = "static", 

220 static_host: str | None = None, 

221 host_matching: bool = False, 

222 subdomain_matching: bool = False, 

223 template_folder: str | os.PathLike | None = "templates", 

224 instance_path: str | None = None, 

225 instance_relative_config: bool = False, 

226 root_path: str | None = None, 

227 ): 

228 super().__init__( 

229 import_name=import_name, 

230 static_url_path=static_url_path, 

231 static_folder=static_folder, 

232 static_host=static_host, 

233 host_matching=host_matching, 

234 subdomain_matching=subdomain_matching, 

235 template_folder=template_folder, 

236 instance_path=instance_path, 

237 instance_relative_config=instance_relative_config, 

238 root_path=root_path, 

239 ) 

240 

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

242 # and static_folder if there is a configured static_folder. 

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

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

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

246 if self.has_static_folder: 

247 assert ( 

248 bool(static_host) == host_matching 

249 ), "Invalid static_host/host_matching combination" 

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

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

252 self_ref = weakref.ref(self) 

253 self.add_url_rule( 

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

255 endpoint="static", 

256 host=static_host, 

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

258 ) 

259 

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

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

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

263 

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

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

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

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

268 

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

270 class. 

271 

272 .. versionchanged:: 2.0 

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

274 

275 .. versionadded:: 0.9 

276 """ 

277 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] 

278 

279 if value is None: 

280 return None 

281 

282 if isinstance(value, timedelta): 

283 return int(value.total_seconds()) 

284 

285 return value 

286 

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

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

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

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

291 set. 

292 

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

294 class. 

295 

296 .. versionadded:: 0.5 

297 

298 """ 

299 if not self.has_static_folder: 

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

301 

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

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

304 max_age = self.get_send_file_max_age(filename) 

305 return send_from_directory( 

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

307 ) 

308 

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

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

311 reading. 

312 

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

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

315 with: 

316 

317 .. code-block:: python 

318 

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

320 conn.executescript(f.read()) 

321 

322 :param resource: Path to the resource relative to 

323 :attr:`root_path`. 

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

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

326 

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

328 class. 

329 

330 """ 

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

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

333 

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

335 

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

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

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

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

340 writing. 

341 

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

343 subfolders use forward slashes as separator. 

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

345 """ 

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

347 

348 def create_jinja_environment(self) -> Environment: 

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

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

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

352 Flask-related globals and filters to the environment. 

353 

354 .. versionchanged:: 0.11 

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

356 ``TEMPLATES_AUTO_RELOAD`` configuration option. 

357 

358 .. versionadded:: 0.5 

359 """ 

360 options = dict(self.jinja_options) 

361 

362 if "autoescape" not in options: 

363 options["autoescape"] = self.select_jinja_autoescape 

364 

365 if "auto_reload" not in options: 

366 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] 

367 

368 if auto_reload is None: 

369 auto_reload = self.debug 

370 

371 options["auto_reload"] = auto_reload 

372 

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

374 rv.globals.update( 

375 url_for=self.url_for, 

376 get_flashed_messages=get_flashed_messages, 

377 config=self.config, 

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

379 # context processor for efficiency reasons but for imported 

380 # templates we also want the proxies in there. 

381 request=request, 

382 session=session, 

383 g=g, 

384 ) 

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

386 return rv 

387 

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

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

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

391 up so the request is passed explicitly. 

392 

393 .. versionadded:: 0.6 

394 

395 .. versionchanged:: 0.9 

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

397 URL adapter is created for the application context. 

398 

399 .. versionchanged:: 1.0 

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

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

402 """ 

403 if request is not None: 

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

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

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

407 if not self.subdomain_matching: 

408 subdomain = self.url_map.default_subdomain or None 

409 else: 

410 subdomain = None 

411 

412 return self.url_map.bind_to_environ( 

413 request.environ, 

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

415 subdomain=subdomain, 

416 ) 

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

418 # to work. 

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

420 return self.url_map.bind( 

421 self.config["SERVER_NAME"], 

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

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

424 ) 

425 

426 return None 

427 

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

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

430 

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

432 an error if the body will be discarded. 

433 

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

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

436 body. 

437 

438 .. versionchanged:: 2.1 

439 Don't intercept 307 and 308 redirects. 

440 

441 :meta private: 

442 :internal: 

443 """ 

444 if ( 

445 not self.debug 

446 or not isinstance(request.routing_exception, RequestRedirect) 

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

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

449 ): 

450 raise request.routing_exception # type: ignore 

451 

452 from .debughelpers import FormDataRoutingRedirect 

453 

454 raise FormDataRoutingRedirect(request) 

455 

456 def update_template_context(self, context: dict) -> None: 

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

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

459 context as well as everything template context processors want 

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

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

462 decides to return a value with the same key. 

463 

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

465 to add extra variables. 

466 """ 

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

468 

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

470 if request: 

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

472 

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

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

475 orig_ctx = context.copy() 

476 

477 for name in names: 

478 if name in self.template_context_processors: 

479 for func in self.template_context_processors[name]: 

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

481 

482 context.update(orig_ctx) 

483 

484 def make_shell_context(self) -> dict: 

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

486 application. This runs all the registered shell context 

487 processors. 

488 

489 .. versionadded:: 0.11 

490 """ 

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

492 for processor in self.shell_context_processors: 

493 rv.update(processor()) 

494 return rv 

495 

496 def run( 

497 self, 

498 host: str | None = None, 

499 port: int | None = None, 

500 debug: bool | None = None, 

501 load_dotenv: bool = True, 

502 **options: t.Any, 

503 ) -> None: 

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

505 

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

507 meet security and performance requirements for a production server. 

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

509 

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

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

512 

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

514 code execution on the interactive debugger, you can pass 

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

516 traceback screen active, but disable code execution. 

517 

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

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

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

521 

522 .. admonition:: Keep in Mind 

523 

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

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

526 interactive debugger without the code reloading, you have to 

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

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

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

530 catch. 

531 

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

533 have the server available externally as well. Defaults to 

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

535 if present. 

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

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

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

539 :attr:`debug`. 

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

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

542 directory to the directory containing the first file found. 

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

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

545 information. 

546 

547 .. versionchanged:: 1.0 

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

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

550 

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

552 

553 Threaded mode is enabled by default. 

554 

555 .. versionchanged:: 0.10 

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

557 variable. 

558 """ 

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

560 # the 'flask run' command is used. 

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

562 if not is_running_from_reloader(): 

563 click.secho( 

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

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

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

567 ' "__main__"\' guard.', 

568 fg="red", 

569 ) 

570 

571 return 

572 

573 if get_load_dotenv(load_dotenv): 

574 cli.load_dotenv() 

575 

576 # if set, env var overrides existing value 

577 if "FLASK_DEBUG" in os.environ: 

578 self.debug = get_debug_flag() 

579 

580 # debug passed to method overrides all other sources 

581 if debug is not None: 

582 self.debug = bool(debug) 

583 

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

585 sn_host = sn_port = None 

586 

587 if server_name: 

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

589 

590 if not host: 

591 if sn_host: 

592 host = sn_host 

593 else: 

594 host = "127.0.0.1" 

595 

596 if port or port == 0: 

597 port = int(port) 

598 elif sn_port: 

599 port = int(sn_port) 

600 else: 

601 port = 5000 

602 

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

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

605 options.setdefault("threaded", True) 

606 

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

608 

609 from werkzeug.serving import run_simple 

610 

611 try: 

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

613 finally: 

614 # reset the first request information if the development server 

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

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

617 self._got_first_request = False 

618 

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

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

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

622 

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

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

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

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

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

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

629 attribute. For example:: 

630 

631 app.testing = True 

632 client = app.test_client() 

633 

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

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

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

637 

638 with app.test_client() as c: 

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

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

641 

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

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

644 For example:: 

645 

646 from flask.testing import FlaskClient 

647 

648 class CustomClient(FlaskClient): 

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

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

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

652 

653 app.test_client_class = CustomClient 

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

655 

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

657 

658 .. versionchanged:: 0.4 

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

660 

661 .. versionadded:: 0.7 

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

663 to override the client to be used by setting the 

664 :attr:`test_client_class` attribute. 

665 

666 .. versionchanged:: 0.11 

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

668 the constructor of :attr:`test_client_class`. 

669 """ 

670 cls = self.test_client_class 

671 if cls is None: 

672 from .testing import FlaskClient as cls 

673 return cls( # type: ignore 

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

675 ) 

676 

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

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

679 See :ref:`testing-cli`. 

680 

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

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

683 passed as the first argument. 

684 

685 .. versionadded:: 1.0 

686 """ 

687 cls = self.test_cli_runner_class 

688 

689 if cls is None: 

690 from .testing import FlaskCliRunner as cls 

691 

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

693 

694 def handle_http_exception( 

695 self, e: HTTPException 

696 ) -> HTTPException | ft.ResponseReturnValue: 

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

698 registered error handlers and fall back to returning the 

699 exception as response. 

700 

701 .. versionchanged:: 1.0.3 

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

703 slash redirects during routing, is not passed to error 

704 handlers. 

705 

706 .. versionchanged:: 1.0 

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

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

709 handler for the base ``HTTPException``. 

710 

711 .. versionadded:: 0.3 

712 """ 

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

714 # those unchanged as errors 

715 if e.code is None: 

716 return e 

717 

718 # RoutingExceptions are used internally to trigger routing 

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

720 # are not raised or handled in user code. 

721 if isinstance(e, RoutingException): 

722 return e 

723 

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

725 if handler is None: 

726 return e 

727 return self.ensure_sync(handler)(e) 

728 

729 def handle_user_exception( 

730 self, e: Exception 

731 ) -> HTTPException | ft.ResponseReturnValue: 

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

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

734 .exceptions.HTTPException` which is forwarded to the 

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

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

737 traceback. 

738 

739 .. versionchanged:: 1.0 

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

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

742 message. 

743 

744 .. versionadded:: 0.7 

745 """ 

746 if isinstance(e, BadRequestKeyError) and ( 

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

748 ): 

749 e.show_exception = True 

750 

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

752 return self.handle_http_exception(e) 

753 

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

755 

756 if handler is None: 

757 raise 

758 

759 return self.ensure_sync(handler)(e) 

760 

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

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

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

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

765 

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

767 

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

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

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

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

772 

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

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

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

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

777 

778 .. versionchanged:: 1.1.0 

779 Always passes the ``InternalServerError`` instance to the 

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

781 error. 

782 

783 .. versionchanged:: 1.1.0 

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

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

786 

787 .. versionadded:: 0.3 

788 """ 

789 exc_info = sys.exc_info() 

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

791 propagate = self.config["PROPAGATE_EXCEPTIONS"] 

792 

793 if propagate is None: 

794 propagate = self.testing or self.debug 

795 

796 if propagate: 

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

798 # raise the passed in exception. 

799 if exc_info[1] is e: 

800 raise 

801 

802 raise e 

803 

804 self.log_exception(exc_info) 

805 server_error: InternalServerError | ft.ResponseReturnValue 

806 server_error = InternalServerError(original_exception=e) 

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

808 

809 if handler is not None: 

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

811 

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

813 

814 def log_exception( 

815 self, 

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

817 ) -> None: 

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

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

820 The default implementation logs the exception as error on the 

821 :attr:`logger`. 

822 

823 .. versionadded:: 0.8 

824 """ 

825 self.logger.error( 

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

827 ) 

828 

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

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

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

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

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

834 

835 .. versionchanged:: 0.7 

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

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

838 """ 

839 req = request_ctx.request 

840 if req.routing_exception is not None: 

841 self.raise_routing_exception(req) 

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

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

844 # request came with the OPTIONS method, reply automatically 

845 if ( 

846 getattr(rule, "provide_automatic_options", False) 

847 and req.method == "OPTIONS" 

848 ): 

849 return self.make_default_options_response() 

850 # otherwise dispatch to the handler for that endpoint 

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

852 return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) 

853 

854 def full_dispatch_request(self) -> Response: 

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

856 pre and postprocessing as well as HTTP exception catching and 

857 error handling. 

858 

859 .. versionadded:: 0.7 

860 """ 

861 self._got_first_request = True 

862 

863 try: 

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

865 rv = self.preprocess_request() 

866 if rv is None: 

867 rv = self.dispatch_request() 

868 except Exception as e: 

869 rv = self.handle_user_exception(e) 

870 return self.finalize_request(rv) 

871 

872 def finalize_request( 

873 self, 

874 rv: ft.ResponseReturnValue | HTTPException, 

875 from_error_handler: bool = False, 

876 ) -> Response: 

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

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

879 postprocessing functions. This is invoked for both normal 

880 request dispatching as well as error handlers. 

881 

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

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

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

885 response processing will be logged and otherwise ignored. 

886 

887 :internal: 

888 """ 

889 response = self.make_response(rv) 

890 try: 

891 response = self.process_response(response) 

892 request_finished.send( 

893 self, _async_wrapper=self.ensure_sync, response=response 

894 ) 

895 except Exception: 

896 if not from_error_handler: 

897 raise 

898 self.logger.exception( 

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

900 ) 

901 return response 

902 

903 def make_default_options_response(self) -> Response: 

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

905 This can be changed through subclassing to change the default 

906 behavior of ``OPTIONS`` responses. 

907 

908 .. versionadded:: 0.7 

909 """ 

910 adapter = request_ctx.url_adapter 

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

912 rv = self.response_class() 

913 rv.allow.update(methods) 

914 return rv 

915 

916 def ensure_sync(self, func: t.Callable) -> t.Callable: 

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

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

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

920 

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

922 

923 .. versionadded:: 2.0 

924 """ 

925 if iscoroutinefunction(func): 

926 return self.async_to_sync(func) 

927 

928 return func 

929 

930 def async_to_sync( 

931 self, func: t.Callable[..., t.Coroutine] 

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

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

934 

935 .. code-block:: python 

936 

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

938 

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

940 to be synchronously callable. 

941 

942 .. versionadded:: 2.0 

943 """ 

944 try: 

945 from asgiref.sync import async_to_sync as asgiref_async_to_sync 

946 except ImportError: 

947 raise RuntimeError( 

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

949 ) from None 

950 

951 return asgiref_async_to_sync(func) 

952 

953 def url_for( 

954 self, 

955 /, 

956 endpoint: str, 

957 *, 

958 _anchor: str | None = None, 

959 _method: str | None = None, 

960 _scheme: str | None = None, 

961 _external: bool | None = None, 

962 **values: t.Any, 

963 ) -> str: 

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

965 

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

967 directly as well. 

968 

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

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

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

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

973 endpoint. 

974 

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

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

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

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

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

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

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

982 

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

984 keyword arguments before the URL is built. 

985 

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

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

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

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

990 

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

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

993 name (if any) will be used. 

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

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

996 method for the endpoint. 

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

998 is external. 

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

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

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

1002 request, URLs are external by default. 

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

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

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

1006 

1007 .. versionadded:: 2.2 

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

1009 """ 

1010 req_ctx = _cv_request.get(None) 

1011 

1012 if req_ctx is not None: 

1013 url_adapter = req_ctx.url_adapter 

1014 blueprint_name = req_ctx.request.blueprint 

1015 

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

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

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

1019 if blueprint_name is not None: 

1020 endpoint = f"{blueprint_name}{endpoint}" 

1021 else: 

1022 endpoint = endpoint[1:] 

1023 

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

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

1026 if _external is None: 

1027 _external = _scheme is not None 

1028 else: 

1029 app_ctx = _cv_app.get(None) 

1030 

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

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

1033 # directly, build an adapter. 

1034 if app_ctx is not None: 

1035 url_adapter = app_ctx.url_adapter 

1036 else: 

1037 url_adapter = self.create_url_adapter(None) 

1038 

1039 if url_adapter is None: 

1040 raise RuntimeError( 

1041 "Unable to build URLs outside an active request" 

1042 " without 'SERVER_NAME' configured. Also configure" 

1043 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" 

1044 " needed." 

1045 ) 

1046 

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

1048 # domain by default. 

1049 if _external is None: 

1050 _external = True 

1051 

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

1053 # to avoid accidental insecure URLs. 

1054 if _scheme is not None and not _external: 

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

1056 

1057 self.inject_url_defaults(endpoint, values) 

1058 

1059 try: 

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

1061 endpoint, 

1062 values, 

1063 method=_method, 

1064 url_scheme=_scheme, 

1065 force_external=_external, 

1066 ) 

1067 except BuildError as error: 

1068 values.update( 

1069 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external 

1070 ) 

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

1072 

1073 if _anchor is not None: 

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

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

1076 

1077 return rv 

1078 

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

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

1081 :attr:`response_class`. 

1082 

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

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

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

1086 for ``view_rv``: 

1087 

1088 ``str`` 

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

1090 as the body. 

1091 

1092 ``bytes`` 

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

1094 

1095 ``dict`` 

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

1097 

1098 ``list`` 

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

1100 

1101 ``generator`` or ``iterator`` 

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

1103 streamed as the response. 

1104 

1105 ``tuple`` 

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

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

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

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

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

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

1112 extended. 

1113 

1114 :attr:`response_class` 

1115 The object is returned unchanged. 

1116 

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

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

1119 

1120 :func:`callable` 

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

1122 used to create a response object. 

1123 

1124 .. versionchanged:: 2.2 

1125 A generator will be converted to a streaming response. 

1126 A list will be converted to a JSON response. 

1127 

1128 .. versionchanged:: 1.1 

1129 A dict will be converted to a JSON response. 

1130 

1131 .. versionchanged:: 0.9 

1132 Previously a tuple was interpreted as the arguments for the 

1133 response object. 

1134 """ 

1135 

1136 status = headers = None 

1137 

1138 # unpack tuple returns 

1139 if isinstance(rv, tuple): 

1140 len_rv = len(rv) 

1141 

1142 # a 3-tuple is unpacked directly 

1143 if len_rv == 3: 

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

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

1146 elif len_rv == 2: 

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

1148 rv, headers = rv 

1149 else: 

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

1151 # other sized tuples are not allowed 

1152 else: 

1153 raise TypeError( 

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

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

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

1157 ) 

1158 

1159 # the body must not be None 

1160 if rv is None: 

1161 raise TypeError( 

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

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

1164 " None or ended without a return statement." 

1165 ) 

1166 

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

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

1169 if isinstance(rv, (str, bytes, bytearray)) or isinstance(rv, _abc_Iterator): 

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

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

1172 # special logic 

1173 rv = self.response_class( 

1174 rv, 

1175 status=status, 

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

1177 ) 

1178 status = headers = None 

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

1180 rv = self.json.response(rv) 

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

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

1183 # class to the correct type 

1184 try: 

1185 rv = self.response_class.force_type( 

1186 rv, request.environ # type: ignore[arg-type] 

1187 ) 

1188 except TypeError as e: 

1189 raise TypeError( 

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

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

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

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

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

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

1196 else: 

1197 raise TypeError( 

1198 "The view function did not return a valid" 

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

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

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

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

1203 ) 

1204 

1205 rv = t.cast(Response, rv) 

1206 # prefer the status if it was provided 

1207 if status is not None: 

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

1209 rv.status = status 

1210 else: 

1211 rv.status_code = status 

1212 

1213 # extend existing headers with provided headers 

1214 if headers: 

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

1216 

1217 return rv 

1218 

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

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

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

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

1223 registered with the app and the blueprint. 

1224 

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

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

1227 further request handling is stopped. 

1228 """ 

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

1230 

1231 for name in names: 

1232 if name in self.url_value_preprocessors: 

1233 for url_func in self.url_value_preprocessors[name]: 

1234 url_func(request.endpoint, request.view_args) 

1235 

1236 for name in names: 

1237 if name in self.before_request_funcs: 

1238 for before_func in self.before_request_funcs[name]: 

1239 rv = self.ensure_sync(before_func)() 

1240 

1241 if rv is not None: 

1242 return rv 

1243 

1244 return None 

1245 

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

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

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

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

1250 

1251 .. versionchanged:: 0.5 

1252 As of Flask 0.5 the functions registered for after request 

1253 execution are called in reverse order of registration. 

1254 

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

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

1257 instance of :attr:`response_class`. 

1258 """ 

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

1260 

1261 for func in ctx._after_request_functions: 

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

1263 

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

1265 if name in self.after_request_funcs: 

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

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

1268 

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

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

1271 

1272 return response 

1273 

1274 def do_teardown_request( 

1275 self, exc: BaseException | None = _sentinel # type: ignore 

1276 ) -> None: 

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

1278 returned, right before the request context is popped. 

1279 

1280 This calls all functions decorated with 

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

1282 if a blueprint handled the request. Finally, the 

1283 :data:`request_tearing_down` signal is sent. 

1284 

1285 This is called by 

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

1287 which may be delayed during testing to maintain access to 

1288 resources. 

1289 

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

1291 request. Detected from the current exception information if 

1292 not passed. Passed to each teardown function. 

1293 

1294 .. versionchanged:: 0.9 

1295 Added the ``exc`` argument. 

1296 """ 

1297 if exc is _sentinel: 

1298 exc = sys.exc_info()[1] 

1299 

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

1301 if name in self.teardown_request_funcs: 

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

1303 self.ensure_sync(func)(exc) 

1304 

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

1306 

1307 def do_teardown_appcontext( 

1308 self, exc: BaseException | None = _sentinel # type: ignore 

1309 ) -> None: 

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

1311 

1312 When handling a request, the application context is popped 

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

1314 

1315 This calls all functions decorated with 

1316 :meth:`teardown_appcontext`. Then the 

1317 :data:`appcontext_tearing_down` signal is sent. 

1318 

1319 This is called by 

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

1321 

1322 .. versionadded:: 0.9 

1323 """ 

1324 if exc is _sentinel: 

1325 exc = sys.exc_info()[1] 

1326 

1327 for func in reversed(self.teardown_appcontext_funcs): 

1328 self.ensure_sync(func)(exc) 

1329 

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

1331 

1332 def app_context(self) -> AppContext: 

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

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

1335 point at this application. 

1336 

1337 An application context is automatically pushed by 

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

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

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

1341 

1342 :: 

1343 

1344 with app.app_context(): 

1345 init_db() 

1346 

1347 See :doc:`/appcontext`. 

1348 

1349 .. versionadded:: 0.9 

1350 """ 

1351 return AppContext(self) 

1352 

1353 def request_context(self, environ: dict) -> RequestContext: 

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

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

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

1357 

1358 See :doc:`/reqcontext`. 

1359 

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

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

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

1363 an environment and context instead of this method. 

1364 

1365 :param environ: a WSGI environment 

1366 """ 

1367 return RequestContext(self, environ) 

1368 

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

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

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

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

1373 request data without dispatching a full request. 

1374 

1375 See :doc:`/reqcontext`. 

1376 

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

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

1379 environment. :: 

1380 

1381 with app.test_request_context(...): 

1382 generate_report() 

1383 

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

1385 context manually to avoid indentation. :: 

1386 

1387 ctx = app.test_request_context(...) 

1388 ctx.push() 

1389 ... 

1390 ctx.pop() 

1391 

1392 Takes the same arguments as Werkzeug's 

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

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

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

1396 

1397 :param path: URL path being requested. 

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

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

1400 :data:`PREFERRED_URL_SCHEME`, ``subdomain``, 

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

1402 :param subdomain: Subdomain name to append to 

1403 :data:`SERVER_NAME`. 

1404 :param url_scheme: Scheme to use instead of 

1405 :data:`PREFERRED_URL_SCHEME`. 

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

1407 form keys and values. 

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

1409 ``data``. Also defaults ``content_type`` to 

1410 ``application/json``. 

1411 :param args: other positional arguments passed to 

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

1413 :param kwargs: other keyword arguments passed to 

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

1415 """ 

1416 from .testing import EnvironBuilder 

1417 

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

1419 

1420 try: 

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

1422 finally: 

1423 builder.close() 

1424 

1425 def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any: 

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

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

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

1429 

1430 app = MyMiddleware(app) 

1431 

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

1433 

1434 app.wsgi_app = MyMiddleware(app.wsgi_app) 

1435 

1436 Then you still have the original application object around and 

1437 can continue to call methods on it. 

1438 

1439 .. versionchanged:: 0.7 

1440 Teardown events for the request and app contexts are called 

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

1442 called depending on when an error occurs during dispatch. 

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

1444 

1445 :param environ: A WSGI environment. 

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

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

1448 start the response. 

1449 """ 

1450 ctx = self.request_context(environ) 

1451 error: BaseException | None = None 

1452 try: 

1453 try: 

1454 ctx.push() 

1455 response = self.full_dispatch_request() 

1456 except Exception as e: 

1457 error = e 

1458 response = self.handle_exception(e) 

1459 except: # noqa: B001 

1460 error = sys.exc_info()[1] 

1461 raise 

1462 return response(environ, start_response) 

1463 finally: 

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

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

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

1467 

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

1469 error = None 

1470 

1471 ctx.pop(error) 

1472 

1473 def __call__(self, environ: dict, start_response: t.Callable) -> t.Any: 

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

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

1476 wrapped to apply middleware. 

1477 """ 

1478 return self.wsgi_app(environ, start_response)