# Path: doctor/errors.py
# class ParseError(DoctorError):
#     """Raised when a value cannot be parsed into an appropriate type."""
#     pass
# 
# class TypeSystemError(DoctorError):
#     """An error that represents an invalid value for a type.
# 
#     This is borrowed from apistar:
#     https://github.com/encode/apistar/blob/
#     50dd15f0878f0a7c50ce829a72adb276782bcb78/apistar/exceptions.py#L4-L15
# 
#     :param detail: Detail about the error.
#     :param cls: The class type that was being instantiated.
#     :param code: The error code.
#     :param errors: A dict containing all validation errors during the request.
#         The key is the param name and the value is the error message.
#     """
#     def __init__(self,
#                  detail: Union[str, dict] = None,
#                  cls: type = None,
#                  code: str = None,
#                  errors: dict = None) -> None:
# 
#         if cls is not None and code is not None:
#             cls_errors = getattr(cls, 'errors')
#             detail = cls_errors[code].format(**cls.__dict__)
# 
#         self.detail = detail
#         if errors and len(errors) == 1:
#             param = list(errors.keys())[0]
#             msg = list(errors.values())[0]
#             detail = '{} - {}'.format(param, msg)
#         super().__init__(detail, errors=errors)


import inspect
import logging
import warnings
import simplejson as json
from typing import List
from doctor.errors import ParseError, TypeSystemError
    from doctor.types import SuperType, UnionType
            continue
        # Skip coercing parameters not annotated by a doctor type.
        if not issubclass(sig_params[param].annotation, SuperType):
            continue

        # Check if the type has a custom parser for the parameter.
        custom_parser = sig_params[param].annotation.parser
        if custom_parser is not None:
            if not callable(custom_parser):
                warnings.warn(
                    'Parser `{}` is not callable, using default parser.'.format(
                        custom_parser))
                custom_parser = None

        try:
            if custom_parser is not None:
                parsed_params[param] = custom_parser(value)
            else:
                if issubclass(sig_params[param].annotation, UnionType):
                    json_type = [
                        _native_type_to_json[_type.native_type]
                        for _type in sig_params[param].annotation.types
                    ]
                else:
                    native_type = sig_params[param].annotation.native_type
                    json_type = [_native_type_to_json[native_type]]
                # If the type is nullable, also add null as an allowed type.
                if sig_params[param].annotation.nullable:
                    json_type.append('null')
                _, parsed_params[param] = parse_value(value, json_type)

# Path: doctor/errors.py
# class ParseError(DoctorError):
#     """Raised when a value cannot be parsed into an appropriate type."""
#     pass
# 
# class TypeSystemError(DoctorError):
#     """An error that represents an invalid value for a type.
# 
#     This is borrowed from apistar:
#     https://github.com/encode/apistar/blob/
#     50dd15f0878f0a7c50ce829a72adb276782bcb78/apistar/exceptions.py#L4-L15
# 
#     :param detail: Detail about the error.
#     :param cls: The class type that was being instantiated.
#     :param code: The error code.
#     :param errors: A dict containing all validation errors during the request.
#         The key is the param name and the value is the error message.
#     """
#     def __init__(self,
#                  detail: Union[str, dict] = None,
#                  cls: type = None,
#                  code: str = None,
#                  errors: dict = None) -> None:
# 
#         if cls is not None and code is not None:
#             cls_errors = getattr(cls, 'errors')
#             detail = cls_errors[code].format(**cls.__dict__)
# 
#         self.detail = detail
#         if errors and len(errors) == 1:
#             param = list(errors.keys())[0]
#             msg = list(errors.values())[0]
#             detail = '{} - {}'.format(param, msg)
#         super().__init__(detail, errors=errors)


# Path: doctor/parsers.py
import inspect
import logging
import warnings
import simplejson as json
from typing import List
from doctor.errors import ParseError, TypeSystemError
    from doctor.types import SuperType, UnionType

            continue
        # Skip coercing parameters not annotated by a doctor type.
        if not issubclass(sig_params[param].annotation, SuperType):
            continue

        # Check if the type has a custom parser for the parameter.
        custom_parser = sig_params[param].annotation.parser
        if custom_parser is not None:
            if not callable(custom_parser):
                warnings.warn(
                    'Parser `{}` is not callable, using default parser.'.format(
                        custom_parser))
                custom_parser = None

        try:
            if custom_parser is not None:
                parsed_params[param] = custom_parser(value)
            else:
                if issubclass(sig_params[param].annotation, UnionType):
                    json_type = [
                        _native_type_to_json[_type.native_type]
                        for _type in sig_params[param].annotation.types
                    ]
                else:
                    native_type = sig_params[param].annotation.native_type
                    json_type = [_native_type_to_json[native_type]]
                # If the type is nullable, also add null as an allowed type.
                if sig_params[param].annotation.nullable:
                    json_type.append('null')
                _, parsed_params[param] = parse_value(value, json_type)

        except ParseError as e: