codekingpro/portable-devtools
114k
1from __future__ import annotations2 3import typing as t4 5from werkzeug.exceptions import BadRequest6from werkzeug.exceptions import HTTPException7from werkzeug.wrappers import Request as RequestBase8from werkzeug.wrappers import Response as ResponseBase9 10from . import json11from .globals import current_app12from .helpers import _split_blueprint_path13 14if t.TYPE_CHECKING: # pragma: no cover15 from werkzeug.routing import Rule16 17 18class Request(RequestBase):19 """The request object used by default in Flask. Remembers the20 matched endpoint and view arguments.21 22 It is what ends up as :class:`~flask.request`. If you want to replace23 the request object used you can subclass this and set24 :attr:`~flask.Flask.request_class` to your subclass.25 26 The request object is a :class:`~werkzeug.wrappers.Request` subclass and27 provides all of the attributes Werkzeug defines plus a few Flask28 specific ones.29 """30 31 json_module: t.Any = json32 33 #: The internal URL rule that matched the request. This can be34 #: useful to inspect which methods are allowed for the URL from35 #: a before/after handler (``request.url_rule.methods``) etc.36 #: Though if the request's method was invalid for the URL rule,37 #: the valid list is available in ``routing_exception.valid_methods``38 #: instead (an attribute of the Werkzeug exception39 #: :exc:`~werkzeug.exceptions.MethodNotAllowed`)40 #: because the request was never internally bound.41 #:42 #: .. versionadded:: 0.643 url_rule: Rule | None = None44 45 #: A dict of view arguments that matched the request. If an exception46 #: happened when matching, this will be ``None``.47 view_args: dict[str, t.Any] | None = None48 49 #: If matching the URL failed, this is the exception that will be50 #: raised / was raised as part of the request handling. This is51 #: usually a :exc:`~werkzeug.exceptions.NotFound` exception or52 #: something similar.53 routing_exception: HTTPException | None = None54 55 @property56 def max_content_length(self) -> int | None: # type: ignore[override]57 """Read-only view of the ``MAX_CONTENT_LENGTH`` config key."""58 if current_app:59 return current_app.config["MAX_CONTENT_LENGTH"] # type: ignore[no-any-return]60 else:61 return None62 63 @property64 def endpoint(self) -> str | None:65 """The endpoint that matched the request URL.66 67 This will be ``None`` if matching failed or has not been68 performed yet.69 70 This in combination with :attr:`view_args` can be used to71 reconstruct the same URL or a modified URL.72 """73 if self.url_rule is not None:74 return self.url_rule.endpoint75 76 return None77 78 @property79 def blueprint(self) -> str | None:80 """The registered name of the current blueprint.81 82 This will be ``None`` if the endpoint is not part of a83 blueprint, or if URL matching failed or has not been performed84 yet.85 86 This does not necessarily match the name the blueprint was87 created with. It may have been nested, or registered with a88 different name.89 """90 endpoint = self.endpoint91 92 if endpoint is not None and "." in endpoint:93 return endpoint.rpartition(".")[0]94 95 return None96 97 @property98 def blueprints(self) -> list[str]:99 """The registered names of the current blueprint upwards through100 parent blueprints.101 102 This will be an empty list if there is no current blueprint, or103 if URL matching failed.104 105 .. versionadded:: 2.0.1106 """107 name = self.blueprint108 109 if name is None:110 return []111 112 return _split_blueprint_path(name)113 114 def _load_form_data(self) -> None:115 super()._load_form_data()116 117 # In debug mode we're replacing the files multidict with an ad-hoc118 # subclass that raises a different error for key errors.119 if (120 current_app121 and current_app.debug122 and self.mimetype != "multipart/form-data"123 and not self.files124 ):125 from .debughelpers import attach_enctype_error_multidict126 127 attach_enctype_error_multidict(self)128 129 def on_json_loading_failed(self, e: ValueError | None) -> t.Any:130 try:131 return super().on_json_loading_failed(e)132 except BadRequest as e:133 if current_app and current_app.debug:134 raise135 136 raise BadRequest() from e137 138 139class Response(ResponseBase):140 """The response object that is used by default in Flask. Works like the141 response object from Werkzeug but is set to have an HTML mimetype by142 default. Quite often you don't have to create this object yourself because143 :meth:`~flask.Flask.make_response` will take care of that for you.144 145 If you want to replace the response object used you can subclass this and146 set :attr:`~flask.Flask.response_class` to your subclass.147 148 .. versionchanged:: 1.0149 JSON support is added to the response, like the request. This is useful150 when testing to get the test client response data as JSON.151 152 .. versionchanged:: 1.0153 154 Added :attr:`max_cookie_size`.155 """156 157 default_mimetype: str | None = "text/html"158 159 json_module = json160 161 autocorrect_location_header = False162 163 @property164 def max_cookie_size(self) -> int: # type: ignore165 """Read-only view of the :data:`MAX_COOKIE_SIZE` config key.166 167 See :attr:`~werkzeug.wrappers.Response.max_cookie_size` in168 Werkzeug's docs.169 """170 if current_app:171 return current_app.config["MAX_COOKIE_SIZE"] # type: ignore[no-any-return]172 173 # return Werkzeug's default when not in an app context174 return super().max_cookie_size175 