def GET(self, courseid, taskid): """ GET request """ if User.is_logged_in(): try: course = FrontendCourse(courseid) if not course.is_open_to_user(User.get_username()): return renderer.course_unavailable() task = course.get_task(taskid) if not task.is_visible_by_user(User.get_username()): return renderer.task_unavailable() User.get_data().view_task(courseid, taskid) userinput = web.input() if "submissionid" in userinput and "questionid" in userinput: # Download a previously submitted file submission = submission_manager.get_submission(userinput["submissionid"], True) if submission is None: raise web.notfound() sinput = submission_manager.get_input_from_submission(submission, True) if userinput["questionid"] not in sinput: raise web.notfound() if isinstance(sinput[userinput["questionid"]], dict): # File uploaded previously mimetypes.init() mime_type = mimetypes.guess_type(urllib.pathname2url(sinput[userinput["questionid"]]['filename'])) web.header('Content-Type', mime_type[0]) return base64.b64decode(sinput[userinput["questionid"]]['value']) else: # Other file, download it as text web.header('Content-Type', 'text/plain') return sinput[userinput["questionid"]] else: # Display the task itself return renderer.task(course, task, submission_manager.get_user_submissions(task)) except: if web.config.debug: raise else: raise web.notfound() else: return renderer.index(False)
def POST(self, courseid, taskid): """ POST a new submission """ if User.is_logged_in(): try: course = FrontendCourse(courseid) if not course.is_open_to_user(User.get_username()): return renderer.course_unavailable() task = course.get_task(taskid) if not task.is_visible_by_user(User.get_username()): return renderer.task_unavailable() User.get_data().view_task(courseid, taskid) userinput = web.input() if "@action" in userinput and userinput["@action"] == "submit": # Verify rights if not task.can_user_submit(User.get_username()): return json.dumps({"status": "error", "text": "The deadline is over"}) # Reparse user input with array for multiple choices init_var = self.list_multiple_multiple_choices_and_files(task) userinput = task.adapt_input_for_backend(web.input(**init_var)) if not task.input_is_consistent(userinput): web.header('Content-Type', 'application/json') return json.dumps({"status": "error", "text": "Please answer to all the questions. Your responses were not tested."}) del userinput['@action'] # Get debug info if the current user is an admin debug = User.get_username() in course.get_admins() # Start the submission submissionid = submission_manager.add_job(task, userinput, debug) web.header('Content-Type', 'application/json') return json.dumps({"status": "ok", "submissionid": str(submissionid)}) elif "@action" in userinput and userinput["@action"] == "check" and "submissionid" in userinput: if submission_manager.is_done(userinput['submissionid']): web.header('Content-Type', 'application/json') result = submission_manager.get_submission(userinput['submissionid']) result = submission_manager.get_input_from_submission(result) return self.submission_to_json(result, User.get_username() in course.get_admins()) else: web.header('Content-Type', 'application/json') return json.dumps({'status': "waiting"}) elif "@action" in userinput and userinput["@action"] == "load_submission_input" and "submissionid" in userinput: submission = submission_manager.get_submission(userinput["submissionid"]) submission = submission_manager.get_input_from_submission(submission) if not submission: raise web.notfound() web.header('Content-Type', 'application/json') return self.submission_to_json(submission, (User.get_username() in course.get_admins()), True) else: raise web.notfound() except: if web.config.debug: raise else: raise web.notfound() else: return renderer.index(False)
def download_submission_set(self, submissions, filename, sub_folders): """ Create a tar archive with all the submissions """ if len(submissions) == 0: raise web.notfound(renderer.notfound("There's no submission that matches your request")) try: tmpfile = tempfile.TemporaryFile() tar = tarfile.open(fileobj=tmpfile, mode='w:gz') for submission in submissions: submission = get_input_from_submission(submission) # Compute base path in the tar file base_path = "/" for sub_folder in sub_folders: if sub_folder == 'taskid': base_path = submission['taskid'] + '/' + base_path elif sub_folder == 'username': base_path = submission['username'] + '/' + base_path submission_yaml = StringIO.StringIO(common.custom_yaml.dump(submission).encode('utf-8')) submission_yaml_fname = base_path + str(submission["_id"]) + '.test' info = tarfile.TarInfo(name=submission_yaml_fname) info.size = submission_yaml.len info.mtime = time.mktime(submission["submitted_on"].timetuple()) # Add file in tar archive tar.addfile(info, fileobj=submission_yaml) # If there is an archive, add it too if 'archive' in submission and submission['archive'] is not None and submission['archive'] != "": subfile = get_gridfs().get(submission['archive']) taskfname = base_path + str(submission["_id"]) + '.tgz' # Generate file info info = tarfile.TarInfo(name=taskfname) info.size = subfile.length info.mtime = time.mktime(submission["submitted_on"].timetuple()) # Add file in tar archive tar.addfile(info, fileobj=subfile) # If there files that were uploaded by the student, add them if submission['input'] is not None: for pid, problem in submission['input'].iteritems(): # If problem is a dict, it is a file (from the specification of the problems) if isinstance(problem, dict): # Get the extension (match extensions with more than one dot too) DOUBLE_EXTENSIONS = ['.tar.gz', '.tar.bz2', '.tar.bz', '.tar.xz'] if not problem['filename'].endswith(tuple(DOUBLE_EXTENSIONS)): _, ext = os.path.splitext(problem['filename']) else: for t_ext in DOUBLE_EXTENSIONS: if problem['filename'].endswith(t_ext): ext = t_ext subfile = StringIO.StringIO(base64.b64decode(problem['value'])) taskfname = base_path + str(submission["_id"]) + '_uploaded_files/' + pid + ext # Generate file info info = tarfile.TarInfo(name=taskfname) info.size = subfile.len info.mtime = time.mktime(submission["submitted_on"].timetuple()) # Add file in tar archive tar.addfile(info, fileobj=subfile) # Close tarfile and put tempfile cursor at 0 tar.close() tmpfile.seek(0) web.header('Content-Type', 'application/x-gzip', unique=True) web.header('Content-Disposition', 'attachment; filename="' + filename + '"', unique=True) return tmpfile except Exception as e: print e raise web.notfound()