<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def document_to_text(filename: str = None, blob: bytes = None, extension: str = None, config: TextProcessingConfig = _DEFAULT_CONFIG) -> str: """ Converts a document to text. This function selects a processor based on the file extension (either from the filename, or, in the case of a BLOB, the extension specified manually via the ``extension`` parameter). Pass either a filename or a binary object. - Raises an exception for malformed arguments, missing files, bad filetypes, etc. - Returns a string if the file was processed (potentially an empty string). """

    if not filename and not blob:
        raise ValueError("document_to_text: no filename and no blob")
    if filename and blob:
        raise ValueError("document_to_text: specify either filename or blob")
    if blob and not extension:
        raise ValueError("document_to_text: need extension hint for blob")
    if filename:
        stub, extension = os.path.splitext(filename)
    else:
        if extension[0] != ".":
            extension = "." + extension
    extension = extension.lower()

    # Ensure blob is an appropriate type
    log.debug(
        "filename: {}, blob type: {}, blob length: {}, extension: {}".format(
            filename,
            type(blob),
            len(blob) if blob is not None else None,
            extension))

    # If we were given a filename and the file doesn't exist, don't bother.
    if filename and not os.path.isfile(filename):
        raise ValueError("document_to_text: no such file: {!r}".format(
            filename))

    # Choose method
    info = ext_map.get(extension)
    if info is None:
        log.warning("Unknown filetype: {}; using generic tool", extension)
        info = ext_map[None]
    func = info[CONVERTER]
    return func(filename, blob, config)