def __init__(self, task, problemid, content): if not id_checker(problemid): raise Exception("Invalid problem _id: " + problemid) self._id = problemid self._task = task self._name = content['name'] if "name" in content else "" self._header = content['header'] if "header" in content else ""
def __init__(self, task, problemid, content): if not id_checker(problemid): raise Exception("Invalid problem _id: " + problemid) self._id = problemid self._task = task self._name = content['name'] if "name" in content else "" self._header = ParsableText((content['header'] if "header" in content else ""), ("HTML" if "headerIsHTML" in content and content["headerIsHTML"] else "rst"))
def _create_task_problem(self, task, problemid, problem_content): """Creates a new instance of the right class for a given problem.""" # Basic checks if not id_checker(problemid): raise Exception("Invalid problem _id: " + problemid) if problem_content.get('type', "") not in self._problem_types: raise Exception("Invalid type for problem " + problemid) return self._problem_types.get(problem_content.get('type', ""))(task, problemid, problem_content)
def _get_course_descriptor_path(cls, courseid): """Returns the path to the file that describes the course 'courseid'""" if not id_checker(courseid): raise Exception("Course with invalid name: " + courseid) base_file = os.path.join(get_tasks_directory(), courseid, "course") if os.path.isfile(base_file + ".yaml"): return base_file + ".yaml" else: return base_file + ".json"
def _get_course_descriptor_path(cls, courseid): """Returns the path to the file that describes the course 'courseid'""" if not id_checker(courseid): raise Exception("Course with invalid name: " + courseid) base_file = os.path.join(INGIniousConfiguration["tasks_directory"], courseid, "course") if os.path.isfile(base_file + ".yaml"): return base_file + ".yaml" else: return base_file + ".json" return base_file + ".yaml" # by default, YAML.
def _create_box(self, boxid, box_content): """ Create adequate box """ if not id_checker(boxid) and not boxid == "": raise Exception("Invalid box _id " + boxid) if "type" not in box_content: raise Exception("Box " + boxid + " does not have a type") try: return self._box_types[box_content["type"]](self, boxid, box_content) except: raise Exception("Unknow box type " + box_content["type"] + "for box _id " + boxid)
def POST(self, courseid, taskid): """ Upload or modify a file """ if not id_checker(taskid): raise Exception("Invalid task id") get_course_and_check_rights(courseid, allow_all_staff=False) request = web.input(file={}) if request.get("action") == "upload" and request.get('path') is not None and request.get('file') is not None: return self.action_upload(courseid, taskid, request.get('path'), request.get('file')) elif request.get("action") == "edit_save" and request.get('path') is not None and request.get('content') is not None: return self.action_edit_save(courseid, taskid, request.get('path'), request.get('content')) else: return self.show_tab_file(courseid, taskid)
def GET(self, courseid, taskid): """ Edit a task """ if not id_checker(taskid): raise Exception("Invalid task id") course, _ = get_course_and_check_rights(courseid, allow_all_staff=False) try: task_data = get_task_file_manager(courseid, taskid).read() except: task_data = None if task_data is None: task_data = {} environments = INGIniousConfiguration["containers"].keys() current_filetype = None try: current_filetype = get_task_file_manager(courseid, taskid).get_ext() except: pass available_filetypes = get_available_task_file_managers().keys() # custom problem-type: for pid in task_data.get("problems", {}): problem = task_data["problems"][pid] if (problem["type"] == "code" and "boxes" in problem) or problem["type"] not in ( "code", "code-single-line", "code-file", "match", "multiple-choice"): problem_copy = copy.deepcopy(problem) for i in ["name", "header", "headerIsHTML"]: if i in problem_copy: del problem_copy[i] problem["custom"] = common.custom_yaml.dump(problem_copy) return renderer.course_admin.edit_task( course, taskid, task_data, environments, json.dumps( task_data.get( 'problems', {})), self.contains_is_html(task_data), current_filetype, available_filetypes, AccessibleTime, CourseTaskFiles.get_task_filelist(courseid, taskid))
def __init__(self, course, taskid, init_data=None): """ Init the task. course is a Course object, taskid the task id, and init_data is a dictionnary containing the data needed to initialize the Task object. If init_data is None, the data will be taken from the course tasks' directory. """ if not id_checker(taskid): raise Exception("Task with invalid id: " + course.get_id() + "/" + taskid) self._course = course self._taskid = taskid if init_data is None: try: self._data = get_task_file_manager(self.get_course_id(), self.get_id()).read() except Exception as inst: raise Exception("Error while reading task file: " + self._course.get_id() + "/" + self._taskid + " :\n" + str(inst)) else: self._data = init_data self._environment = self._data.get('environment', None) #Response is HTML self._response_is_html = self._data.get("responseIsHTML", False) # Limits self._limits = {"time": 20, "memory": 1024, "disk": 1024} if "limits" in self._data: try: self._limits['time'] = int(self._data["limits"].get("time", 20)) self._limits['memory'] = int(self._data["limits"].get("memory", 1024)) self._limits['disk'] = int(self._data["limits"].get("disk", 1024)) except: raise Exception("Invalid limit") if "problems" not in self._data: raise Exception("Tasks must have some problems descriptions") # Check all problems self._problems = [] for problemid in self._data['problems']: self._problems.append(self._create_task_problem(self, problemid, self._data['problems'][problemid]))
def GET(self, courseid, taskid): """ Edit a task """ if not id_checker(taskid): raise Exception("Invalid task id") get_course_and_check_rights(courseid, allow_all_staff=False) request = web.input() if request.get("action") == "download" and request.get('path') is not None: return self.action_download(courseid, taskid, request.get('path')) elif request.get("action") == "delete" and request.get('path') is not None: return self.action_delete(courseid, taskid, request.get('path')) elif request.get("action") == "rename" and request.get('path') is not None and request.get('new_path') is not None: return self.action_rename(courseid, taskid, request.get('path'), request.get('new_path')) elif request.get("action") == "create" and request.get('path') is not None: return self.action_create(courseid, taskid, request.get('path')) elif request.get("action") == "edit" and request.get('path') is not None: return self.action_edit(courseid, taskid, request.get('path')) else: return self.show_tab_file(courseid, taskid)
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))
def test_id_checker_invalid_3(self): assert id_checker("test/test") is False
def test_id_checker_invalid_2(self): assert id_checker("") is False
def test_id_checker_invalid_1(self): assert id_checker("a@a") is False
def test_id_checker_valid_1(self): assert id_checker("azertyuiopZERTYUIO65456_5-a") is True
def POST(self, courseid, taskid): """ Edit a task """ if not id_checker(taskid) or not id_checker(courseid): raise Exception("Invalid course/task id") course, _ = get_course_and_check_rights(courseid, allow_all_staff=False) # Parse content try: data = web.input(task_file={}) try: task_zip = data.get("task_file").file except: task_zip = None del data["task_file"] problems = self.dict_from_prefix("problem", data) limits = self.dict_from_prefix("limits", data) data = {key: val for key, val in data.iteritems() if not key.startswith("problem") and not key.startswith("limits")} del data["@action"] try: file_manager = get_available_task_file_managers()[data["@filetype"]](courseid, taskid) except Exception as inst: return json.dumps({"status": "error", "message": "Invalid file type: {}".format(str(inst))}) del data["@filetype"] if problems is None: return json.dumps({"status": "error", "message": "You cannot create a task without subproblems"}) # Order the problems (this line also deletes @order from the result) data["problems"] = OrderedDict([(key, self.parse_problem(val)) for key, val in sorted(problems.iteritems(), key=lambda x: int(x[1]['@order']))]) data["limits"] = limits if "hard_time" in data["limits"] and data["limits"]["hard_time"] == "": del data["limits"]["hard_time"] # Weight try: data["weight"] = float(data["weight"]) except: return json.dumps({"status": "error", "message": "Grade weight must be a floating-point number"}) # Accessible if data["accessible"] == "custom": data["accessible"] = "{}/{}".format(data["accessible_start"], data["accessible_end"]) elif data["accessible"] == "true": data["accessible"] = True else: data["accessible"] = False del data["accessible_start"] del data["accessible_end"] # Checkboxes if data.get("responseIsHTML"): data["responseIsHTML"] = True if data.get("contextIsHTML"): data["contextIsHTML"] = True except Exception as message: return json.dumps({"status": "error", "message": "Your browser returned an invalid form ({})".format(str(message))}) # Get the course try: course = FrontendCourse(courseid) except: return json.dumps({"status": "error", "message": "Error while reading course's informations"}) # Get original data try: orig_data = get_task_file_manager(courseid, taskid).read() data["order"] = orig_data["order"] except: pass try: FrontendTask(course, taskid, data) except Exception as message: return json.dumps({"status": "error", "message": "Invalid data: {}".format(str(message))}) if not os.path.exists(os.path.join(get_tasks_directory(), courseid, taskid)): os.mkdir(os.path.join(get_tasks_directory(), courseid, taskid)) if task_zip: try: zipfile = ZipFile(task_zip) except Exception as message: return json.dumps({"status": "error", "message": "Cannot read zip file. Files were not modified"}) try: zipfile.extractall(os.path.join(get_tasks_directory(), courseid, taskid)) except Exception as message: return json.dumps( {"status": "error", "message": "There was a problem while extracting the zip archive. Some files may have been modified"}) delete_all_possible_task_files(courseid, taskid) file_manager.write(data) return json.dumps({"status": "ok"})