Esempio n. 1
0
def add_job(task, inputdata, debug=False):
    """ Add a job in the queue and returns a submission id.
        task is a Task instance and inputdata is the input as a dictionary
        If debug is true, more debug data will be saved
    """
    if not User.is_logged_in():
        raise Exception("A user must be logged in to submit an object")

    username = User.get_username()
    course = FrontendCourse(task.get_course_id())

    obj = {
        "courseid": task.get_course_id(),
        "taskid": task.get_id(),
        "input": get_gridfs().put(
            json.dumps(inputdata)),
        "status": "waiting",
        "submitted_on": datetime.now()}

    if course.is_group_course() and username not in course.get_staff(True):
        group = get_database().groups.find_one({"course_id": task.get_course_id(), "users": username})
        obj.update({"username": group["users"]})
    else:
        obj.update({"username": [username]})

    submissionid = get_database().submissions.insert(obj)

    PluginManager.get_instance().call_hook("new_submission", submissionid=submissionid, submission=obj, inputdata=inputdata)

    get_job_manager().new_job(task, inputdata, (lambda job: _job_done_callback(submissionid, task, job)), "Frontend - {}".format(username), debug)

    return submissionid
Esempio n. 2
0
def get_app(config_file):
    """ Get the application. config_file is the path to the JSON configuration file """
    appli = web.application(urls, globals(), autoreload=False)
    common.base.INGIniousConfiguration.load(config_file)

    frontend.base.init_database()
    update_database()
    frontend.session.init(appli)

    def not_found():
        """ Display the error 404 page """
        return web.notfound(frontend.base.renderer.notfound('Page not found'))
    appli.notfound = not_found

    plugin_manager = PluginManager(appli, common.base.INGIniousConfiguration.get("plugins", []))

    # Plugin Manager is also a Hook Manager
    submission_manager.init_backend_interface(plugin_manager)

    # Loads template_helper
    TemplateHelper()

    # Loads plugins
    plugin_manager.load()

    return appli
Esempio n. 3
0
def _job_done_callback(submissionid, task, job):
    """ Callback called by JobManager when a job is done. Updates the submission in the database with the data returned after the completion of the job """
    submission = get_submission(submissionid, False)
    submission = get_input_from_submission(submission)

    job = _parse_text(task, job)

    data = {
        "status": ("done" if job["result"] == "success" or job["result"] == "failed" else "error"),  # error only if error was made by INGInious
        "result": job["result"],
        "grade": job["grade"],
        "text": job.get("text", None),
        "tests": job.get("tests", None),
        "problems": (job["problems"] if "problems" in job else {}),
        "archive": (get_gridfs().put(base64.b64decode(job["archive"])) if "archive" in job else None)
    }

    # Store additional data
    dont_dump = ["task", "course", "input"]
    for index in job:
        if index not in data and index not in dont_dump:
            data[index] = job[index]

    # Save submission to database
    get_database().submissions.update(
        {"_id": submission["_id"]},
        {"$set": data}
    )

    for username in submission["username"]:
        UserData(username).update_stats(submission, job)

    PluginManager.get_instance().call_hook("submission_done", submission=submission, job=job)
def add_job(task, inputdata, debug=False):
    """ Add a job in the queue and returns a submission id.
        task is a Task instance and inputdata is the input as a dictionary
        If debug is true, more debug data will be saved
    """
    if not User.is_logged_in():
        raise Exception("A user must be logged in to submit an object")

    username = User.get_username()

    jobid = get_job_manager().new_job_id()

    obj = {
        "username": username,
        "courseid": task.get_course_id(),
        "taskid": task.get_id(),
        "input": get_gridfs().put(
            json.dumps(inputdata)),
        "status": "waiting",
        "jobid": jobid,
        "submitted_on": datetime.now()}
    submissionid = get_database().submissions.insert(obj)

    PluginManager.get_instance().call_hook("new_submission", submissionid=submissionid, submission=obj, jobid=jobid, inputdata=inputdata)

    get_job_manager().new_job(task, inputdata, job_done_callback, "Frontend - {}".format(username), jobid, debug)

    return submissionid
    def _javascript_helper(cls, position):
        """ Add javascript links for the current page and for the plugins """
        if position not in ["header", "footer"]:
            position = "footer"

        # Load javascript files from plugins
        if position == "header":
            entries = [entry for entry in PluginManager.get_instance().call_hook("javascript_header") if entry is not None]
        else:
            entries = [entry for entry in PluginManager.get_instance().call_hook("javascript_footer") if entry is not None]
        # Load javascript for the current page
        entries += cls.get_instance()._get_ctx()["javascript"][position]
        entries = ["<script src='" + entry + "' type='text/javascript' charset='utf-8'></script>" for entry in entries]
        return "\n".join(entries)
 def _css_helper(cls):
     """ Add CSS links for the current page and for the plugins """
     entries = [entry for entry in PluginManager.get_instance().call_hook("css") if entry is not None]
     # Load javascript for the current page
     entries += cls.get_instance()._get_ctx()["css"]
     entries = ["<link href='" + entry + "' rel='stylesheet'>" for entry in entries]
     return "\n".join(entries)
Esempio n. 7
0
def get_menu(course, current):
    """ Returns the HTML of the menu used in the administration. ```current``` is the current page of section """
    custom_renderer = get_template_renderer('templates/')
    default_entries = [("settings", "<span class='glyphicon glyphicon-cog'></span> Course settings"),
                       ("students", "<span class='glyphicon glyphicon-user'></span> Students"),
                       ("tasks", "<span class='glyphicon glyphicon-tasks'></span> Tasks")]
    # Hook should return a tuple (link,name) where link is the relative link from the index of the course administration.
    additionnal_entries = [entry for entry in PluginManager.get_instance().call_hook('course_admin_menu', course=course) if entry is not None]

    return custom_renderer.course_admin.menu(course, default_entries + additionnal_entries, current)
Esempio n. 8
0
    def __init__(self, course, taskid, init_data=None):
        # We load the descriptor of the task here to allow plugins to modify settings of the task before it is read by the Task constructor
        if not id_checker(taskid):
            raise Exception("Task with invalid id: " + course.get_id() + "/" + taskid)
        if init_data is None:
            try:
                init_data = get_task_file_manager(course.get_id(), taskid).read()
            except Exception as inst:
                raise Exception("Error while reading task file: " + self._course.get_id() + "/" + self._taskid + " :\n" + str(inst))
        PluginManager.get_instance().call_hook('modify_task_data', course=course, taskid=taskid, data=init_data)

        # Now init the task
        common.tasks.Task.__init__(self, course, taskid, init_data)

        self._name = self._data.get('name', 'Task {}'.format(taskid))

        self._context = ParsableText(self._data.get('context', ""), "HTML" if self._data.get("contextIsHTML", False) else "rst")

        # Authors
        if isinstance(self._data.get('author'), basestring):  # verify if author is a string
            self._author = [self._data['author']]
        elif isinstance(self._data.get('author'), list):  # verify if author is a list
            for author in self._data['author']:
                if not isinstance(author, basestring):  # authors must be strings
                    raise Exception("This task has an invalid author")
            self._author = self._data['author']
        else:
            self._author = []

        # Grade weight
        self._weight = float(self._data.get("weight", 1.0))

        # _accessible
        self._accessible = AccessibleTime(self._data.get("accessible", None))

        # Order
        self._order = int(self._data.get('order', -1))
Esempio n. 9
0
def get_menu(course, current):
    """ Returns the HTML of the menu used in the administration. ```current``` is the current page of section """
    custom_renderer = get_template_renderer('templates/')

    default_entries = []
    if User.get_username() in course.get_admins():
        default_entries += [("settings", "<i class='fa fa-cog fa-fw'></i>&nbsp; Course settings"),
                            ("batch", "<i class='fa fa-rocket fa-fw'></i>&nbsp; Batch operations")]

    default_entries += [("students", "<i class='fa " + ("fa-group" if course.is_group_course() else "fa-user")
                         + " fa-fw'></i>&nbsp; " + ("Groups" if course.is_group_course() else "Students"))]

    default_entries += [("tasks", "<i class='fa fa-tasks fa-fw'></i>&nbsp; Tasks")]

    # Hook should return a tuple (link,name) where link is the relative link from the index of the course administration.
    additionnal_entries = [entry for entry in PluginManager.get_instance().call_hook('course_admin_menu', course=course) if entry is not None]

    return custom_renderer.course_admin.menu(course, default_entries + additionnal_entries, current)
Esempio n. 10
0
 def call(self, name, **kwargs):
     helpers = dict(self._base_helpers.items() + PluginManager.get_instance().call_hook("template_helper"))
     if helpers.get(name, None) is None:
         return ""
     else:
         return helpers.get(name, None)(**kwargs)
Esempio n. 11
0
def generic_hook(name, **kwargs):
    """ A generic hook that links the TemplateHelper with PluginManager """
    entries = [entry for entry in PluginManager.get_instance().call_hook(name, **kwargs) if entry is not None]
    return "\n".join(entries)
Esempio n. 12
0
def connect(auth_method_id, login_data):
    """ Connect throught plugins """
    return PluginManager.get_instance().get_auth_method_callback(auth_method_id)(login_data)