コード例 #1
0
ファイル: submit.py プロジェクト: RealTimeWeb/websheets
def submit_and_log(websheet_name, student, client_request, meta):
    import sys, Websheet, re, cgi, os
    from config import run_java

    config.meta = meta

    websheet = Websheet.Websheet.from_filesystem(websheet_name)
    classname = websheet.classname

    errmsg = None
    epilogue = None

    def compile_and_run():
        nonlocal errmsg, epilogue

        user_poschunks = client_request["snippets"]

        # this is the pre-syntax check
        student_solution = websheet.make_student_solution(user_poschunks, "student")
        if student_solution[0] == False:
            if student_solution[1] == "Internal error! Wrong number of inputs":
                return ("Internal Error (Wrong number of snippets)", "Error: wrong number of snippets")
            errmsg = student_solution[1].split("\n")[1]
            return (
                "Pre-syntax Error",
                "<div class='pre-syntax-error'>Syntax error:"
                + "<pre>\n"
                + cgi.escape(student_solution[1])
                + "</pre></div>",
            )  # error text
        ss_to_ui_linemap = student_solution[2]

        def translate_line(ss_lineno):
            ss_lineno = int(ss_lineno)
            if ss_lineno in ss_to_ui_linemap:
                return str(ss_to_ui_linemap[ss_lineno])
            else:
                return "???(" + str(ss_lineno) + ")" + "<!--" + json.dumps(ss_to_ui_linemap) + "-->"

        reference_solution = websheet.get_reference_solution("reference")

        with open("GenericTester.java") as file:
            GTjava = "".join(file)

        dump = {
            "reference." + classname: reference_solution,
            "student." + classname: student_solution[1],
            "tester." + classname: websheet.make_tester(),
            "framework.GenericTester": GTjava,
        }

        # print(student_solution[1])

        for dep in websheet.dependencies:
            depws = Websheet.Websheet.from_filesystem(dep)
            submission = config.load_submission(student, dep, True)
            if submission == False:
                return (
                    "Dependency Error",
                    "<div class='dependency-error'><i>Dependency error</i>: "
                    + "You need to successfully complete the <a href='javascript:loadProblem(\""
                    + dep
                    + "\")'><tt>"
                    + dep
                    + "</tt></a> websheet first (while logged in).</div>",
                )  # error text
            submission = [{"code": x, "from": {"line": 0, "ch": 0}, "to": {"line": 0, "ch": 0}} for x in submission]
            dump["student." + dep] = depws.make_student_solution(submission, "student")[1]

            dump["reference." + dep] = depws.get_reference_solution("reference")

        compileRun = run_java("traceprinter/ramtools/CompileToBytes", json.dumps(dump))
        compileResult = compileRun.stdout
        if compileResult == "":
            return ("Internal Error (Compiling)", "<pre>\n" + cgi.escape(compileRun.stderr) + "</pre>")

        compileObj = json.loads(compileResult)

        #    print(compileObj['status'])

        if compileObj["status"] == "Internal Error":
            return ("Internal Error (Compiling)", "<pre>\n" + cgi.escape(compileObj["errmsg"]) + "</pre>")
        elif compileObj["status"] == "Compile-time Error":
            result = "Syntax error (could not compile):"
            result += "<br>"
            errorObj = compileObj["error"]
            result += "<tt>" + errorObj["filename"].split(".")[-2] + ".java</tt>, line "
            result += str(translate_line(errorObj["row"])) + ":"
            # result += str(errorObj['row']) + ':'
            result += "<pre>\n"
            # remove the safeexec bits
            result += cgi.escape(errorObj["errmsg"].replace("stdlibpack.", "").replace("student.", ""))
            result += "</pre>"
            return ("Syntax Error", result)

        #    print(compileResult)

        runUser = run_java("traceprinter/ramtools/RAMRun tester." + classname + " " + student, compileResult)
        # runUser = run_java("tester." + classname + " " + student)

        # print(runUser.stdout)
        RAMRunError = runUser.stdout.startswith("Error")
        RAMRunErrmsg = runUser.stdout[: runUser.stdout.index("\n")]

        runUser.stdout = runUser.stdout[runUser.stdout.index("\n") + 1 :]

        # print(runUser.stdout)
        # print(runUser.stderr)

        if runUser.returncode != 0 or runUser.stdout.startswith("Time Limit Exceeded"):
            errmsg = runUser.stderr.split("\n")[0]
            result = runUser.stdout
            result += "<div class='safeexec'>Crashed! The grader reported "
            result += "<code>"
            result += cgi.escape(errmsg)
            result += "</code>"
            result += "</div>"
            result += "<!--" + runUser.stderr + "-->"
            return ("Sandbox Limit", result)

        if RAMRunError:
            result += "<div class='safeexec'>Could not execute! "
            result += "<code>"
            result += cgi.escape(RAMRunErrmsg)
            result += "</code>"
            result += "</div>"
            return ("Internal Error (RAMRun)", result)

        runtimeOutput = re.sub(
            re.compile("at line (\d+) "),
            lambda match: "at line " + translate_line(match.group(1)) + " ",
            runUser.stdout,
        )

        # print(runtimeOutput)

        def ssf(s, t, u):  # substring from of s from after t to before u
            if t not in s:
                raise ValueError("Can't ssf(" + s + "," + t + "," + u + ")")
            s = s[s.index(t) + len(t) :]
            return s[: s.index(u)]

        if "<div class='error'>Runtime error:" in runtimeOutput:
            category = "Runtime Error"
            errmsg = ssf(runtimeOutput[runtimeOutput.index("<div class='error'>Runtime error:") :], "<pre >", "\n")
        elif "<div class='all-passed'>" in runtimeOutput:
            category = "Passed"
            epilogue = websheet.epilogue
        else:
            category = "Failed Tests"
            if "<div class='error'>" in runtimeOutput:
                errmsg = ssf(runtimeOutput, "<div class='error'>", "</div>")
            else:
                return (
                    "Internal Error",
                    "<b>stderr</b><pre>" + runUser.stderr + "</pre><b>stdout</b><br>" + runUser.stdout,
                )

        return (category, runtimeOutput)

    try:
        category, results = compile_and_run()
    except Exception:
        category = "Internal Error (Script)"
        import traceback

        results = "<pre>" + cgi.escape(traceback.format_exc()) + "</pre>"

    if category.startswith("Internal Error"):
        results = "<b><p>Internal Error; please report to course staff!</p></b>" + results

    import copy

    print_output = {"category": category, "results": results}
    save_this = {"category": category}
    if errmsg is not None:
        print_output["errmsg"] = errmsg
        save_this["errmsg"] = errmsg
    if epilogue is not None:  # no need to log this
        print_output["epilogue"] = epilogue

    passed = category == "Passed"

    if not client_request["viewing_ref"]:
        # remove positional information
        user_snippets = [blank["code"] for blank in client_request["snippets"]]
        config.save_submission(student, classname, user_snippets, save_this, passed)

    return json.dumps(print_output)
コード例 #2
0
ファイル: submit.py プロジェクト: usc-cs/websheets
def submit_and_log(websheet_name, student, client_request, meta):

  config.meta = meta

  websheet = Websheet.Websheet.from_name(websheet_name, client_request['preview']=='True', student)

  errmsg = None
  epilogue = None
  
  def compile_and_run():
    nonlocal errmsg, epilogue

    if websheet.nocode:
      if websheet.evaluate_nocode_submission(client_request["nocode_state"]):
        return ("Passed", "<div>Correct!</div>")
      else:
        return ("Failed", "<div>Not correct, please try again.</div>")

    user_poschunks = client_request["snippets"]

    # this is the pre-syntax check
    student_solution = websheet.combine_with_template(user_poschunks, "student")
    if student_solution[0] == False:
        if student_solution[1] == "Internal error! Wrong number of inputs":
          return("Internal Error (Wrong number of snippets)", "Error: wrong number of snippets")

        errmsg = student_solution[1].split('\n')
        if len(errmsg) > 1:
          errmsg = errmsg[1]
        else:
          errmsg = errmsg[0]
        
        return("Pre-syntax Error",
               "<div class='pre-syntax-error'>Syntax error:" + 
               "<pre>\n"+cgi.escape(student_solution[1])+"</pre></div>") # error text

    ss_to_ui_linemap = student_solution[2]

    def translate_line(ss_lineno):
        ss_lineno = int(ss_lineno)
        if ss_lineno in ss_to_ui_linemap:
          return str(ss_to_ui_linemap[ss_lineno])
        else:
          return "???("+str(ss_lineno)+")" + "<!--" + json.dumps(ss_to_ui_linemap) + "-->"
        
    reference_solution = websheet.get_reference_solution("reference")

    ss = student_solution[1]
    for i in range(len(ss)):
      if badchar(ss[i]):
        return("Pre-syntax Error",
               "<div class='pre-syntax-error'>Syntax error:" + 
               " Your code contains character number " + str(ord(ss[i])) + ":<br>" + 
               "<pre>"
               +("&hellip;" if i>5 else "")
               +cgi.escape(ss[max(0,i-5):i])
               +"<b style='background:orange'>"
               +cgi.escape(ss[i])+"</b>"
               +cgi.escape(ss[i+1:i+6])
               +("&hellip;" if i+5<len(ss) else "")
               +"</pre></div>")

    for verboten in websheet.verboten:
        for chunk in user_poschunks:
          if verboten in chunk['code']:
            return("Pre-syntax Error",
                   "<div class='pre-syntax-error'>" + 
                   "You can't use " + tt(verboten) + 
                   " in this exercise.</div>")

    #print(cgi.escape(student_solution[1]))
    #print(cgi.escape(reference_solution))

    if websheet.lang.startswith("C++"):
      student_solution = student_solution[1]
      if websheet.lang == "C++func":
        student_solution = re.sub(r"\bmain\b", "__student_main__", student_solution)

    if websheet.lang.startswith("C++"):
      import grade_cpp
      return grade_cpp.grade(reference_solution, student_solution, translate_line, websheet)
    elif websheet.lang == "Java":
      import grade_java
      # java needs to know student name to look up their solutions for dependencies
      return grade_java.grade(reference_solution, student_solution, translate_line, websheet, student)
    

  try:
    category, results = compile_and_run()
    config.uncreate_tempdirs()
  except Exception:
    category = "Internal Error (Script)"
    import traceback
    results = '<pre>' + cgi.escape(traceback.format_exc()) + '</pre>'

  if category.startswith("Internal Error"):
    results = "<b><p>"+category+"; please report to course staff!</p></b>" + results

  import copy
    
  print_output = {'category': category, 'results' : results}
  save_this = {'category': category}
  if errmsg is not None:
    print_output['errmsg'] = errmsg
    save_this['errmsg'] = errmsg
  if category=='Passed' and websheet.epilogue is not None: 
    print_output['epilogue'] = websheet.epilogue

  passed = (category == "Passed")

  global authinfo
  #print(authinfo)
  if authinfo["error_span"] != "":
    print_output["results"] = authinfo["error_span"]
    print_output["category"] = "Auth Error" 
    meta["logout_bug"] = True

  if (not client_request["viewing_ref"]):
    if websheet.nocode:
      user_state = client_request["nocode_state"]
    else:
      # remove positional information
      user_state = [blank["code"] for blank in client_request["snippets"]]
    config.save_submission(student, websheet.dbslug, user_state, save_this, passed)

  if websheet.attempts_until_ref == 'never':
    pass
  elif websheet.attempts_until_ref == 'infinity':
    if passed:
      print_output["reference_sol"] = websheet.get_reference_snippets()
  else:
    if passed or config.num_submissions(student, websheet.dbslug) == websheet.attempts_until_ref:
      print_output["reference_sol"] = websheet.get_reference_snippets()

  # we can't reliably track # submissions of anonymous users so put trust in the UI
  if ('reference_sol' not in print_output and authinfo['username'] == 'anonymous'
      and websheet.attempts_until_ref not in ['never', 'infinity']):
    print_output["anon_reference_sol"] = websheet.get_reference_snippets()

  return print_output