def get_submission(submission_uuid, read_replica=False):
    """Retrieves a single submission by uuid.

    Args:
        submission_uuid (str): Identifier for the submission.

    Kwargs:
        read_replica (bool): If true, attempt to use the read replica database.
            If no read replica is available, use the default database.

    Raises:
        SubmissionNotFoundError: Raised if the submission does not exist.
        SubmissionRequestError: Raised if the search parameter is not a string.
        SubmissionInternalError: Raised for unknown errors.

    Examples:
        >>> get_submission("20b78e0f32df805d21064fc912f40e9ae5ab260d")
        {
            'student_item': 2,
            'attempt_number': 1,
            'submitted_at': datetime.datetime(2014, 1, 29, 23, 14, 52, 649284, tzinfo=<UTC>),
            'created_at': datetime.datetime(2014, 1, 29, 17, 14, 52, 668850, tzinfo=<UTC>),
            'answer': u'The answer is 42.'
        }

    """
    if not isinstance(submission_uuid, six.string_types):
        if isinstance(submission_uuid, UUID):
            submission_uuid = six.text_type(submission_uuid)
        else:
            raise SubmissionRequestError(
                msg="submission_uuid ({!r}) must be serializable".format(submission_uuid)
            )

    cache_key = Submission.get_cache_key(submission_uuid)
    try:
        cached_submission_data = cache.get(cache_key)
    except Exception:
        # The cache backend could raise an exception
        # (for example, memcache keys that contain spaces)
        logger.exception("Error occurred while retrieving submission from the cache")
        cached_submission_data = None

    if cached_submission_data:
        logger.info("Get submission {} (cached)".format(submission_uuid))
        return cached_submission_data

    try:
        submission = _get_submission_model(submission_uuid, read_replica)
        submission_data = SubmissionSerializer(submission).data
        cache.set(cache_key, submission_data)
    except Submission.DoesNotExist:
        logger.error("Submission {} not found.".format(submission_uuid))
        raise SubmissionNotFoundError(
            u"No submission matching uuid {}".format(submission_uuid)
        )
    except Exception as exc:
        # Something very unexpected has just happened (like DB misconfig)
        err_msg = "Could not get submission due to error: {}".format(exc)
        logger.exception(err_msg)
        raise SubmissionInternalError(err_msg)

    logger.info("Get submission {}".format(submission_uuid))
    return submission_data
Retrieves a single submission by uuid.

    Args:
        submission_uuid (str): Identifier for the submission.

    Kwargs:
        read_replica (bool): If true, attempt to use the read replica database.
            If no read replica is available, use the default database.

    Raises:
        SubmissionNotFoundError: Raised if the submission does not exist.
        SubmissionRequestError: Raised if the search parameter is not a string.
        SubmissionInternalError: Raised for unknown errors.

    Examples:
        >>> get_submission("20b78e0f32df805d21064fc912f40e9ae5ab260d")
        {
            'student_item': 2,
            'attempt_number': 1,
            'submitted_at': datetime.datetime(2014, 1, 29, 23, 14, 52, 649284, tzinfo=<UTC>),
            'created_at': datetime.datetime(2014, 1, 29, 17, 14, 52, 668850, tzinfo=<UTC>),
            'answer': u'The answer is 42.'
        }