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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

404 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import os 

5import sys 

6import typing as t 

7import weakref 

8from datetime import timedelta 

9from inspect import iscoroutinefunction 

10from itertools import chain 

11from types import TracebackType 

12from urllib.parse import quote as _url_quote 

13 

14import click 

15from werkzeug.datastructures import Headers 

16from werkzeug.datastructures import ImmutableDict 

17from werkzeug.exceptions import BadRequestKeyError 

18from werkzeug.exceptions import HTTPException 

19from werkzeug.exceptions import InternalServerError 

20from werkzeug.routing import BuildError 

21from werkzeug.routing import MapAdapter 

22from werkzeug.routing import RequestRedirect 

23from werkzeug.routing import RoutingException 

24from werkzeug.routing import Rule 

25from werkzeug.serving import is_running_from_reloader 

26from werkzeug.wrappers import Response as BaseResponse 

27from werkzeug.wsgi import get_host 

28 

29from . import cli 

30from . import typing as ft 

31from .ctx import AppContext 

32from .ctx import RequestContext 

33from .globals import _cv_app 

34from .globals import _cv_request 

35from .globals import current_app 

36from .globals import g 

37from .globals import request 

38from .globals import request_ctx 

39from .globals import session 

40from .helpers import get_debug_flag 

41from .helpers import get_flashed_messages 

42from .helpers import get_load_dotenv 

43from .helpers import send_from_directory 

44from .sansio.app import App 

45from .sansio.scaffold import _sentinel 

46from .sessions import SecureCookieSessionInterface 

47from .sessions import SessionInterface 

48from .signals import appcontext_tearing_down 

49from .signals import got_request_exception 

50from .signals import request_finished 

51from .signals import request_started 

52from .signals import request_tearing_down 

53from .templating import Environment 

54from .wrappers import Request 

55from .wrappers import Response 

56 

57if t.TYPE_CHECKING: # pragma: no cover 

58 from _typeshed.wsgi import StartResponse 

59 from _typeshed.wsgi import WSGIEnvironment 

60 

61 from .testing import FlaskClient 

62 from .testing import FlaskCliRunner 

63 from .typing import HeadersValue 

64 

65T_shell_context_processor = t.TypeVar( 

66 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable 

67) 

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

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

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

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

72 

73 

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

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

76 return value 

77 

78 return timedelta(seconds=value) 

79 

80 

81class Flask(App): 

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

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

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

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

86 

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

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

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

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

91 

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

93 

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

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

96 

97 from flask import Flask 

98 app = Flask(__name__) 

99 

100 .. admonition:: About the First Parameter 

101 

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

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

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

105 information and a lot more. 

106 

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

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

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

110 your package there. 

111 

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

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

114 

115 app = Flask('yourapplication') 

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

117 

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

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

120 painful. Certain extensions can make assumptions based on the 

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

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

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

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

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

126 `yourapplication.views.frontend`) 

127 

128 .. versionadded:: 0.7 

129 The `static_url_path`, `static_folder`, and `template_folder` 

130 parameters were added. 

131 

132 .. versionadded:: 0.8 

133 The `instance_path` and `instance_relative_config` parameters were 

134 added. 

135 

136 .. versionadded:: 0.11 

137 The `root_path` parameter was added. 

138 

139 .. versionadded:: 1.0 

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

141 

142 .. versionadded:: 1.0 

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

144 matching needs to be enabled manually now. Setting 

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

146 

147 :param import_name: the name of the application package 

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

149 static files on the web. Defaults to the name 

150 of the `static_folder` folder. 

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

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

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

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

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

156 with a ``static_folder`` configured. 

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

158 Defaults to False. 

159 :param subdomain_matching: consider the subdomain relative to 

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

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

162 be used by the application. Defaults to 

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

164 application. 

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

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

167 package or module is assumed to be the instance 

168 path. 

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

170 for loading the config are assumed to 

171 be relative to the instance path instead 

172 of the application root. 

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

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

175 automatically, such as for namespace packages. 

176 """ 

177 

178 default_config = ImmutableDict( 

179 { 

180 "DEBUG": None, 

181 "TESTING": False, 

182 "PROPAGATE_EXCEPTIONS": None, 

183 "SECRET_KEY": None, 

184 "SECRET_KEY_FALLBACKS": None, 

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

186 "USE_X_SENDFILE": False, 

187 "TRUSTED_HOSTS": None, 

188 "SERVER_NAME": None, 

189 "APPLICATION_ROOT": "/", 

190 "SESSION_COOKIE_NAME": "session", 

191 "SESSION_COOKIE_DOMAIN": None, 

192 "SESSION_COOKIE_PATH": None, 

193 "SESSION_COOKIE_HTTPONLY": True, 

194 "SESSION_COOKIE_SECURE": False, 

195 "SESSION_COOKIE_PARTITIONED": False, 

196 "SESSION_COOKIE_SAMESITE": None, 

197 "SESSION_REFRESH_EACH_REQUEST": True, 

198 "MAX_CONTENT_LENGTH": None, 

199 "MAX_FORM_MEMORY_SIZE": 500_000, 

200 "MAX_FORM_PARTS": 1_000, 

201 "SEND_FILE_MAX_AGE_DEFAULT": None, 

202 "TRAP_BAD_REQUEST_ERRORS": None, 

203 "TRAP_HTTP_EXCEPTIONS": False, 

204 "EXPLAIN_TEMPLATE_LOADING": False, 

205 "PREFERRED_URL_SCHEME": "http", 

206 "TEMPLATES_AUTO_RELOAD": None, 

207 "MAX_COOKIE_SIZE": 4093, 

208 "PROVIDE_AUTOMATIC_OPTIONS": True, 

209 } 

210 ) 

211 

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

213 #: for more information. 

214 request_class: type[Request] = Request 

215 

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

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

218 response_class: type[Response] = Response 

219 

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

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

222 #: 

223 #: .. versionadded:: 0.8 

224 session_interface: SessionInterface = SecureCookieSessionInterface() 

225 

226 def __init__( 

227 self, 

228 import_name: str, 

229 static_url_path: str | None = None, 

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

231 static_host: str | None = None, 

232 host_matching: bool = False, 

233 subdomain_matching: bool = False, 

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

235 instance_path: str | None = None, 

236 instance_relative_config: bool = False, 

237 root_path: str | None = None, 

238 ): 

239 super().__init__( 

240 import_name=import_name, 

241 static_url_path=static_url_path, 

242 static_folder=static_folder, 

243 static_host=static_host, 

244 host_matching=host_matching, 

245 subdomain_matching=subdomain_matching, 

246 template_folder=template_folder, 

247 instance_path=instance_path, 

248 instance_relative_config=instance_relative_config, 

249 root_path=root_path, 

250 ) 

251 

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

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

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

255 #: been registered. 

256 self.cli = cli.AppGroup() 

257 

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

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

260 self.cli.name = self.name 

261 

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

263 # and static_folder if there is a configured static_folder. 

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

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

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

267 if self.has_static_folder: 

268 assert bool(static_host) == host_matching, ( 

269 "Invalid static_host/host_matching combination" 

270 ) 

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

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

273 self_ref = weakref.ref(self) 

274 self.add_url_rule( 

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

276 endpoint="static", 

277 host=static_host, 

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

279 ) 

280 

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

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

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

284 

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

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

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

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

289 

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

291 class. 

292 

293 .. versionchanged:: 2.0 

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

295 

296 .. versionadded:: 0.9 

297 """ 

298 value = current_app.config["SEND_FILE_MAX_AGE_DEFAULT"] 

299 

300 if value is None: 

301 return None 

302 

303 if isinstance(value, timedelta): 

304 return int(value.total_seconds()) 

305 

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

307 

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

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

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

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

312 set. 

313 

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

315 class. 

316 

317 .. versionadded:: 0.5 

318 

319 """ 

320 if not self.has_static_folder: 

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

322 

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

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

325 max_age = self.get_send_file_max_age(filename) 

326 return send_from_directory( 

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

328 ) 

329 

330 def open_resource( 

331 self, resource: str, mode: str = "rb", encoding: str | None = None 

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

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

334 

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

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

337 with: 

338 

339 .. code-block:: python 

340 

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

342 conn.executescript(f.read()) 

343 

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

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

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

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

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

349 

350 .. versionchanged:: 3.1 

351 Added the ``encoding`` parameter. 

352 """ 

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

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

355 

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

357 

358 if mode == "rb": 

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

360 

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

362 

363 def open_instance_resource( 

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

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

366 """Open a resource file relative to the application's instance folder 

367 :attr:`instance_path`. Unlike :meth:`open_resource`, files in the 

368 instance folder can be opened for writing. 

369 

370 :param resource: Path to the resource relative to :attr:`instance_path`. 

371 :param mode: Open the file in this mode. 

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

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

374 

375 .. versionchanged:: 3.1 

376 Added the ``encoding`` parameter. 

377 """ 

378 path = os.path.join(self.instance_path, resource) 

379 

380 if "b" in mode: 

381 return open(path, mode) 

382 

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

384 

385 def create_jinja_environment(self) -> Environment: 

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

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

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

389 Flask-related globals and filters to the environment. 

390 

391 .. versionchanged:: 0.11 

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

393 ``TEMPLATES_AUTO_RELOAD`` configuration option. 

394 

395 .. versionadded:: 0.5 

396 """ 

397 options = dict(self.jinja_options) 

398 

399 if "autoescape" not in options: 

400 options["autoescape"] = self.select_jinja_autoescape 

401 

402 if "auto_reload" not in options: 

403 auto_reload = self.config["TEMPLATES_AUTO_RELOAD"] 

404 

405 if auto_reload is None: 

406 auto_reload = self.debug 

407 

408 options["auto_reload"] = auto_reload 

409 

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

411 rv.globals.update( 

412 url_for=self.url_for, 

413 get_flashed_messages=get_flashed_messages, 

414 config=self.config, 

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

416 # context processor for efficiency reasons but for imported 

417 # templates we also want the proxies in there. 

418 request=request, 

419 session=session, 

420 g=g, 

421 ) 

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

423 return rv 

424 

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

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

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

428 up so the request is passed explicitly. 

429 

430 .. versionchanged:: 3.1 

431 If :data:`SERVER_NAME` is set, it does not restrict requests to 

432 only that domain, for both ``subdomain_matching`` and 

433 ``host_matching``. 

434 

435 .. versionchanged:: 1.0 

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

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

438 

439 .. versionchanged:: 0.9 

440 This can be called outside a request when the URL adapter is created 

441 for an application context. 

442 

443 .. versionadded:: 0.6 

444 """ 

445 if request is not None: 

446 if (trusted_hosts := self.config["TRUSTED_HOSTS"]) is not None: 

447 request.trusted_hosts = trusted_hosts 

448 

449 # Check trusted_hosts here until bind_to_environ does. 

450 request.host = get_host(request.environ, request.trusted_hosts) # pyright: ignore 

451 subdomain = None 

452 server_name = self.config["SERVER_NAME"] 

453 

454 if self.url_map.host_matching: 

455 # Don't pass SERVER_NAME, otherwise it's used and the actual 

456 # host is ignored, which breaks host matching. 

457 server_name = None 

458 elif not self.subdomain_matching: 

459 # Werkzeug doesn't implement subdomain matching yet. Until then, 

460 # disable it by forcing the current subdomain to the default, or 

461 # the empty string. 

462 subdomain = self.url_map.default_subdomain or "" 

463 

464 return self.url_map.bind_to_environ( 

465 request.environ, server_name=server_name, subdomain=subdomain 

466 ) 

467 

468 # Need at least SERVER_NAME to match/build outside a request. 

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

470 return self.url_map.bind( 

471 self.config["SERVER_NAME"], 

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

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

474 ) 

475 

476 return None 

477 

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

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

480 

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

482 an error if the body will be discarded. 

483 

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

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

486 body. 

487 

488 .. versionchanged:: 2.1 

489 Don't intercept 307 and 308 redirects. 

490 

491 :meta private: 

492 :internal: 

493 """ 

494 if ( 

495 not self.debug 

496 or not isinstance(request.routing_exception, RequestRedirect) 

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

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

499 ): 

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

501 

502 from .debughelpers import FormDataRoutingRedirect 

503 

504 raise FormDataRoutingRedirect(request) 

505 

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

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

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

509 context as well as everything template context processors want 

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

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

512 decides to return a value with the same key. 

513 

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

515 to add extra variables. 

516 """ 

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

518 

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

520 if request: 

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

522 

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

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

525 orig_ctx = context.copy() 

526 

527 for name in names: 

528 if name in self.template_context_processors: 

529 for func in self.template_context_processors[name]: 

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

531 

532 context.update(orig_ctx) 

533 

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

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

536 application. This runs all the registered shell context 

537 processors. 

538 

539 .. versionadded:: 0.11 

540 """ 

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

542 for processor in self.shell_context_processors: 

543 rv.update(processor()) 

544 return rv 

545 

546 def run( 

547 self, 

548 host: str | None = None, 

549 port: int | None = None, 

550 debug: bool | None = None, 

551 load_dotenv: bool = True, 

552 **options: t.Any, 

553 ) -> None: 

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

555 

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

557 meet security and performance requirements for a production server. 

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

559 

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

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

562 

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

564 code execution on the interactive debugger, you can pass 

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

566 traceback screen active, but disable code execution. 

567 

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

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

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

571 

572 .. admonition:: Keep in Mind 

573 

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

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

576 interactive debugger without the code reloading, you have to 

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

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

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

580 catch. 

581 

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

583 have the server available externally as well. Defaults to 

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

585 if present. 

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

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

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

589 :attr:`debug`. 

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

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

592 directory to the directory containing the first file found. 

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

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

595 information. 

596 

597 .. versionchanged:: 1.0 

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

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

600 

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

602 

603 Threaded mode is enabled by default. 

604 

605 .. versionchanged:: 0.10 

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

607 variable. 

608 """ 

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

610 # the 'flask run' command is used. 

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

612 if not is_running_from_reloader(): 

613 click.secho( 

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

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

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

617 ' "__main__"\' guard.', 

618 fg="red", 

619 ) 

620 

621 return 

622 

623 if get_load_dotenv(load_dotenv): 

624 cli.load_dotenv() 

625 

626 # if set, env var overrides existing value 

627 if "FLASK_DEBUG" in os.environ: 

628 self.debug = get_debug_flag() 

629 

630 # debug passed to method overrides all other sources 

631 if debug is not None: 

632 self.debug = bool(debug) 

633 

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

635 sn_host = sn_port = None 

636 

637 if server_name: 

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

639 

640 if not host: 

641 if sn_host: 

642 host = sn_host 

643 else: 

644 host = "127.0.0.1" 

645 

646 if port or port == 0: 

647 port = int(port) 

648 elif sn_port: 

649 port = int(sn_port) 

650 else: 

651 port = 5000 

652 

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

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

655 options.setdefault("threaded", True) 

656 

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

658 

659 from werkzeug.serving import run_simple 

660 

661 try: 

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

663 finally: 

664 # reset the first request information if the development server 

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

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

667 self._got_first_request = False 

668 

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

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

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

672 

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

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

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

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

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

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

679 attribute. For example:: 

680 

681 app.testing = True 

682 client = app.test_client() 

683 

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

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

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

687 

688 with app.test_client() as c: 

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

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

691 

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

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

694 For example:: 

695 

696 from flask.testing import FlaskClient 

697 

698 class CustomClient(FlaskClient): 

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

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

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

702 

703 app.test_client_class = CustomClient 

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

705 

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

707 

708 .. versionchanged:: 0.4 

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

710 

711 .. versionadded:: 0.7 

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

713 to override the client to be used by setting the 

714 :attr:`test_client_class` attribute. 

715 

716 .. versionchanged:: 0.11 

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

718 the constructor of :attr:`test_client_class`. 

719 """ 

720 cls = self.test_client_class 

721 if cls is None: 

722 from .testing import FlaskClient as cls 

723 return cls( # type: ignore 

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

725 ) 

726 

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

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

729 See :ref:`testing-cli`. 

730 

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

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

733 passed as the first argument. 

734 

735 .. versionadded:: 1.0 

736 """ 

737 cls = self.test_cli_runner_class 

738 

739 if cls is None: 

740 from .testing import FlaskCliRunner as cls 

741 

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

743 

744 def handle_http_exception( 

745 self, e: HTTPException 

746 ) -> HTTPException | ft.ResponseReturnValue: 

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

748 registered error handlers and fall back to returning the 

749 exception as response. 

750 

751 .. versionchanged:: 1.0.3 

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

753 slash redirects during routing, is not passed to error 

754 handlers. 

755 

756 .. versionchanged:: 1.0 

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

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

759 handler for the base ``HTTPException``. 

760 

761 .. versionadded:: 0.3 

762 """ 

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

764 # those unchanged as errors 

765 if e.code is None: 

766 return e 

767 

768 # RoutingExceptions are used internally to trigger routing 

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

770 # are not raised or handled in user code. 

771 if isinstance(e, RoutingException): 

772 return e 

773 

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

775 if handler is None: 

776 return e 

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

778 

779 def handle_user_exception( 

780 self, e: Exception 

781 ) -> HTTPException | ft.ResponseReturnValue: 

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

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

784 .exceptions.HTTPException` which is forwarded to the 

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

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

787 traceback. 

788 

789 .. versionchanged:: 1.0 

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

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

792 message. 

793 

794 .. versionadded:: 0.7 

795 """ 

796 if isinstance(e, BadRequestKeyError) and ( 

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

798 ): 

799 e.show_exception = True 

800 

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

802 return self.handle_http_exception(e) 

803 

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

805 

806 if handler is None: 

807 raise 

808 

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

810 

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

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

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

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

815 

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

817 

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

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

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

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

822 

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

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

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

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

827 

828 .. versionchanged:: 1.1.0 

829 Always passes the ``InternalServerError`` instance to the 

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

831 error. 

832 

833 .. versionchanged:: 1.1.0 

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

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

836 

837 .. versionadded:: 0.3 

838 """ 

839 exc_info = sys.exc_info() 

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

841 propagate = self.config["PROPAGATE_EXCEPTIONS"] 

842 

843 if propagate is None: 

844 propagate = self.testing or self.debug 

845 

846 if propagate: 

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

848 # raise the passed in exception. 

849 if exc_info[1] is e: 

850 raise 

851 

852 raise e 

853 

854 self.log_exception(exc_info) 

855 server_error: InternalServerError | ft.ResponseReturnValue 

856 server_error = InternalServerError(original_exception=e) 

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

858 

859 if handler is not None: 

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

861 

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

863 

864 def log_exception( 

865 self, 

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

867 ) -> None: 

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

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

870 The default implementation logs the exception as error on the 

871 :attr:`logger`. 

872 

873 .. versionadded:: 0.8 

874 """ 

875 self.logger.error( 

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

877 ) 

878 

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

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

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

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

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

884 

885 .. versionchanged:: 0.7 

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

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

888 """ 

889 req = request_ctx.request 

890 if req.routing_exception is not None: 

891 self.raise_routing_exception(req) 

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

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

894 # request came with the OPTIONS method, reply automatically 

895 if ( 

896 getattr(rule, "provide_automatic_options", False) 

897 and req.method == "OPTIONS" 

898 ): 

899 return self.make_default_options_response() 

900 # otherwise dispatch to the handler for that endpoint 

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

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

903 

904 def full_dispatch_request(self) -> Response: 

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

906 pre and postprocessing as well as HTTP exception catching and 

907 error handling. 

908 

909 .. versionadded:: 0.7 

910 """ 

911 self._got_first_request = True 

912 

913 try: 

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

915 rv = self.preprocess_request() 

916 if rv is None: 

917 rv = self.dispatch_request() 

918 except Exception as e: 

919 rv = self.handle_user_exception(e) 

920 return self.finalize_request(rv) 

921 

922 def finalize_request( 

923 self, 

924 rv: ft.ResponseReturnValue | HTTPException, 

925 from_error_handler: bool = False, 

926 ) -> Response: 

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

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

929 postprocessing functions. This is invoked for both normal 

930 request dispatching as well as error handlers. 

931 

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

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

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

935 response processing will be logged and otherwise ignored. 

936 

937 :internal: 

938 """ 

939 response = self.make_response(rv) 

940 try: 

941 response = self.process_response(response) 

942 request_finished.send( 

943 self, _async_wrapper=self.ensure_sync, response=response 

944 ) 

945 except Exception: 

946 if not from_error_handler: 

947 raise 

948 self.logger.exception( 

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

950 ) 

951 return response 

952 

953 def make_default_options_response(self) -> Response: 

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

955 This can be changed through subclassing to change the default 

956 behavior of ``OPTIONS`` responses. 

957 

958 .. versionadded:: 0.7 

959 """ 

960 adapter = request_ctx.url_adapter 

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

962 rv = self.response_class() 

963 rv.allow.update(methods) 

964 return rv 

965 

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

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

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

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

970 

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

972 

973 .. versionadded:: 2.0 

974 """ 

975 if iscoroutinefunction(func): 

976 return self.async_to_sync(func) 

977 

978 return func 

979 

980 def async_to_sync( 

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

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

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

984 

985 .. code-block:: python 

986 

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

988 

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

990 to be synchronously callable. 

991 

992 .. versionadded:: 2.0 

993 """ 

994 try: 

995 from asgiref.sync import async_to_sync as asgiref_async_to_sync 

996 except ImportError: 

997 raise RuntimeError( 

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

999 ) from None 

1000 

1001 return asgiref_async_to_sync(func) 

1002 

1003 def url_for( 

1004 self, 

1005 /, 

1006 endpoint: str, 

1007 *, 

1008 _anchor: str | None = None, 

1009 _method: str | None = None, 

1010 _scheme: str | None = None, 

1011 _external: bool | None = None, 

1012 **values: t.Any, 

1013 ) -> str: 

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

1015 

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

1017 directly as well. 

1018 

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

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

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

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

1023 endpoint. 

1024 

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

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

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

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

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

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

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

1032 

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

1034 keyword arguments before the URL is built. 

1035 

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

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

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

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

1040 

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

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

1043 name (if any) will be used. 

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

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

1046 method for the endpoint. 

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

1048 is external. 

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

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

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

1052 request, URLs are external by default. 

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

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

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

1056 

1057 .. versionadded:: 2.2 

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

1059 """ 

1060 req_ctx = _cv_request.get(None) 

1061 

1062 if req_ctx is not None: 

1063 url_adapter = req_ctx.url_adapter 

1064 blueprint_name = req_ctx.request.blueprint 

1065 

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

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

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

1069 if blueprint_name is not None: 

1070 endpoint = f"{blueprint_name}{endpoint}" 

1071 else: 

1072 endpoint = endpoint[1:] 

1073 

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

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

1076 if _external is None: 

1077 _external = _scheme is not None 

1078 else: 

1079 app_ctx = _cv_app.get(None) 

1080 

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

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

1083 # directly, build an adapter. 

1084 if app_ctx is not None: 

1085 url_adapter = app_ctx.url_adapter 

1086 else: 

1087 url_adapter = self.create_url_adapter(None) 

1088 

1089 if url_adapter is None: 

1090 raise RuntimeError( 

1091 "Unable to build URLs outside an active request" 

1092 " without 'SERVER_NAME' configured. Also configure" 

1093 " 'APPLICATION_ROOT' and 'PREFERRED_URL_SCHEME' as" 

1094 " needed." 

1095 ) 

1096 

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

1098 # domain by default. 

1099 if _external is None: 

1100 _external = True 

1101 

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

1103 # to avoid accidental insecure URLs. 

1104 if _scheme is not None and not _external: 

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

1106 

1107 self.inject_url_defaults(endpoint, values) 

1108 

1109 try: 

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

1111 endpoint, 

1112 values, 

1113 method=_method, 

1114 url_scheme=_scheme, 

1115 force_external=_external, 

1116 ) 

1117 except BuildError as error: 

1118 values.update( 

1119 _anchor=_anchor, _method=_method, _scheme=_scheme, _external=_external 

1120 ) 

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

1122 

1123 if _anchor is not None: 

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

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

1126 

1127 return rv 

1128 

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

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

1131 :attr:`response_class`. 

1132 

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

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

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

1136 for ``view_rv``: 

1137 

1138 ``str`` 

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

1140 as the body. 

1141 

1142 ``bytes`` 

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

1144 

1145 ``dict`` 

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

1147 

1148 ``list`` 

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

1150 

1151 ``generator`` or ``iterator`` 

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

1153 streamed as the response. 

1154 

1155 ``tuple`` 

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

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

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

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

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

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

1162 extended. 

1163 

1164 :attr:`response_class` 

1165 The object is returned unchanged. 

1166 

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

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

1169 

1170 :func:`callable` 

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

1172 used to create a response object. 

1173 

1174 .. versionchanged:: 2.2 

1175 A generator will be converted to a streaming response. 

1176 A list will be converted to a JSON response. 

1177 

1178 .. versionchanged:: 1.1 

1179 A dict will be converted to a JSON response. 

1180 

1181 .. versionchanged:: 0.9 

1182 Previously a tuple was interpreted as the arguments for the 

1183 response object. 

1184 """ 

1185 

1186 status: int | None = None 

1187 headers: HeadersValue | None = None 

1188 

1189 # unpack tuple returns 

1190 if isinstance(rv, tuple): 

1191 len_rv = len(rv) 

1192 

1193 # a 3-tuple is unpacked directly 

1194 if len_rv == 3: 

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

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

1197 elif len_rv == 2: 

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

1199 rv, headers = rv # pyright: ignore 

1200 else: 

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

1202 # other sized tuples are not allowed 

1203 else: 

1204 raise TypeError( 

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

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

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

1208 ) 

1209 

1210 # the body must not be None 

1211 if rv is None: 

1212 raise TypeError( 

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

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

1215 " None or ended without a return statement." 

1216 ) 

1217 

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

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

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

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

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

1223 # special logic 

1224 rv = self.response_class( 

1225 rv, # pyright: ignore 

1226 status=status, 

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

1228 ) 

1229 status = headers = None 

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

1231 rv = self.json.response(rv) 

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

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

1234 # class to the correct type 

1235 try: 

1236 rv = self.response_class.force_type( 

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

1238 request.environ, 

1239 ) 

1240 except TypeError as e: 

1241 raise TypeError( 

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

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

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

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

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

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

1248 else: 

1249 raise TypeError( 

1250 "The view function did not return a valid" 

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

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

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

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

1255 ) 

1256 

1257 rv = t.cast(Response, rv) 

1258 # prefer the status if it was provided 

1259 if status is not None: 

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

1261 rv.status = status 

1262 else: 

1263 rv.status_code = status 

1264 

1265 # extend existing headers with provided headers 

1266 if headers: 

1267 rv.headers.update(headers) 

1268 

1269 return rv 

1270 

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

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

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

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

1275 registered with the app and the blueprint. 

1276 

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

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

1279 further request handling is stopped. 

1280 """ 

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

1282 

1283 for name in names: 

1284 if name in self.url_value_preprocessors: 

1285 for url_func in self.url_value_preprocessors[name]: 

1286 url_func(request.endpoint, request.view_args) 

1287 

1288 for name in names: 

1289 if name in self.before_request_funcs: 

1290 for before_func in self.before_request_funcs[name]: 

1291 rv = self.ensure_sync(before_func)() 

1292 

1293 if rv is not None: 

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

1295 

1296 return None 

1297 

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

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

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

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

1302 

1303 .. versionchanged:: 0.5 

1304 As of Flask 0.5 the functions registered for after request 

1305 execution are called in reverse order of registration. 

1306 

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

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

1309 instance of :attr:`response_class`. 

1310 """ 

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

1312 

1313 for func in ctx._after_request_functions: 

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

1315 

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

1317 if name in self.after_request_funcs: 

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

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

1320 

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

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

1323 

1324 return response 

1325 

1326 def do_teardown_request( 

1327 self, 

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

1329 ) -> None: 

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

1331 returned, right before the request context is popped. 

1332 

1333 This calls all functions decorated with 

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

1335 if a blueprint handled the request. Finally, the 

1336 :data:`request_tearing_down` signal is sent. 

1337 

1338 This is called by 

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

1340 which may be delayed during testing to maintain access to 

1341 resources. 

1342 

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

1344 request. Detected from the current exception information if 

1345 not passed. Passed to each teardown function. 

1346 

1347 .. versionchanged:: 0.9 

1348 Added the ``exc`` argument. 

1349 """ 

1350 if exc is _sentinel: 

1351 exc = sys.exc_info()[1] 

1352 

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

1354 if name in self.teardown_request_funcs: 

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

1356 self.ensure_sync(func)(exc) 

1357 

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

1359 

1360 def do_teardown_appcontext( 

1361 self, 

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

1363 ) -> None: 

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

1365 

1366 When handling a request, the application context is popped 

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

1368 

1369 This calls all functions decorated with 

1370 :meth:`teardown_appcontext`. Then the 

1371 :data:`appcontext_tearing_down` signal is sent. 

1372 

1373 This is called by 

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

1375 

1376 .. versionadded:: 0.9 

1377 """ 

1378 if exc is _sentinel: 

1379 exc = sys.exc_info()[1] 

1380 

1381 for func in reversed(self.teardown_appcontext_funcs): 

1382 self.ensure_sync(func)(exc) 

1383 

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

1385 

1386 def app_context(self) -> AppContext: 

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

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

1389 point at this application. 

1390 

1391 An application context is automatically pushed by 

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

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

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

1395 

1396 :: 

1397 

1398 with app.app_context(): 

1399 init_db() 

1400 

1401 See :doc:`/appcontext`. 

1402 

1403 .. versionadded:: 0.9 

1404 """ 

1405 return AppContext(self) 

1406 

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

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

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

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

1411 

1412 See :doc:`/reqcontext`. 

1413 

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

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

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

1417 an environment and context instead of this method. 

1418 

1419 :param environ: a WSGI environment 

1420 """ 

1421 return RequestContext(self, environ) 

1422 

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

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

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

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

1427 request data without dispatching a full request. 

1428 

1429 See :doc:`/reqcontext`. 

1430 

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

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

1433 environment. :: 

1434 

1435 with app.test_request_context(...): 

1436 generate_report() 

1437 

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

1439 context manually to avoid indentation. :: 

1440 

1441 ctx = app.test_request_context(...) 

1442 ctx.push() 

1443 ... 

1444 ctx.pop() 

1445 

1446 Takes the same arguments as Werkzeug's 

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

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

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

1450 

1451 :param path: URL path being requested. 

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

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

1454 :data:`PREFERRED_URL_SCHEME`, ``subdomain``, 

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

1456 :param subdomain: Subdomain name to append to 

1457 :data:`SERVER_NAME`. 

1458 :param url_scheme: Scheme to use instead of 

1459 :data:`PREFERRED_URL_SCHEME`. 

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

1461 form keys and values. 

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

1463 ``data``. Also defaults ``content_type`` to 

1464 ``application/json``. 

1465 :param args: other positional arguments passed to 

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

1467 :param kwargs: other keyword arguments passed to 

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

1469 """ 

1470 from .testing import EnvironBuilder 

1471 

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

1473 

1474 try: 

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

1476 finally: 

1477 builder.close() 

1478 

1479 def wsgi_app( 

1480 self, environ: WSGIEnvironment, start_response: StartResponse 

1481 ) -> cabc.Iterable[bytes]: 

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

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

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

1485 

1486 app = MyMiddleware(app) 

1487 

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

1489 

1490 app.wsgi_app = MyMiddleware(app.wsgi_app) 

1491 

1492 Then you still have the original application object around and 

1493 can continue to call methods on it. 

1494 

1495 .. versionchanged:: 0.7 

1496 Teardown events for the request and app contexts are called 

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

1498 called depending on when an error occurs during dispatch. 

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

1500 

1501 :param environ: A WSGI environment. 

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

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

1504 start the response. 

1505 """ 

1506 ctx = self.request_context(environ) 

1507 error: BaseException | None = None 

1508 try: 

1509 try: 

1510 ctx.push() 

1511 response = self.full_dispatch_request() 

1512 except Exception as e: 

1513 error = e 

1514 response = self.handle_exception(e) 

1515 except: # noqa: B001 

1516 error = sys.exc_info()[1] 

1517 raise 

1518 return response(environ, start_response) 

1519 finally: 

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

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

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

1523 

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

1525 error = None 

1526 

1527 ctx.pop(error) 

1528 

1529 def __call__( 

1530 self, environ: WSGIEnvironment, start_response: StartResponse 

1531 ) -> cabc.Iterable[bytes]: 

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

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

1534 wrapped to apply middleware. 

1535 """ 

1536 return self.wsgi_app(environ, start_response)