Пример #1
0
def displayWork(form):
    """
    Provides the student-requested view of previously submitted work.
    """
    tamarin.printHeader()
    try:
        # Validate that this person is really capable of seeing this stuff
        # (throws exception if not)
        tamarin.authenticate(form.getfirst('user'), form.getfirst('pass'))
        if 'submission' in form:
            #wants to see a specific submission
            print('<br>')
            core_view.displaySubmission(form.getfirst('submission'))       
        else:
            #show them all their work
            #start form
            print('<form action="' + tamarin.CGI_URL + 'view.py" '
                  'method="post">')
            print('<input type="hidden" name="user" value="' + 
                  form.getfirst('user') + '">')
            print('<input type="hidden" name="pass" value="' + 
                  form.getfirst('pass') + '">')
            print('<div class="logout">[Close your browser to logout]</div>')
            core_view.displayUser(form.getfirst('user'), brief=True)
            print('</form>')
    
    except tamarin.TamarinError as err:
        tamarin.printError(err)
    except:
        tamarin.printError('UNHANDLED_ERROR')
    finally: 
        tamarin.printFooter()
Пример #2
0
def main(form=None):
    if not form:
        form = cgi.FieldStorage()
    tamarin.printHeader("Submission and Grading Results")
    print("<h2>Submission and Grading Results</h2>")
    try:
        print("<p>")

        # check that submitted form was correct with all needed details
        if "uploaded" not in form:
            raise TamarinError("BAD_SUBMITTED_FORM", "Missing uploaded field.")

        # validate filename format, printing username and assignment
        filename = form.getfirst("uploaded")
        match = re.match(tamarin.UPLOADED_RE, filename)
        if not match:
            raise TamarinError("BAD_SUBMITTED_FORM", "Wrong filename format.")

        print("<b>Username:</b> " + match.group(1) + "<br>")
        print("<b>Assignment:</b> " + match.group(2) + "<br>")

        # check that uploaded file really exists
        uploadedFilename = os.path.join(tamarin.UPLOADED_ROOT, filename)
        if not os.path.exists(uploadedFilename):
            raise TamarinError("NO_UPLOADED_FILE")

        # create submitted filename and move uploaded file to submitted folder
        currentStamp = tamarin.convertTimeToTimestamp()
        submittedFilename = filename.replace(".", "-" + currentStamp + ".", 1)
        submittedFilename = os.path.join(tamarin.SUBMITTED_ROOT, submittedFilename)
        shutil.move(uploadedFilename, submittedFilename)
        print("<b>File submitted at:</b> " + currentStamp + "<br>")
        # Yay!  Submission is successful, and user is DONE
        print("<i>--Submission completed successfully--</i>")
        print("</p>")

        # now start grading...
        # (In future, might have option to grade in real time.  For now,
        #  just start the grade pipe and print results.)
        startGradePipe()

    except TamarinError as err:
        tamarin.printError(err)
        print("<p>")
        print(
            "Due to the above error, your file was <i>not</i> successfully "
            "submitted. You may want to try again or else contact your "
            "Tamarin administrator "
        )
        if tamarin.ADMIN_EMAIL:
            print("(" + tamarin.ADMIN_EMAIL + ")")
        print(" with the details of the error you encountered.")
        print("</p>")
    except:
        tamarin.printError("UNHANDLED_ERROR")
    finally:
        tamarin.printFooter()
Пример #3
0
 def testPrintPage(self):
     """ printHeader and printFooter work. """
     printHeader()
     print("<p>Hello World.</p>")
     printFooter()
     #print(sys.stdout.getvalue(), file=sys.__stdout__)
     
     output = sys.stdout.getvalue()
     self.assertIn('<html>', output)
     self.assertIn('</html>', output)
     self.assertIn('Hello', output)
Пример #4
0
def main():
    """
    Displays current time, grading method, gradepipe status, number of
    uploaded (but unsubmitted files), and the submitted queue.
    """
    tamarin.printHeader("Tamarin Status")
    try: 
        print('<h2>Tamarin Status</h2>')
    
        # current time 
        # (Printed in two different formats as a way for users 
        # to learn how to make sense of Tamarin timestamp format)
        print('<p><b>Current System Time:</b> ')
        now = datetime.datetime.now()
        print(tamarin.convertTimeToTimestamp(now))
        print('&nbsp; (<i>' + now.isoformat(' ') + '</i>)')
        print('</p>')
    
        # uploaded file count
        print('<p><b>Uploaded (but not submitted) file count:</b> ')
        uploaded = glob.glob(os.path.join(tamarin.UPLOADED_ROOT, '*'))
        print(len(uploaded))
        
        # grade pipe status      
        print('<p><b>Gradepipe:</b> ')
        if os.path.exists(tamarin.GRADEPIPE_ACTIVE):
            print('<small>RUNNING</small>')
        else:
            print('<small>OFF</small>')
        if os.path.exists(tamarin.GRADEPIPE_DISABLED):
            print(' <small>(DISABLED)</small>')    
        print('</p>')
        
        # grading queue contents
        print('<p><b>Submitted (but not yet graded) queue:</b> ')
        submitted = tamarin.getSubmittedFilenames()
        if len(submitted) == 0:
            print('[empty]')
        else:
            print('<br>')
            for s in submitted:
                print('<span class="gradequeue">' + os.path.basename(s) + 
                      '</span><br>')
        print('</p>')

    except:
        tamarin.printError('UNHANDLED_ERROR')
    finally: 
        tamarin.printFooter()
Пример #5
0
def main(form=None):
    """
    Determine whether to show view login form, show all the user's work,
    or show a single given submission.
    """
    if not form:
        form = cgi.FieldStorage()
    if not form:
        # no values passed
        displayLogin()
    elif ('user' in form) and ('pass' in form):
        displayWork(form)
    else:
        tamarin.printHeader('File Upload Error')
        tamarin.printError('BAD_SUBMITTED_FORM')
        tamarin.printFooter()
Пример #6
0
def displayLogin():
    """
    Displays the login form to be used to view submissions.
    """
    tamarin.printHeader('View Submissions')
    print("""
<h2>View Submissions</h2>
<form class="html" action="/cgi-bin/view.py" method="post" 
  enctype="multipart/form-data">
<table>
<tr><td>Username:</td><td><input type="text" name="user"></td></tr>
<tr><td>Password:</td><td><input type="password" name="pass"></td></tr>
<tr><td colspan="2" style="text-align: center;">
  <input type="submit" value="View my submissions"></td></tr>
</table>
</form>
    """)
    tamarin.printFooter()
Пример #7
0
def displayUploadForm():
    """
    Displays the form to be used to upload a file.
    """
    printHeader('File Upload')
    print("""
<h2>File Upload</h2>  
<form class="html" action="/cgi-bin/upload.py" method="post" 
    enctype="multipart/form-data">
<table>
<tr><td>File (<code><i>Username</i>A##.<i>ext</i></code>):</td>
    <td><input type="file" name="file"></td></tr>
<tr><td>Your password:</td>
    <td><input type="password" name="pass"></td></tr>
<tr><td colspan="2" style="text-align: center;">
    <input type="submit" value="Upload this file for grading"></td></tr>
</table>
</form>
    """)
    printFooter()
Пример #8
0
def main(form=None):
    """
    Determine which mode to run in: are we displaying the upload page, 
    or processing a submission, or was there an error?
    """
    if form is None:
        form = cgi.FieldStorage()
        
    if not form:
        displayUploadForm()
    elif 'pass' in form and 'file' in form:
        validateUploadedFile(form)
    else:
        # XXX: You'll get this error if a binary file is uploaded and
        # Tamarin is running on Windows because, for some reason, the
        # pass field is then not submitted correctly.
        printHeader('File Upload Error')
        printError('BAD_SUBMITTED_FORM')
        #print(form);
        printFooter()
Пример #9
0
def main(form=None):
    if not form:
        form = cgi.FieldStorage()
    try:
        if not form:
            tamarin.printHeader('Tamarin Masterview')
            displayForm()
        
        elif 'modify' in form:
            # modify a submission's grade
            if 'submission' not in form or 'grade' not in form:
                # may have a comment too, but that can be blank
                tamarin.printHeader('Masterview: Modify error')
                raise TamarinError('BAD_SUBMITTED_FORM')        
            
            tamarin.printHeader("Masterview: Modified " + 
                                form.getfirst('submission'))
            modifySubmission(form.getfirst('submission'), 
                             form.getfirst('grade'), form.getfirst('verify'),
                             form.getfirst('comment'))
            core_view.displaySubmission(form.getfirst('submission'), 
                                        master=True)
        elif 'deleteComment' in form:
            # delete a comment from a submission
            if 'submission' not in form:
                tamarin.printHeader('Masterview: Delete comment error')
                raise TamarinError('BAD_SUBMITTED_FORM')
            
            tamarin.printHeader('Masterview: Deleted comment #' + 
                                form.getfirst('deleteComment'))
            deleteComment(form.getfirst('submission'), 
                          form.getfirst('deleteComment'))
            print('<br>')
            core_view.displaySubmission(form.getfirst('submission'), 
                                        master=True)
    
        elif 'submission' in form:
            # view a single specific submission 
            # (without modify or deleteComment, caught above)            
            tamarin.printHeader('Masterview: ' + form.getfirst('submission'))
            print('<br>')
            core_view.modifySubmission(form.getfirst('submission'))
       
        elif 'user' in form:
            # view all of a user's submissions
            tamarin.printHeader('Masterview: ' + form.getfirst('user'))
            core_view.displayUser(form.getfirst('user'),
                                  assignment=form.getfirst('assignment'),
                                  brief=form.getfirst('brief'), 
                                  master=True)
      
        elif 'assignment' in form:
            # without user given, or would have been caught above
            tamarin.printHeader('Masterview: ' + form.getfirst('assignment'))
            core_view.displayAssignment(form.getfirst('assignment'), 
                                        form.getfirst('brief'), 
                                        master=True)
                                          
        elif 'strip' in form: 
            tamarin.printHeader('Masterview: Stripping ' + 
                                form.getfirst('strip'))
            stripFiles(form.getfirst('strip'), form.getfirst('only'))

        elif 'verifyAll' in form: 
            tamarin.printHeader('Masterview: Verifying ' + 
                                form.getfirst('verifyAll'))
            markAllAsVerified(form.getfirst('verifyAll'))
        
        elif 'startGrader' in form:
            tamarin.printHeader('Masterview: Start grading pipeline')
            started = submit.startGradePipe(printStatus=False)
            if started:
                print('<p><br>Grading pipeline started.</p>')
            else:
                print('<p><br>Grader pipeline <b>not</b> started.')
                print('This is either because it is disabled or is already '
                      'running.')
                print('<p>See <a href="' + tamarin.CGI_URL + 
                      'status.py">status</a> ' + 'for more.</p>')
        elif 'gradesheet' in form:
                print("Content-Type: text/plain")
                print()
                displayGradeSheet(form.getfirst('comma'))
        else:
            tamarin.printHeader('Masterview: No valid option submitted')
            raise TamarinError('BAD_SUBMITTED_FORM')          

    except TamarinError as err:
        tamarin.printError(err)
    except:
        tamarin.printError('UNHANDLED_ERROR')
    finally:
        if not (form and 'gradesheet' in form):
            tamarin.printFooter()
Пример #10
0
def validateUploadedFile(form):
    """
    Processes a file upload.  
    
    Assumes the passed form is a valid query submission.  On an error, 
    reports what went wrong to the user. Otherwise confirms that the 
    user wants to submit the uploaded file for grading.
    """
    printHeader("File Upload Results")
    try: 
        print('<h2>File Upload Results</h2>')
        print('<p>')

        # get filename and check that file was properly uploaded
        assert 'file' in form and 'pass' in form, "Invalid form submission"
        filename = form['file'].filename
        if not filename:
            raise TamarinError('NO_FILE_UPLOADED')
        else:
            print('<!--Original filename: ' + filename + '-->')
            filename = stripFilename(filename)  #defined below
            print('<b>Filename:</b> ' + filename + '<br>')
            filecontents = form.getfirst('file')
            if not filecontents:
                raise TamarinError('EMPTY_FILE')
            
        # validate filename
        checkFilename(filename)
        
        # authenticate user 
        match = re.match(tamarin.UPLOADED_RE, filename)
        assert match  #because filename is valid from above
        username = match.group(1)
        username = username.lower()  #for any initial uppercase letter
        assignmentName = match.group(2)
        extension = match.group(3)
        password = form.getfirst('pass')
        
        print('<b>Username:</b> ' + username + '<br>')
        print('<b>Password:</b> ', end='')
        if password: 
            print('*' * len(password) + '<br>')
        else:
            print('[missing]<br>')      
        
        tamarin.authenticate(username, password)
    
        # validate that assignment exists
        print('<b>Assignment:</b> ' + assignmentName)  #... no <br> yet
        assignment = Assignment(assignmentName) #may throw TamarinError
        
        # confirm any type-specific requirements...
        # right extension?
        if extension != assignment.type.fileExt:
            raise TamarinError('WRONG_EXTENSION',
                'Your file is .' + extension + 
                ' but this assignment requires .' + assignment.type.fileExt)
        
        # initial cap?
        if assignment.type.initialCap and not re.match(r"^[A-Z]", filename):
            raise TamarinError('NO_INITIAL_CAP', filename)

        # check that file contents are plain text (if necessary)
        if assignment.type.encoding:
            try:
                # convert bytes to str
                filecontents = filecontents.decode(
                                    encoding=assignment.type.encoding)
                # files often uploaded in binary form from various OSs, 
                # so adjust line-endings
                # XXX: Still need this in Python3?
                filecontents = filecontents.replace('\r\n', '\r')
                # \n comes out properly as 0D0A on Windows
                filecontents = filecontents.replace('\r', '\n')  

            except UnicodeError as err:
                # this problem is often due to a copy-and-paste thing from a 
                # different encoding where a couple odd characters (like quotes
                # and such) come from a word processor.  So this will help 
                # students track down where their bad chars are in this most
                # common non-ASCII case
                lineCount = 1
                charCount = 1
                for char in filecontents: 
                    if char > 128:
                        print("<p><b>First non-ASCII character:</b>: ")
                        print("line " + str(lineCount) + ", char " + 
                              str(charCount) + "<br>")
                        break
                    elif char == '\n':  
                        # NOTE: line count only correct for Unix and Windows; 
                        # not old Mac, etc
                        lineCount += 1
                        charCount = 1
                    else:
                        charCount += 1
                raise TamarinError('BINARY_FILE', "This assignment requires "
                    "plain text files using the " + assignment.type.encoding +
                    " (or compatible) encoding, but: " + str(err))

        # Ready to accept based on submission itself.

        # Now see if late or already submitted (for warnings) or verified        
        # Reuse filename (without extension) from above
        wildFilename = filename.replace('.', '*.', 1)        
        alreadySubmitted = glob.glob(os.path.join(tamarin.SUBMITTED_ROOT, 
                                                  wildFilename))
        alreadyGraded = glob.glob(os.path.join(assignment.path, wildFilename))
        # but not all files in graded == a graded submission file if submitted
        # ext is same as grader output file ext, so remove grader output files
        for ag in alreadyGraded[:]: 
            if re.match(tamarin.GRADED_RE, os.path.basename(ag)):              
                alreadyGraded.remove(ag)   
        
        # determine lateness, so can print it here
        if assignment.isLate():
            print(' (<i>Late: </i>' + assignment.getLateOffset() + ')') 
            if assignment.isTooLate():
                raise TamarinError('SUBMISSION_TOO_LATE')
            if not tamarin.MAY_RESUBMIT_LATE and \
                    (alreadySubmitted or alreadyGraded):
                raise 'RESUBMISSION_LATE'
      
        # has a human already verified a previous submission?
        if not tamarin.MAY_RESUMBIT_AFTER_HUMAN and alreadyGraded:
            # check if a graded file has also been verified
            for f in alreadyGraded: 
                gradedF = GradedFile(os.path.basename(f))
                if gradedF.humanVerified:
                    # oops for student: already verified
                    raise TamarinError('PREVIOUS_SUBMISSION_VERIFIED')
                
        # display file contents (if appropriate)
        print('<p><b>Uploaded Code:</b></p>')
        print('<pre ' if assignment.type.preformatted else '<div ')
        print('class="code">')
        if not assignment.type.encoding:
            print('[ <i>binary file format: '
                  'cannot display contents here</i> ]')
        else:
            # prevent disappearing code due to code test looking like html tags
            if assignment.type.preformatted:
                print(html.escape(filecontents))
            else:
                print(html.escape(filecontents).replace('\n', '<br>\n'))            
        print('</pre>' if assignment.type.preformatted else '</div>')
      
        # Done!
        # write file (could result in an io error, handed as UNHANDLED below)
        uploadedFilename = os.path.join(tamarin.UPLOADED_ROOT, filename)
        overwrite = glob.glob(uploadedFilename)  #see if file already exists
        outfile = open(uploadedFilename, 
                       'w' if assignment.type.encoding else 'wb')
        outfile.write(filecontents)
        outfile.close()

        # give success message
        print('<p>')
        print('Your code (as shown above) has been uploaded to Tamarin. ')
        if overwrite:
            print('(Doing so overwrote a previously uploaded '
                  'but unsubmitted file of the same name.) ')
        print('<i>It has not yet been submitted.</i> ')

        # warn if already submitted (and/or graded) this assignment
        if alreadySubmitted or alreadyGraded:
            print('<p><b><i>Warning:</i></b> You already have ')
            if alreadySubmitted:
                print(str(len(alreadySubmitted)) + ' file(s) submitted '
                      '(but not yet graded) ')
                if alreadyGraded:
                    print('and ')
            if alreadyGraded:
                print(str(len(alreadyGraded)) + ' file(s) graded ')
            print('for this ' + str(assignment) + ' assignment. ')
            submitCount = len(alreadySubmitted) + len(alreadyGraded)
            if tamarin.RESUBMISSION_PENALTY:
                print('If you submit this uploaded file, it will be a ' +
                      '(resubmission * ' + str(submitCount) + '), ')
                print('and so its final score will be reduced by ' + 
                      str(round(submitCount * tamarin.RESUBMISSION_PENALTY, 
                                tamarin.GRADE_PRECISION)) + 
                      '.</p>')
                
        # provide submit button
        print("<p>If you are ready to officially submit this uploaded file "
              "for grading, click the button below. </p>")
        print()
        print('<form action="' + tamarin.CGI_URL + 'submit.py" '
              'method="post" class="html">')
        print('<input type="hidden" name="uploaded" value="' + filename + '">')
        print('<input type="submit" value="Submit this file" '
              'class="centered">')
        print('</form>')  
    
    except TamarinError as err:
        printError(err)
        print('<p>')
        print('Due to the above error, your uploaded file was not saved. ' 
            'Please <a href="' + tamarin.CGI_URL + 'upload.py' + 
            '">return to the upload page</a> and try again.')
        print('</p>')   
    except:
        printError('UNHANDLED_ERROR')
    finally: 
        printFooter()