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

235 statements  

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

1from __future__ import annotations 

2 

3import logging 

4import os 

5import sys 

6import typing as t 

7from datetime import timedelta 

8from itertools import chain 

9 

10from werkzeug.exceptions import Aborter 

11from werkzeug.exceptions import BadRequest 

12from werkzeug.exceptions import BadRequestKeyError 

13from werkzeug.routing import BuildError 

14from werkzeug.routing import Map 

15from werkzeug.routing import Rule 

16from werkzeug.sansio.response import Response 

17from werkzeug.utils import cached_property 

18from werkzeug.utils import redirect as _wz_redirect 

19 

20from .. import typing as ft 

21from ..config import Config 

22from ..config import ConfigAttribute 

23from ..ctx import _AppCtxGlobals 

24from ..helpers import _split_blueprint_path 

25from ..helpers import get_debug_flag 

26from ..json.provider import DefaultJSONProvider 

27from ..json.provider import JSONProvider 

28from ..logging import create_logger 

29from ..templating import DispatchingJinjaLoader 

30from ..templating import Environment 

31from .scaffold import _endpoint_from_view_func 

32from .scaffold import find_package 

33from .scaffold import Scaffold 

34from .scaffold import setupmethod 

35 

36if t.TYPE_CHECKING: # pragma: no cover 

37 from werkzeug.wrappers import Response as BaseResponse 

38 

39 from ..testing import FlaskClient 

40 from ..testing import FlaskCliRunner 

41 from .blueprints import Blueprint 

42 

43T_shell_context_processor = t.TypeVar( 

44 "T_shell_context_processor", bound=ft.ShellContextProcessorCallable 

45) 

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

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

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

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

50 

51 

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

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

54 return value 

55 

56 return timedelta(seconds=value) 

57 

58 

59class App(Scaffold): 

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

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

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

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

64 

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

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

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

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

69 

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

71 

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

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

74 

75 from flask import Flask 

76 app = Flask(__name__) 

77 

78 .. admonition:: About the First Parameter 

79 

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

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

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

83 information and a lot more. 

84 

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

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

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

88 your package there. 

89 

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

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

92 

93 app = Flask('yourapplication') 

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

95 

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

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

98 painful. Certain extensions can make assumptions based on the 

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

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

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

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

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

104 `yourapplication.views.frontend`) 

105 

106 .. versionadded:: 0.7 

107 The `static_url_path`, `static_folder`, and `template_folder` 

108 parameters were added. 

109 

110 .. versionadded:: 0.8 

111 The `instance_path` and `instance_relative_config` parameters were 

112 added. 

113 

114 .. versionadded:: 0.11 

115 The `root_path` parameter was added. 

116 

117 .. versionadded:: 1.0 

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

119 

120 .. versionadded:: 1.0 

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

122 matching needs to be enabled manually now. Setting 

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

124 

125 :param import_name: the name of the application package 

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

127 static files on the web. Defaults to the name 

128 of the `static_folder` folder. 

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

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

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

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

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

134 with a ``static_folder`` configured. 

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

136 Defaults to False. 

137 :param subdomain_matching: consider the subdomain relative to 

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

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

140 be used by the application. Defaults to 

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

142 application. 

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

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

145 package or module is assumed to be the instance 

146 path. 

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

148 for loading the config are assumed to 

149 be relative to the instance path instead 

150 of the application root. 

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

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

153 automatically, such as for namespace packages. 

154 """ 

155 

156 #: The class of the object assigned to :attr:`aborter`, created by 

157 #: :meth:`create_aborter`. That object is called by 

158 #: :func:`flask.abort` to raise HTTP errors, and can be 

159 #: called directly as well. 

160 #: 

161 #: Defaults to :class:`werkzeug.exceptions.Aborter`. 

162 #: 

163 #: .. versionadded:: 2.2 

164 aborter_class = Aborter 

165 

166 #: The class that is used for the Jinja environment. 

167 #: 

168 #: .. versionadded:: 0.11 

169 jinja_environment = Environment 

170 

171 #: The class that is used for the :data:`~flask.g` instance. 

172 #: 

173 #: Example use cases for a custom class: 

174 #: 

175 #: 1. Store arbitrary attributes on flask.g. 

176 #: 2. Add a property for lazy per-request database connectors. 

177 #: 3. Return None instead of AttributeError on unexpected attributes. 

178 #: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g. 

179 #: 

180 #: In Flask 0.9 this property was called `request_globals_class` but it 

181 #: was changed in 0.10 to :attr:`app_ctx_globals_class` because the 

182 #: flask.g object is now application context scoped. 

183 #: 

184 #: .. versionadded:: 0.10 

185 app_ctx_globals_class = _AppCtxGlobals 

186 

187 #: The class that is used for the ``config`` attribute of this app. 

188 #: Defaults to :class:`~flask.Config`. 

189 #: 

190 #: Example use cases for a custom class: 

191 #: 

192 #: 1. Default values for certain config options. 

193 #: 2. Access to config values through attributes in addition to keys. 

194 #: 

195 #: .. versionadded:: 0.11 

196 config_class = Config 

197 

198 #: The testing flag. Set this to ``True`` to enable the test mode of 

199 #: Flask extensions (and in the future probably also Flask itself). 

200 #: For example this might activate test helpers that have an 

201 #: additional runtime cost which should not be enabled by default. 

202 #: 

203 #: If this is enabled and PROPAGATE_EXCEPTIONS is not changed from the 

204 #: default it's implicitly enabled. 

205 #: 

206 #: This attribute can also be configured from the config with the 

207 #: ``TESTING`` configuration key. Defaults to ``False``. 

208 testing = ConfigAttribute[bool]("TESTING") 

209 

210 #: If a secret key is set, cryptographic components can use this to 

211 #: sign cookies and other things. Set this to a complex random value 

212 #: when you want to use the secure cookie for instance. 

213 #: 

214 #: This attribute can also be configured from the config with the 

215 #: :data:`SECRET_KEY` configuration key. Defaults to ``None``. 

216 secret_key = ConfigAttribute[t.Union[str, bytes, None]]("SECRET_KEY") 

217 

218 #: A :class:`~datetime.timedelta` which is used to set the expiration 

219 #: date of a permanent session. The default is 31 days which makes a 

220 #: permanent session survive for roughly one month. 

221 #: 

222 #: This attribute can also be configured from the config with the 

223 #: ``PERMANENT_SESSION_LIFETIME`` configuration key. Defaults to 

224 #: ``timedelta(days=31)`` 

225 permanent_session_lifetime = ConfigAttribute[timedelta]( 

226 "PERMANENT_SESSION_LIFETIME", 

227 get_converter=_make_timedelta, # type: ignore[arg-type] 

228 ) 

229 

230 json_provider_class: type[JSONProvider] = DefaultJSONProvider 

231 """A subclass of :class:`~flask.json.provider.JSONProvider`. An 

232 instance is created and assigned to :attr:`app.json` when creating 

233 the app. 

234 

235 The default, :class:`~flask.json.provider.DefaultJSONProvider`, uses 

236 Python's built-in :mod:`json` library. A different provider can use 

237 a different JSON library. 

238 

239 .. versionadded:: 2.2 

240 """ 

241 

242 #: Options that are passed to the Jinja environment in 

243 #: :meth:`create_jinja_environment`. Changing these options after 

244 #: the environment is created (accessing :attr:`jinja_env`) will 

245 #: have no effect. 

246 #: 

247 #: .. versionchanged:: 1.1.0 

248 #: This is a ``dict`` instead of an ``ImmutableDict`` to allow 

249 #: easier configuration. 

250 #: 

251 jinja_options: dict[str, t.Any] = {} 

252 

253 #: The rule object to use for URL rules created. This is used by 

254 #: :meth:`add_url_rule`. Defaults to :class:`werkzeug.routing.Rule`. 

255 #: 

256 #: .. versionadded:: 0.7 

257 url_rule_class = Rule 

258 

259 #: The map object to use for storing the URL rules and routing 

260 #: configuration parameters. Defaults to :class:`werkzeug.routing.Map`. 

261 #: 

262 #: .. versionadded:: 1.1.0 

263 url_map_class = Map 

264 

265 #: The :meth:`test_client` method creates an instance of this test 

266 #: client class. Defaults to :class:`~flask.testing.FlaskClient`. 

267 #: 

268 #: .. versionadded:: 0.7 

269 test_client_class: type[FlaskClient] | None = None 

270 

271 #: The :class:`~click.testing.CliRunner` subclass, by default 

272 #: :class:`~flask.testing.FlaskCliRunner` that is used by 

273 #: :meth:`test_cli_runner`. Its ``__init__`` method should take a 

274 #: Flask app object as the first argument. 

275 #: 

276 #: .. versionadded:: 1.0 

277 test_cli_runner_class: type[FlaskCliRunner] | None = None 

278 

279 default_config: dict[str, t.Any] 

280 response_class: type[Response] 

281 

282 def __init__( 

283 self, 

284 import_name: str, 

285 static_url_path: str | None = None, 

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

287 static_host: str | None = None, 

288 host_matching: bool = False, 

289 subdomain_matching: bool = False, 

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

291 instance_path: str | None = None, 

292 instance_relative_config: bool = False, 

293 root_path: str | None = None, 

294 ): 

295 super().__init__( 

296 import_name=import_name, 

297 static_folder=static_folder, 

298 static_url_path=static_url_path, 

299 template_folder=template_folder, 

300 root_path=root_path, 

301 ) 

302 

303 if instance_path is None: 

304 instance_path = self.auto_find_instance_path() 

305 elif not os.path.isabs(instance_path): 

306 raise ValueError( 

307 "If an instance path is provided it must be absolute." 

308 " A relative path was given instead." 

309 ) 

310 

311 #: Holds the path to the instance folder. 

312 #: 

313 #: .. versionadded:: 0.8 

314 self.instance_path = instance_path 

315 

316 #: The configuration dictionary as :class:`Config`. This behaves 

317 #: exactly like a regular dictionary but supports additional methods 

318 #: to load a config from files. 

319 self.config = self.make_config(instance_relative_config) 

320 

321 #: An instance of :attr:`aborter_class` created by 

322 #: :meth:`make_aborter`. This is called by :func:`flask.abort` 

323 #: to raise HTTP errors, and can be called directly as well. 

324 #: 

325 #: .. versionadded:: 2.2 

326 #: Moved from ``flask.abort``, which calls this object. 

327 self.aborter = self.make_aborter() 

328 

329 self.json: JSONProvider = self.json_provider_class(self) 

330 """Provides access to JSON methods. Functions in ``flask.json`` 

331 will call methods on this provider when the application context 

332 is active. Used for handling JSON requests and responses. 

333 

334 An instance of :attr:`json_provider_class`. Can be customized by 

335 changing that attribute on a subclass, or by assigning to this 

336 attribute afterwards. 

337 

338 The default, :class:`~flask.json.provider.DefaultJSONProvider`, 

339 uses Python's built-in :mod:`json` library. A different provider 

340 can use a different JSON library. 

341 

342 .. versionadded:: 2.2 

343 """ 

344 

345 #: A list of functions that are called by 

346 #: :meth:`handle_url_build_error` when :meth:`.url_for` raises a 

347 #: :exc:`~werkzeug.routing.BuildError`. Each function is called 

348 #: with ``error``, ``endpoint`` and ``values``. If a function 

349 #: returns ``None`` or raises a ``BuildError``, it is skipped. 

350 #: Otherwise, its return value is returned by ``url_for``. 

351 #: 

352 #: .. versionadded:: 0.9 

353 self.url_build_error_handlers: list[ 

354 t.Callable[[Exception, str, dict[str, t.Any]], str] 

355 ] = [] 

356 

357 #: A list of functions that are called when the application context 

358 #: is destroyed. Since the application context is also torn down 

359 #: if the request ends this is the place to store code that disconnects 

360 #: from databases. 

361 #: 

362 #: .. versionadded:: 0.9 

363 self.teardown_appcontext_funcs: list[ft.TeardownCallable] = [] 

364 

365 #: A list of shell context processor functions that should be run 

366 #: when a shell context is created. 

367 #: 

368 #: .. versionadded:: 0.11 

369 self.shell_context_processors: list[ft.ShellContextProcessorCallable] = [] 

370 

371 #: Maps registered blueprint names to blueprint objects. The 

372 #: dict retains the order the blueprints were registered in. 

373 #: Blueprints can be registered multiple times, this dict does 

374 #: not track how often they were attached. 

375 #: 

376 #: .. versionadded:: 0.7 

377 self.blueprints: dict[str, Blueprint] = {} 

378 

379 #: a place where extensions can store application specific state. For 

380 #: example this is where an extension could store database engines and 

381 #: similar things. 

382 #: 

383 #: The key must match the name of the extension module. For example in 

384 #: case of a "Flask-Foo" extension in `flask_foo`, the key would be 

385 #: ``'foo'``. 

386 #: 

387 #: .. versionadded:: 0.7 

388 self.extensions: dict[str, t.Any] = {} 

389 

390 #: The :class:`~werkzeug.routing.Map` for this instance. You can use 

391 #: this to change the routing converters after the class was created 

392 #: but before any routes are connected. Example:: 

393 #: 

394 #: from werkzeug.routing import BaseConverter 

395 #: 

396 #: class ListConverter(BaseConverter): 

397 #: def to_python(self, value): 

398 #: return value.split(',') 

399 #: def to_url(self, values): 

400 #: return ','.join(super(ListConverter, self).to_url(value) 

401 #: for value in values) 

402 #: 

403 #: app = Flask(__name__) 

404 #: app.url_map.converters['list'] = ListConverter 

405 self.url_map = self.url_map_class(host_matching=host_matching) 

406 

407 self.subdomain_matching = subdomain_matching 

408 

409 # tracks internally if the application already handled at least one 

410 # request. 

411 self._got_first_request = False 

412 

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

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

415 self.cli.name = self.name 

416 

417 def _check_setup_finished(self, f_name: str) -> None: 

418 if self._got_first_request: 

419 raise AssertionError( 

420 f"The setup method '{f_name}' can no longer be called" 

421 " on the application. It has already handled its first" 

422 " request, any changes will not be applied" 

423 " consistently.\n" 

424 "Make sure all imports, decorators, functions, etc." 

425 " needed to set up the application are done before" 

426 " running it." 

427 ) 

428 

429 @cached_property 

430 def name(self) -> str: # type: ignore 

431 """The name of the application. This is usually the import name 

432 with the difference that it's guessed from the run file if the 

433 import name is main. This name is used as a display name when 

434 Flask needs the name of the application. It can be set and overridden 

435 to change the value. 

436 

437 .. versionadded:: 0.8 

438 """ 

439 if self.import_name == "__main__": 

440 fn: str | None = getattr(sys.modules["__main__"], "__file__", None) 

441 if fn is None: 

442 return "__main__" 

443 return os.path.splitext(os.path.basename(fn))[0] 

444 return self.import_name 

445 

446 @cached_property 

447 def logger(self) -> logging.Logger: 

448 """A standard Python :class:`~logging.Logger` for the app, with 

449 the same name as :attr:`name`. 

450 

451 In debug mode, the logger's :attr:`~logging.Logger.level` will 

452 be set to :data:`~logging.DEBUG`. 

453 

454 If there are no handlers configured, a default handler will be 

455 added. See :doc:`/logging` for more information. 

456 

457 .. versionchanged:: 1.1.0 

458 The logger takes the same name as :attr:`name` rather than 

459 hard-coding ``"flask.app"``. 

460 

461 .. versionchanged:: 1.0.0 

462 Behavior was simplified. The logger is always named 

463 ``"flask.app"``. The level is only set during configuration, 

464 it doesn't check ``app.debug`` each time. Only one format is 

465 used, not different ones depending on ``app.debug``. No 

466 handlers are removed, and a handler is only added if no 

467 handlers are already configured. 

468 

469 .. versionadded:: 0.3 

470 """ 

471 return create_logger(self) 

472 

473 @cached_property 

474 def jinja_env(self) -> Environment: 

475 """The Jinja environment used to load templates. 

476 

477 The environment is created the first time this property is 

478 accessed. Changing :attr:`jinja_options` after that will have no 

479 effect. 

480 """ 

481 return self.create_jinja_environment() 

482 

483 def create_jinja_environment(self) -> Environment: 

484 raise NotImplementedError() 

485 

486 def make_config(self, instance_relative: bool = False) -> Config: 

487 """Used to create the config attribute by the Flask constructor. 

488 The `instance_relative` parameter is passed in from the constructor 

489 of Flask (there named `instance_relative_config`) and indicates if 

490 the config should be relative to the instance path or the root path 

491 of the application. 

492 

493 .. versionadded:: 0.8 

494 """ 

495 root_path = self.root_path 

496 if instance_relative: 

497 root_path = self.instance_path 

498 defaults = dict(self.default_config) 

499 defaults["DEBUG"] = get_debug_flag() 

500 return self.config_class(root_path, defaults) 

501 

502 def make_aborter(self) -> Aborter: 

503 """Create the object to assign to :attr:`aborter`. That object 

504 is called by :func:`flask.abort` to raise HTTP errors, and can 

505 be called directly as well. 

506 

507 By default, this creates an instance of :attr:`aborter_class`, 

508 which defaults to :class:`werkzeug.exceptions.Aborter`. 

509 

510 .. versionadded:: 2.2 

511 """ 

512 return self.aborter_class() 

513 

514 def auto_find_instance_path(self) -> str: 

515 """Tries to locate the instance path if it was not provided to the 

516 constructor of the application class. It will basically calculate 

517 the path to a folder named ``instance`` next to your main file or 

518 the package. 

519 

520 .. versionadded:: 0.8 

521 """ 

522 prefix, package_path = find_package(self.import_name) 

523 if prefix is None: 

524 return os.path.join(package_path, "instance") 

525 return os.path.join(prefix, "var", f"{self.name}-instance") 

526 

527 def create_global_jinja_loader(self) -> DispatchingJinjaLoader: 

528 """Creates the loader for the Jinja2 environment. Can be used to 

529 override just the loader and keeping the rest unchanged. It's 

530 discouraged to override this function. Instead one should override 

531 the :meth:`jinja_loader` function instead. 

532 

533 The global loader dispatches between the loaders of the application 

534 and the individual blueprints. 

535 

536 .. versionadded:: 0.7 

537 """ 

538 return DispatchingJinjaLoader(self) 

539 

540 def select_jinja_autoescape(self, filename: str) -> bool: 

541 """Returns ``True`` if autoescaping should be active for the given 

542 template name. If no template name is given, returns `True`. 

543 

544 .. versionchanged:: 2.2 

545 Autoescaping is now enabled by default for ``.svg`` files. 

546 

547 .. versionadded:: 0.5 

548 """ 

549 if filename is None: 

550 return True 

551 return filename.endswith((".html", ".htm", ".xml", ".xhtml", ".svg")) 

552 

553 @property 

554 def debug(self) -> bool: 

555 """Whether debug mode is enabled. When using ``flask run`` to start the 

556 development server, an interactive debugger will be shown for unhandled 

557 exceptions, and the server will be reloaded when code changes. This maps to the 

558 :data:`DEBUG` config key. It may not behave as expected if set late. 

559 

560 **Do not enable debug mode when deploying in production.** 

561 

562 Default: ``False`` 

563 """ 

564 return self.config["DEBUG"] # type: ignore[no-any-return] 

565 

566 @debug.setter 

567 def debug(self, value: bool) -> None: 

568 self.config["DEBUG"] = value 

569 

570 if self.config["TEMPLATES_AUTO_RELOAD"] is None: 

571 self.jinja_env.auto_reload = value 

572 

573 @setupmethod 

574 def register_blueprint(self, blueprint: Blueprint, **options: t.Any) -> None: 

575 """Register a :class:`~flask.Blueprint` on the application. Keyword 

576 arguments passed to this method will override the defaults set on the 

577 blueprint. 

578 

579 Calls the blueprint's :meth:`~flask.Blueprint.register` method after 

580 recording the blueprint in the application's :attr:`blueprints`. 

581 

582 :param blueprint: The blueprint to register. 

583 :param url_prefix: Blueprint routes will be prefixed with this. 

584 :param subdomain: Blueprint routes will match on this subdomain. 

585 :param url_defaults: Blueprint routes will use these default values for 

586 view arguments. 

587 :param options: Additional keyword arguments are passed to 

588 :class:`~flask.blueprints.BlueprintSetupState`. They can be 

589 accessed in :meth:`~flask.Blueprint.record` callbacks. 

590 

591 .. versionchanged:: 2.0.1 

592 The ``name`` option can be used to change the (pre-dotted) 

593 name the blueprint is registered with. This allows the same 

594 blueprint to be registered multiple times with unique names 

595 for ``url_for``. 

596 

597 .. versionadded:: 0.7 

598 """ 

599 blueprint.register(self, options) 

600 

601 def iter_blueprints(self) -> t.ValuesView[Blueprint]: 

602 """Iterates over all blueprints by the order they were registered. 

603 

604 .. versionadded:: 0.11 

605 """ 

606 return self.blueprints.values() 

607 

608 @setupmethod 

609 def add_url_rule( 

610 self, 

611 rule: str, 

612 endpoint: str | None = None, 

613 view_func: ft.RouteCallable | None = None, 

614 provide_automatic_options: bool | None = None, 

615 **options: t.Any, 

616 ) -> None: 

617 if endpoint is None: 

618 endpoint = _endpoint_from_view_func(view_func) # type: ignore 

619 options["endpoint"] = endpoint 

620 methods = options.pop("methods", None) 

621 

622 # if the methods are not given and the view_func object knows its 

623 # methods we can use that instead. If neither exists, we go with 

624 # a tuple of only ``GET`` as default. 

625 if methods is None: 

626 methods = getattr(view_func, "methods", None) or ("GET",) 

627 if isinstance(methods, str): 

628 raise TypeError( 

629 "Allowed methods must be a list of strings, for" 

630 ' example: @app.route(..., methods=["POST"])' 

631 ) 

632 methods = {item.upper() for item in methods} 

633 

634 # Methods that should always be added 

635 required_methods = set(getattr(view_func, "required_methods", ())) 

636 

637 # starting with Flask 0.8 the view_func object can disable and 

638 # force-enable the automatic options handling. 

639 if provide_automatic_options is None: 

640 provide_automatic_options = getattr( 

641 view_func, "provide_automatic_options", None 

642 ) 

643 

644 if provide_automatic_options is None: 

645 if "OPTIONS" not in methods: 

646 provide_automatic_options = True 

647 required_methods.add("OPTIONS") 

648 else: 

649 provide_automatic_options = False 

650 

651 # Add the required methods now. 

652 methods |= required_methods 

653 

654 rule_obj = self.url_rule_class(rule, methods=methods, **options) 

655 rule_obj.provide_automatic_options = provide_automatic_options # type: ignore[attr-defined] 

656 

657 self.url_map.add(rule_obj) 

658 if view_func is not None: 

659 old_func = self.view_functions.get(endpoint) 

660 if old_func is not None and old_func != view_func: 

661 raise AssertionError( 

662 "View function mapping is overwriting an existing" 

663 f" endpoint function: {endpoint}" 

664 ) 

665 self.view_functions[endpoint] = view_func 

666 

667 @setupmethod 

668 def template_filter( 

669 self, name: str | None = None 

670 ) -> t.Callable[[T_template_filter], T_template_filter]: 

671 """A decorator that is used to register custom template filter. 

672 You can specify a name for the filter, otherwise the function 

673 name will be used. Example:: 

674 

675 @app.template_filter() 

676 def reverse(s): 

677 return s[::-1] 

678 

679 :param name: the optional name of the filter, otherwise the 

680 function name will be used. 

681 """ 

682 

683 def decorator(f: T_template_filter) -> T_template_filter: 

684 self.add_template_filter(f, name=name) 

685 return f 

686 

687 return decorator 

688 

689 @setupmethod 

690 def add_template_filter( 

691 self, f: ft.TemplateFilterCallable, name: str | None = None 

692 ) -> None: 

693 """Register a custom template filter. Works exactly like the 

694 :meth:`template_filter` decorator. 

695 

696 :param name: the optional name of the filter, otherwise the 

697 function name will be used. 

698 """ 

699 self.jinja_env.filters[name or f.__name__] = f 

700 

701 @setupmethod 

702 def template_test( 

703 self, name: str | None = None 

704 ) -> t.Callable[[T_template_test], T_template_test]: 

705 """A decorator that is used to register custom template test. 

706 You can specify a name for the test, otherwise the function 

707 name will be used. Example:: 

708 

709 @app.template_test() 

710 def is_prime(n): 

711 if n == 2: 

712 return True 

713 for i in range(2, int(math.ceil(math.sqrt(n))) + 1): 

714 if n % i == 0: 

715 return False 

716 return True 

717 

718 .. versionadded:: 0.10 

719 

720 :param name: the optional name of the test, otherwise the 

721 function name will be used. 

722 """ 

723 

724 def decorator(f: T_template_test) -> T_template_test: 

725 self.add_template_test(f, name=name) 

726 return f 

727 

728 return decorator 

729 

730 @setupmethod 

731 def add_template_test( 

732 self, f: ft.TemplateTestCallable, name: str | None = None 

733 ) -> None: 

734 """Register a custom template test. Works exactly like the 

735 :meth:`template_test` decorator. 

736 

737 .. versionadded:: 0.10 

738 

739 :param name: the optional name of the test, otherwise the 

740 function name will be used. 

741 """ 

742 self.jinja_env.tests[name or f.__name__] = f 

743 

744 @setupmethod 

745 def template_global( 

746 self, name: str | None = None 

747 ) -> t.Callable[[T_template_global], T_template_global]: 

748 """A decorator that is used to register a custom template global function. 

749 You can specify a name for the global function, otherwise the function 

750 name will be used. Example:: 

751 

752 @app.template_global() 

753 def double(n): 

754 return 2 * n 

755 

756 .. versionadded:: 0.10 

757 

758 :param name: the optional name of the global function, otherwise the 

759 function name will be used. 

760 """ 

761 

762 def decorator(f: T_template_global) -> T_template_global: 

763 self.add_template_global(f, name=name) 

764 return f 

765 

766 return decorator 

767 

768 @setupmethod 

769 def add_template_global( 

770 self, f: ft.TemplateGlobalCallable, name: str | None = None 

771 ) -> None: 

772 """Register a custom template global function. Works exactly like the 

773 :meth:`template_global` decorator. 

774 

775 .. versionadded:: 0.10 

776 

777 :param name: the optional name of the global function, otherwise the 

778 function name will be used. 

779 """ 

780 self.jinja_env.globals[name or f.__name__] = f 

781 

782 @setupmethod 

783 def teardown_appcontext(self, f: T_teardown) -> T_teardown: 

784 """Registers a function to be called when the application 

785 context is popped. The application context is typically popped 

786 after the request context for each request, at the end of CLI 

787 commands, or after a manually pushed context ends. 

788 

789 .. code-block:: python 

790 

791 with app.app_context(): 

792 ... 

793 

794 When the ``with`` block exits (or ``ctx.pop()`` is called), the 

795 teardown functions are called just before the app context is 

796 made inactive. Since a request context typically also manages an 

797 application context it would also be called when you pop a 

798 request context. 

799 

800 When a teardown function was called because of an unhandled 

801 exception it will be passed an error object. If an 

802 :meth:`errorhandler` is registered, it will handle the exception 

803 and the teardown will not receive it. 

804 

805 Teardown functions must avoid raising exceptions. If they 

806 execute code that might fail they must surround that code with a 

807 ``try``/``except`` block and log any errors. 

808 

809 The return values of teardown functions are ignored. 

810 

811 .. versionadded:: 0.9 

812 """ 

813 self.teardown_appcontext_funcs.append(f) 

814 return f 

815 

816 @setupmethod 

817 def shell_context_processor( 

818 self, f: T_shell_context_processor 

819 ) -> T_shell_context_processor: 

820 """Registers a shell context processor function. 

821 

822 .. versionadded:: 0.11 

823 """ 

824 self.shell_context_processors.append(f) 

825 return f 

826 

827 def _find_error_handler( 

828 self, e: Exception, blueprints: list[str] 

829 ) -> ft.ErrorHandlerCallable | None: 

830 """Return a registered error handler for an exception in this order: 

831 blueprint handler for a specific code, app handler for a specific code, 

832 blueprint handler for an exception class, app handler for an exception 

833 class, or ``None`` if a suitable handler is not found. 

834 """ 

835 exc_class, code = self._get_exc_class_and_code(type(e)) 

836 names = (*blueprints, None) 

837 

838 for c in (code, None) if code is not None else (None,): 

839 for name in names: 

840 handler_map = self.error_handler_spec[name][c] 

841 

842 if not handler_map: 

843 continue 

844 

845 for cls in exc_class.__mro__: 

846 handler = handler_map.get(cls) 

847 

848 if handler is not None: 

849 return handler 

850 return None 

851 

852 def trap_http_exception(self, e: Exception) -> bool: 

853 """Checks if an HTTP exception should be trapped or not. By default 

854 this will return ``False`` for all exceptions except for a bad request 

855 key error if ``TRAP_BAD_REQUEST_ERRORS`` is set to ``True``. It 

856 also returns ``True`` if ``TRAP_HTTP_EXCEPTIONS`` is set to ``True``. 

857 

858 This is called for all HTTP exceptions raised by a view function. 

859 If it returns ``True`` for any exception the error handler for this 

860 exception is not called and it shows up as regular exception in the 

861 traceback. This is helpful for debugging implicitly raised HTTP 

862 exceptions. 

863 

864 .. versionchanged:: 1.0 

865 Bad request errors are not trapped by default in debug mode. 

866 

867 .. versionadded:: 0.8 

868 """ 

869 if self.config["TRAP_HTTP_EXCEPTIONS"]: 

870 return True 

871 

872 trap_bad_request = self.config["TRAP_BAD_REQUEST_ERRORS"] 

873 

874 # if unset, trap key errors in debug mode 

875 if ( 

876 trap_bad_request is None 

877 and self.debug 

878 and isinstance(e, BadRequestKeyError) 

879 ): 

880 return True 

881 

882 if trap_bad_request: 

883 return isinstance(e, BadRequest) 

884 

885 return False 

886 

887 def should_ignore_error(self, error: BaseException | None) -> bool: 

888 """This is called to figure out if an error should be ignored 

889 or not as far as the teardown system is concerned. If this 

890 function returns ``True`` then the teardown handlers will not be 

891 passed the error. 

892 

893 .. versionadded:: 0.10 

894 """ 

895 return False 

896 

897 def redirect(self, location: str, code: int = 302) -> BaseResponse: 

898 """Create a redirect response object. 

899 

900 This is called by :func:`flask.redirect`, and can be called 

901 directly as well. 

902 

903 :param location: The URL to redirect to. 

904 :param code: The status code for the redirect. 

905 

906 .. versionadded:: 2.2 

907 Moved from ``flask.redirect``, which calls this method. 

908 """ 

909 return _wz_redirect( 

910 location, 

911 code=code, 

912 Response=self.response_class, # type: ignore[arg-type] 

913 ) 

914 

915 def inject_url_defaults(self, endpoint: str, values: dict[str, t.Any]) -> None: 

916 """Injects the URL defaults for the given endpoint directly into 

917 the values dictionary passed. This is used internally and 

918 automatically called on URL building. 

919 

920 .. versionadded:: 0.7 

921 """ 

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

923 

924 # url_for may be called outside a request context, parse the 

925 # passed endpoint instead of using request.blueprints. 

926 if "." in endpoint: 

927 names = chain( 

928 names, reversed(_split_blueprint_path(endpoint.rpartition(".")[0])) 

929 ) 

930 

931 for name in names: 

932 if name in self.url_default_functions: 

933 for func in self.url_default_functions[name]: 

934 func(endpoint, values) 

935 

936 def handle_url_build_error( 

937 self, error: BuildError, endpoint: str, values: dict[str, t.Any] 

938 ) -> str: 

939 """Called by :meth:`.url_for` if a 

940 :exc:`~werkzeug.routing.BuildError` was raised. If this returns 

941 a value, it will be returned by ``url_for``, otherwise the error 

942 will be re-raised. 

943 

944 Each function in :attr:`url_build_error_handlers` is called with 

945 ``error``, ``endpoint`` and ``values``. If a function returns 

946 ``None`` or raises a ``BuildError``, it is skipped. Otherwise, 

947 its return value is returned by ``url_for``. 

948 

949 :param error: The active ``BuildError`` being handled. 

950 :param endpoint: The endpoint being built. 

951 :param values: The keyword arguments passed to ``url_for``. 

952 """ 

953 for handler in self.url_build_error_handlers: 

954 try: 

955 rv = handler(error, endpoint, values) 

956 except BuildError as e: 

957 # make error available outside except block 

958 error = e 

959 else: 

960 if rv is not None: 

961 return rv 

962 

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

964 # the passed in exception. 

965 if error is sys.exc_info()[1]: 

966 raise 

967 

968 raise error