Esempio n. 1
0
def exercise_template(request, course_key, exercise_key, parameter=None):
    '''
    Presents the exercise template.
    '''
    lang = request.GET.get('lang', None)
    (course, exercise, lang) = _get_course_exercise_lang(course_key, exercise_key, lang)

    response = None
    path = None

    if 'template_files' in exercise:
        def find_name(paths, name):
            templates = [(path,path.split('/')[-1]) for path in paths]
            for path,name in templates:
                if name == parameter:
                    return path
            return None
        path = find_name(exercise['template_files'], parameter)

    if path:
        with open(os.path.join(course['dir'], path)) as f:
            content = f.read()
        response = HttpResponse(content, content_type='text/plain')
    else:
        try:
            response = import_named(course, exercise['view_type'] + "Template")(request, course, exercise, parameter)
        except ImportError:
            pass

    if response:
        return response
    else:
        raise Http404()
Esempio n. 2
0
def exercise_model(request, course_key, exercise_key, parameter=None):
    '''
    Presents a model answer for an exercise.
    '''
    (course, exercise) = config.exercise_entry(course_key, exercise_key)
    if course is None or exercise is None:
        raise Http404()
    response = None

    try:
        response = import_named(course, exercise['view_type'] + "Model")(
            request, course, exercise, parameter)
    except ImportError:
        pass

    if 'model_files' in exercise:
        def find_name(paths, name):
            models = [(path,path.split('/')[-1]) for path in paths]
            for path,name in models:
                if name == parameter:
                    return path
            return None
        path = find_name(exercise['model_files'], parameter)
        if path:
            with open(os.path.join(course['dir'], path)) as f:
                content = f.read()
            response = HttpResponse(content, content_type='text/plain')

    if response:
        return response
    else:
        raise Http404()
Esempio n. 3
0
def exercise(request, course_key, exercise_key):
    '''
    Presents the exercise and accepts answers to it.
    '''
    post_url = request.GET.get('post_url', None)
    lang = request.POST.get('__grader_lang', None) or request.GET.get('lang', None)
    (course, exercise, lang) = _get_course_exercise_lang(course_key, exercise_key, lang)

    # Try to call the configured view.
    return import_named(course, exercise['view_type'])(request, course, exercise, post_url)
Esempio n. 4
0
def exercise_ajax(request, course_key, exercise_key):
    '''
    Receives an AJAX request for an exercise.
    '''
    (course, exercise) = config.exercise_entry(course_key, exercise_key)
    if course is None or exercise is None or 'ajax_type' not in exercise:
        raise Http404()
    # jQuery does not send "requested with" on cross domain requests
    #if not request.is_ajax():
    #    return HttpResponse('Method not allowed', status=405)

    response = import_named(course, exercise['ajax_type'])(
        request, course, exercise)

    # No need to control domain as valid submission_url is required to submit.
    response['Access-Control-Allow-Origin'] = '*'
    return response
Esempio n. 5
0
def exercise(request, course_key, exercise_key):
    '''
    Presents the exercise and accepts answers to it.
    '''
    post_url = request.GET.get('post_url', None)
    lang = request.GET.get('lang', None)

    # Fetch the corresponding exercise entry from the config.
    (course, exercise) = config.exercise_entry(course_key, exercise_key, lang=lang)
    if course is None or exercise is None:
        raise Http404()

    # Exercise language.
    if not lang:
        if "lang" in course:
            lang = course["lang"]
        else:
            lang = "en"
    translation.activate(lang)

    # Try to call the configured view.
    return import_named(course, exercise['view_type'])(
        request, course, exercise, post_url)
Esempio n. 6
0
    def _course_root(self, course_key):
        '''
        Gets course dictionary root (meta and data).

        @type course_key: C{str}
        @param course_key: a course key
        @rtype: C{dict}
        @return: course root or None
        '''

        # Try cached version.
        if course_key in self._courses:
            course_root = self._courses[course_key]
            try:
                if course_root["mtime"] >= os.path.getmtime(course_root["file"]):
                    return course_root
            except OSError:
                pass

        LOGGER.debug('Loading course "%s"' % (course_key))
        meta = read_meta(os.path.join(DIR, course_key, META))
        try:
            f = self._get_config(os.path.join(self._conf_dir(DIR, course_key, meta), INDEX))
        except ConfigError:
            return None

        t = os.path.getmtime(f)
        data = self._parse(f)
        if data is None:
            raise ConfigError('Failed to parse configuration file "%s"' % (f))

        self._check_fields(f, data, ["name"])
        data["key"] = course_key
        data["mtime"] = t
        data["dir"] = self._conf_dir(DIR, course_key, {})

        if "language" in data:
            data["lang"] = data["language"]

        if "modules" in data:
            keys = []
            config = {}
            def recurse_exercises(parent):
                if "children" in parent:
                    for exercise_vars in parent["children"]:
                        if "key" in exercise_vars:
                            cfg = None
                            if "config" in exercise_vars:
                                cfg = exercise_vars["config"]
                            elif "type" in exercise_vars and "exercise_types" in data \
                                    and exercise_vars["type"] in data["exercise_types"] \
                                    and "config" in data["exercise_types"][exercise_vars["type"]]:
                                cfg = data["exercise_types"][exercise_vars["type"]]["config"]
                            if cfg:
                                keys.append(exercise_vars["key"])
                                config[exercise_vars["key"]] = cfg
                        recurse_exercises(exercise_vars)
            for module in data["modules"]:
                recurse_exercises(module)
            data["exercises"] = keys
            data["config_files"] = config

        # Enable course configurable ecercise_loader function.
        exercise_loader = self._default_exercise_loader
        if "exercise_loader" in data:
            exercise_loader = import_named(data, data["exercise_loader"])

        self._courses[course_key] = course_root = {
            "meta": meta,
            "file": f,
            "mtime": t,
            "ptime": time.time(),
            "data": data,
            "lang": data.get('lang', DEFAULT_LANG),
            "exercise_loader": exercise_loader,
            "exercises": {}
        }
        return course_root
Esempio n. 7
0
def runactions(course, exercise, submission_dir):
    '''
    Runs configured grading actions for an exercise submission.

    @type course: C{dict}
    @param course: a course configuration
    @type exercise: C{dict}
    @param exercise: an exercise configuration
    @type submission_dir: C{str}
    @param submission_dir: a submission directory where submitted files are stored
    @rtype: C{dict}
    @return: template = template name, result = points, max_points, tests
    '''
    total_points = 0
    max_points = 0
    total_result = []
    error = False
    has_appendixes = False

    # Try to run the grading actions.
    try:
        for action in exercise["actions"]:
            exgrader = None
            try:
                exgrader = import_named(course, action["type"])
            except ImproperlyConfigured as e:
                raise ConfigError("Invalid action \"type\" in exercise configuration.", e)

            # Run the exercise grader action
            LOGGER.debug("Running action \"%s\"", action["type"])
            r = exgrader(course, exercise, action, submission_dir)
            has_appendixes = has_appendixes or \
                ("appendix" in r and r["appendix"])

            # Configured template values.
            if "title" in action:
                r["title"] = action["title"]
            if "html" in action and action["html"]:
                r["html"] = True

            # Override with configured points.
            if "points" in action:
                r["max_points"] = action["points"]
                if r["stop"]:
                    r["points"] = 0
                else:
                    r["points"] = action["points"]
            elif "max_points" in action:
                r["max_points"] = action["max_points"]
                if r["points"] > action["max_points"]:
                    r["points"] = action["max_points"]

            # Sum total numbers.
            total_result.append(r)
            total_points += r["points"]
            if "max_points" in r:
                max_points += r["max_points"]
            if r["stop"]:
                if "expect_success" in action:
                    error = action["expect_success"]
                break

        # Override with configured max points.
        if "max_points" in exercise:
            max_points = exercise["max_points"]

        # Check the points are in range.
        if total_points > max_points:
            total_points = max_points
        elif total_points < 0:
            total_points = 0

        # Determine template.
        template = None
        if "feedback_template" in exercise:
            template = exercise["feedback_template"]
        else:
            template = "access/task_success.html"

        return {
            "template": template,
            "result": {
                "points": total_points,
                "max_points": max_points,
                "tests": total_result,
                "error": error,
                "has_appendixes": has_appendixes,
            }
        }

    finally:
        clean_submission_dir(submission_dir)