Source code for falcon.media.handlers

from collections import UserDict

from falcon import errors
from falcon.constants import MEDIA_JSON, MEDIA_MULTIPART, MEDIA_URLENCODED
from falcon.media.json import JSONHandler
from falcon.media.multipart import MultipartFormHandler, MultipartParseOptions
from falcon.media.urlencoded import URLEncodedFormHandler
from falcon.vendor import mimeparse


class MissingDependencyHandler:
    """Placeholder handler that always raises an error.

    This handler is used by the framework for media types that require an
    external dependency that can not be found.
    """
    def __init__(self, handler: str, library: str):
        self._msg = (
            'The {} requires the {} library, which is not installed.'
        ).format(handler, library)

    def _raise(self, *args, **kwargs):
        raise RuntimeError(self._msg)

    # TODO(kgriffs): Add support for async later if needed.
    serialize = deserialize = _raise


[docs]class Handlers(UserDict): """A :class:`dict`-like object that manages Internet media type handlers.""" def __init__(self, initial=None): handlers = initial or { MEDIA_JSON: JSONHandler(), MEDIA_MULTIPART: MultipartFormHandler(), MEDIA_URLENCODED: URLEncodedFormHandler(), } # NOTE(jmvrbanac): Directly calling UserDict as it's not inheritable. # Also, this results in self.update(...) being called. UserDict.__init__(self, handlers) def _resolve_media_type(self, media_type, all_media_types): resolved = None try: # NOTE(jmvrbanac): Mimeparse will return an empty string if it can # parse the media type, but cannot find a suitable type. resolved = mimeparse.best_match( all_media_types, media_type ) except ValueError: pass return resolved def find_by_media_type(self, media_type, default, raise_not_found=True): # PERF(jmvrbanac): Check via a quick methods first for performance if media_type == '*/*' or not media_type: media_type = default try: return self.data[media_type] except KeyError: pass # PERF(jmvrbanac): Fallback to the slower method resolved = self._resolve_media_type(media_type, self.data.keys()) if not resolved: if raise_not_found: raise errors.HTTPUnsupportedMediaType( description='{0} is an unsupported media type.'.format(media_type) ) return None return self.data[resolved]
# NOTE(vytas): An ugly way to work around circular imports. MultipartParseOptions._DEFAULT_HANDLERS = Handlers({ MEDIA_JSON: JSONHandler(), MEDIA_URLENCODED: URLEncodedFormHandler(), }) # type: ignore