Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
debughelpers.py179 linesDownload Raw Back to flask
1from __future__ import annotations2 3import typing as t4 5from jinja2.loaders import BaseLoader6from werkzeug.routing import RequestRedirect7 8from .blueprints import Blueprint9from .globals import request_ctx10from .sansio.app import App11 12if t.TYPE_CHECKING:13    from .sansio.scaffold import Scaffold14    from .wrappers import Request15 16 17class UnexpectedUnicodeError(AssertionError, UnicodeError):18    """Raised in places where we want some better error reporting for19    unexpected unicode or binary data.20    """21 22 23class DebugFilesKeyError(KeyError, AssertionError):24    """Raised from request.files during debugging.  The idea is that it can25    provide a better error message than just a generic KeyError/BadRequest.26    """27 28    def __init__(self, request: Request, key: str) -> None:29        form_matches = request.form.getlist(key)30        buf = [31            f"You tried to access the file {key!r} in the request.files"32            " dictionary but it does not exist. The mimetype for the"33            f" request is {request.mimetype!r} instead of"34            " 'multipart/form-data' which means that no file contents"35            " were transmitted. To fix this error you should provide"36            ' enctype="multipart/form-data" in your form.'37        ]38        if form_matches:39            names = ", ".join(repr(x) for x in form_matches)40            buf.append(41                "\n\nThe browser instead transmitted some file names. "42                f"This was submitted: {names}"43            )44        self.msg = "".join(buf)45 46    def __str__(self) -> str:47        return self.msg48 49 50class FormDataRoutingRedirect(AssertionError):51    """This exception is raised in debug mode if a routing redirect52    would cause the browser to drop the method or body. This happens53    when method is not GET, HEAD or OPTIONS and the status code is not54    307 or 308.55    """56 57    def __init__(self, request: Request) -> None:58        exc = request.routing_exception59        assert isinstance(exc, RequestRedirect)60        buf = [61            f"A request was sent to '{request.url}', but routing issued"62            f" a redirect to the canonical URL '{exc.new_url}'."63        ]64 65        if f"{request.base_url}/" == exc.new_url.partition("?")[0]:66            buf.append(67                " The URL was defined with a trailing slash. Flask"68                " will redirect to the URL with a trailing slash if it"69                " was accessed without one."70            )71 72        buf.append(73            " Send requests to the canonical URL, or use 307 or 308 for"74            " routing redirects. Otherwise, browsers will drop form"75            " data.\n\n"76            "This exception is only raised in debug mode."77        )78        super().__init__("".join(buf))79 80 81def attach_enctype_error_multidict(request: Request) -> None:82    """Patch ``request.files.__getitem__`` to raise a descriptive error83    about ``enctype=multipart/form-data``.84 85    :param request: The request to patch.86    :meta private:87    """88    oldcls = request.files.__class__89 90    class newcls(oldcls):  # type: ignore[valid-type, misc]91        def __getitem__(self, key: str) -> t.Any:92            try:93                return super().__getitem__(key)94            except KeyError as e:95                if key not in request.form:96                    raise97 98                raise DebugFilesKeyError(request, key).with_traceback(99                    e.__traceback__100                ) from None101 102    newcls.__name__ = oldcls.__name__103    newcls.__module__ = oldcls.__module__104    request.files.__class__ = newcls105 106 107def _dump_loader_info(loader: BaseLoader) -> t.Iterator[str]:108    yield f"class: {type(loader).__module__}.{type(loader).__name__}"109    for key, value in sorted(loader.__dict__.items()):110        if key.startswith("_"):111            continue112        if isinstance(value, (tuple, list)):113            if not all(isinstance(x, str) for x in value):114                continue115            yield f"{key}:"116            for item in value:117                yield f"  - {item}"118            continue119        elif not isinstance(value, (str, int, float, bool)):120            continue121        yield f"{key}: {value!r}"122 123 124def explain_template_loading_attempts(125    app: App,126    template: str,127    attempts: list[128        tuple[129            BaseLoader,130            Scaffold,131            tuple[str, str | None, t.Callable[[], bool] | None] | None,132        ]133    ],134) -> None:135    """This should help developers understand what failed"""136    info = [f"Locating template {template!r}:"]137    total_found = 0138    blueprint = None139    if request_ctx and request_ctx.request.blueprint is not None:140        blueprint = request_ctx.request.blueprint141 142    for idx, (loader, srcobj, triple) in enumerate(attempts):143        if isinstance(srcobj, App):144            src_info = f"application {srcobj.import_name!r}"145        elif isinstance(srcobj, Blueprint):146            src_info = f"blueprint {srcobj.name!r} ({srcobj.import_name})"147        else:148            src_info = repr(srcobj)149 150        info.append(f"{idx + 1:5}: trying loader of {src_info}")151 152        for line in _dump_loader_info(loader):153            info.append(f"       {line}")154 155        if triple is None:156            detail = "no match"157        else:158            detail = f"found ({triple[1] or '<string>'!r})"159            total_found += 1160        info.append(f"       -> {detail}")161 162    seems_fishy = False163    if total_found == 0:164        info.append("Error: the template could not be found.")165        seems_fishy = True166    elif total_found > 1:167        info.append("Warning: multiple loaders returned a match for the template.")168        seems_fishy = True169 170    if blueprint is not None and seems_fishy:171        info.append(172            "  The template was looked up from an endpoint that belongs"173            f" to the blueprint {blueprint!r}."174        )175        info.append("  Maybe you did not place a template in the right folder?")176        info.append("  See https://flask.palletsprojects.com/blueprints/#templates")177 178    app.logger.info("\n".join(info))179 
codekingpro/portable-devtools · Team Ai