def compile_student_source(stud, prob):
    '''Compiles the source code for student "stud/$stud" for the problem $prob'''

    short_write("[compiling: ")

    path = join(BaseDir, 'stud', stud, prob)    # path to source without extension
    makefile_path = join(BaseDir, 'prob', prob, 'makefile') # path to problem's makefile
    makefile_sample_path = join(BaseDir, 'scripts', 'sample_makefile') # path to sample makefile
    makefile_work_path = join(BaseDir, 'work', 'makefile')  # path to where makefile should be put
#    compile_command = {
#        '.c'   : "gcc -Wall -O2 -static %s.c -o work/the.exe -lm" % path,    # gcc command
#        '.cpp' : "g++ -Wall -O2 -static %s.cpp -o work/the.exe -lm" % path,  # g++ command
#        '.pas' : "fpc -O2 -Xs %s.pas -owork/the.exe" % path,                 # fpc command
#    }
    extension = 'no source file'                                                         # student has no source file

    for iterator in ['.adb', '.bas', '.bf', '.c', '.cs', '.cpp', '.d', '.java', '.lua', '.ocaml', '.pas', '.pike', '.pl', '.php', '.py', '.py3', '.rb', '.tcl']:
        if os.path.isfile(path + iterator):
            extension = iterator

    if extension == 'no source file':    # student does not have source file
        # aborting evaluation for this user on this problem
        print 'error]'
        eval_die("Student %s doesn't have any source for problem %s" % (stud, prob) )

    our = os.path.isfile(makefile_path + extension)
    sample = os.path.isfile(makefile_sample_path + extension)
    if our or sample:
        shutil.copy(ternary(our, makefile_path + extension, makefile_sample_path + extension), makefile_work_path)
        shutil.copy(path + extension, join(BaseDir, 'work/user' + extension))
        os.chdir('work')
        process = subprocess.Popen('make -s', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        compiler_message = process.communicate() [0]
        returncode = process.returncode
        os.chdir('..')
    else:
        print 'error]'
        eval_die("I don't have compile support for %s extension. I can't judge student %s on problem %s" % (extension, stud, prob))

    returncode = process.returncode
    if returncode != 0:
        print 'error]'
    else: short_write("ok] ")
    return (returncode, compiler_message)
 def sanity_check(student_dir, prob):
     if not isdir(student_dir):
         eval_die("Student %s doesn't exist in stud/" % stud)
     elif not filter(lambda x: x.startswith(prob), os.listdir(student_dir)):
         eval_die("Couldn't find any source code for student '%s' that would match problem %s" % (stud, prob))
def grade_student(stud, prob):
    # TODO return score
    '''Grade the student in "stud/$stud" on the problem $prob
    @returns score ?
    '''
    global job_number

    def sanity_check(student_dir, prob):
        if not isdir(student_dir):
            eval_die("Student %s doesn't exist in stud/" % stud)
        elif not filter(lambda x: x.startswith(prob), os.listdir(student_dir)):
            eval_die("Couldn't find any source code for student '%s' that would match problem %s" % (stud, prob))

    if global_grading is False:
        print "Grading student %s on problem %s" % (stud, prob)
    else:
        job_number += 1
        if where_interrupted and job_number < where_interrupted:
            return

    # FIXME
    # __params__ = i dunno
    # r = import_object('prob', prob, __params__)

    student_dir = join(BaseDir, 'stud', stud)

    try:
        sanity_check(student_dir, prob)

        problem = load_problem(prob)

        # Save the output somewhere
        output = taskeval.consoleapp.main_output = StringIO()
        if not global_grading:
            output.isatty = lambda: True

        if problem.opts['type'] == 'classical':
            returncode, compiler_message = compile_student_source(stud, prob)
            # TODO: save compiler_message somewhere
            compile_output_file = open(os.path.join(BaseDir, 'work', 'compile'), 'w')
            compile_output_file.writelines(compiler_message)
            compile_output_file.close()
            if returncode != 0:
                eval_die("Compile error")

            # evaluate the executable
            # the join BaseDir is "just in case", cause we chdir to BaseDir anyway
            score = taskeval.consoleapp.print_results(problem, join(BaseDir, "work", "the.exe"))
        elif problem.opts['type'] == 'output-only':
            score = taskeval.consoleapp.print_results(problem,
                join(student_dir, "%s-out" % prob), user_output = "?-%s.out")
        elif problem.opts['type'] == 'interactive':
            pass

        # TODO: save `output` somewhere
        eval_output_file = open(os.path.join(BaseDir, 'work', 'run.tmp'), "w")
        print >> eval_output_file, output.getvalue()
        eval_output_file.close()

        if global_grading is False:
            print '\nShowing compile details:\n'
            print compiler_message
            print 'Showing allres:\n'
            print output.getvalue()
            
    except EvalError, e:
        # handle the error
        print >>sys.stderr, 'Evaluation error:', e