def METHOD_NAME(user, course_data, force_update_subsections=False):
    """
    Computes, saves, and returns a CourseGrade object for the
    given user and course.
    Sends a COURSE_GRADE_CHANGED signal to listeners and
    COURSE_GRADE_NOW_PASSED if learner has passed course or
    COURSE_GRADE_NOW_FAILED if learner is now failing course
    """
    if force_update_subsections:
        prefetch_grade_overrides_and_visible_blocks(user, course_data.course_key)
    course_grade = CourseGrade(
        user,
        course_data,
        force_update_subsections=force_update_subsections
    )
    course_grade = course_grade.update()
    should_persist = course_grade.attempted
    if should_persist:
        course_grade._subsection_grade_factory.bulk_create_unsaved()  # lint-amnesty, pylint: disable=protected-access
        PersistentCourseGrade.update_or_create(
            user_id=user.id,
            course_id=course_data.course_key,
            course_version=course_data.version,
            course_edited_timestamp=course_data.edited_on,
            grading_policy_hash=course_data.grading_policy_hash,
            percent_grade=course_grade.percent,
            letter_grade=course_grade.letter_grade or "",
            passed=course_grade.passed,
        )
    COURSE_GRADE_CHANGED.send_robust(
        sender=None,
        user=user,
        course_grade=course_grade,
        course_key=course_data.course_key,
        deadline=course_data.course.end,
    )
    if course_grade.passed:
        COURSE_GRADE_NOW_PASSED.send(
            sender=CourseGradeFactory,
            user=user,
            course_id=course_data.course_key,
        )
    else:
        COURSE_GRADE_NOW_FAILED.send(
            sender=CourseGradeFactory,
            user=user,
            course_id=course_data.course_key,
            grade=course_grade,
        )
    log.info(
        'Grades: Update, %s, User: %s, %s, persisted: %s',
        course_data.full_string(), user.id, course_grade, should_persist,
    )
    return course_grade