Description:
add python support we compile it into bytecode before run (see 'judge' and 'run')
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r154:3e585749d18c - - 3 files changed: 34 inserted, 13 deleted

@@ -18,30 +18,33
18 18 if ENV['GRADER_LOGGING']!=nil
19 19 log_fname = ENV['GRADER_LOGGING']
20 20 fp = File.open(log_fname,"a")
21 21 fp.puts("run: #{Time.new.strftime("%H:%M")} #{str}")
22 22 fp.close
23 23 end
24 24 end
25 25
26 26 C_COMPILER = "/usr/bin/gcc"
27 27 CPLUSPLUS_COMPILER = "/usr/bin/g++"
28 28 PASCAL_COMPILER = "/usr/bin/fpc"
29 29 JAVA_COMPILER = "/usr/bin/javac"
30 - RUBY_INTEPRETER = "/home/dae/.rvm/rubies/ruby-1.9.2-p320/bin/ruby"
30 + RUBY_INTERPRETER = "/home/dae/.rvm/rubies/ruby-1.9.2-p320/bin/ruby"
31 + PYTHON_INTERPRETER = "/usr/bin/python"
32 + PYTHON_CHECKER = "/usr/bin/pyflakes"
31 33
32 34 C_OPTIONS = "-O2 -s -static -std=c99 -DCONTEST -lm -Wall"
33 35 CPLUSPLUS_OPTIONS = "-O2 -s -static -DCONTEST -lm -Wall"
34 36 PASCAL_OPTIONS = "-O1 -XS -dCONTEST"
35 37 JAVA_OPTIONS = ""
38 + PYTHON_OPTIONS = ""
36 39
37 40 # Check for the correct number of arguments. Otherwise, print usage.
38 41 if ARGV.length == 0 or ARGV.length > 4
39 42 puts "Usage: compile <language> [<source-file>] [<output-file>] [<message-file>]"
40 43 puts
41 44 puts "<source-file> is defaulted to \"source\"."
42 45 puts "<output-file> is defaulted to \"a.out\"."
43 46 puts "<message-file> is defaulted to \"compiler_message\"."
44 47 puts
45 48 exit(127)
46 49 end
47 50
@@ -78,66 +81,81
78 81 f.puts "ERROR: The source file did not exist."
79 82 end
80 83 exit(127)
81 84 end
82 85
83 86 if params[:prog_lang]=='cpp'
84 87 params[:prog_lang] = 'c++'
85 88 end
86 89
87 90 # Compile.
88 91 case params[:prog_lang]
89 92
90 - when "c"
93 + when "c"
91 94 command = "#{C_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{C_OPTIONS} 2> #{params[:message_file]}"
92 95 system(command)
93 96
94 - when "c++"
97 + when "c++"
95 98 command = "#{CPLUSPLUS_COMPILER} #{params[:source_file]} -o #{params[:output_file]} #{CPLUSPLUS_OPTIONS} 2> #{params[:message_file]}"
96 99 system(command)
97 100
98 - when "pas"
101 + when "pas"
99 102 command = "#{PASCAL_COMPILER} #{params[:source_file]} -ooutpas #{PASCAL_OPTIONS} > #{params[:message_file]}"
100 103 system(command)
101 104 FileUtils.mv("output", params[:output_file])
102 105
103 - when "java"
106 + when "java"
104 107 #rename the file to the public class name
105 108
106 109 #get the class name
107 110 classname = 'DUMMY'
108 111 File.foreach(params[:source_file]) do |line|
109 112 md = /\s*public\s*class\s*(\w*)/.match(line)
110 113 classname=md[1] if md
111 114 end
112 115 system("cp #{params[:source_file]} #{classname}.java")
113 116 command = "#{JAVA_COMPILER} #{classname}.java 2> #{params[:message_file]}"
114 117 system(command)
115 118 if File.exists?(classname + ".class")
116 119 File.open(params[:output_file],"w") {|file| file.write("#!/bin/sh\n/usr/bin/java #{classname}\n")}
117 120 File.chmod(0755, params[:output_file])
118 121 end
119 122
120 - when "ruby"
121 - command = "#{RUBY_INTEPRETER} -c #{params[:source_file]} > #{params[:message_file]}"
123 + when "ruby"
124 + command = "#{RUBY_INTERPRETER} -c #{params[:source_file]} > #{params[:message_file]}"
122 125 system(command)
123 126 File.open(params[:output_file],"w") do |out_file|
124 - out_file.puts "#!#{RUBY_INTEPRETER}"
127 + out_file.puts "#!#{RUBY_INTERPRETER}"
125 128 File.open(params[:source_file],"r").each do |line|
126 129 out_file.print line
127 130 end
128 131 end
129 132 File.chmod(0755, params[:output_file])
133 +
134 + when "python"
135 + command = "#{PYTHON_CHECKER} #{params[:source_file]} > #{params[:message_file]}"
136 + if system(command)
137 + #compile to python bytecode
138 + command = "#{PYTHON_INTERPRETER} -m py_compile #{params[:source_file]}"
139 + puts "compile: #{command}"
140 + system(command)
141 + puts "pwd: " + Dir.pwd
142 + Dir.new('.').each {|file| puts file}
143 + File.open(params[:output_file],"w") do |out_file|
144 + out_file.puts "#!#{PYTHON_INTERPRETER} #{params[:source_file]}c"
145 + end
146 + File.chmod(0755, params[:output_file])
147 + end
130 148
131 - else
149 + else
132 150 talk("ERROR: Invalid language specified!")
133 151 open(params[:message_file],"w") do |f|
134 152 f.puts "ERROR: Invalid language specified!"
135 153 end
136 154 exit(127)
137 155 end
138 156
139 157 # Report success or failure.
140 158 if FileTest.exists? params[:output_file]
141 159 talk "Compilation was successful!"
142 160 else
143 161 talk "ERROR: Something was wrong during the compilation!"
@@ -44,25 +44,25
44 44 # ARGV[2] --- test result directory
45 45 # ARGV[3] --- sandbox directory
46 46
47 47 if ARGV.length < 2 || ARGV.length > 4
48 48 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
49 49 puts " <sandbox-directory> is defaulted to ./sandbox"
50 50 puts " <test-result-directory> is defaulted to ./test-result"
51 51 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
52 52 exit(127)
53 53 end
54 54
55 55 language = ARGV[0]
56 - if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby"
56 + if language != "c" && language != "c++" && language != "pas" && language != "java" && language != "ruby" && language != "python"
57 57 log "You specified a language that is not supported: #{language}."
58 58 exit(127)
59 59 end
60 60
61 61 source_file = ARGV[1]
62 62 if File.exist?(source_file) == false
63 63 log "The source file does not exist."
64 64 exit(127)
65 65 end
66 66
67 67 log "Making test result and sandbox directories..."
68 68
@@ -102,48 +102,50
102 102 compile_message = open("compiler_message").read
103 103 compile_message.strip!
104 104 call_and_log("Cannot move the compiler message to #{test_result_dir}.") {
105 105 FileUtils.mv("compiler_message", test_result_dir)
106 106 }
107 107 if !FileTest.exist?("a.out")
108 108 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
109 109 exit(127)
110 110 else
111 111 call_and_log("Cannot move the compiled program to #{test_result_dir}") {
112 112 FileUtils.mv("a.out",test_result_dir)
113 113 if language == "java" then Dir["*.class"].each { |file| FileUtils.mv(file,test_result_dir)} end
114 + if language == "python" then Dir["*.pyc"].each { |file| FileUtils.mv(file,test_result_dir)} end
114 115 }
115 116 FileUtils.rm_rf("#{sandbox_dir}/.")
116 117 end
117 118
118 119 require "#{problem_home}/script/test_dsl.rb"
119 120 load "#{problem_home}/test_cases/all_tests.cfg"
120 121 problem = Problem.get_instance
121 122
122 123 if problem.well_formed? == false
123 124 log "The problem specification is not well formed."
124 125 exit(127)
125 126 end
126 127
127 128 # Doing the testing.
128 129 (1..(problem.num_tests)).each do |test_num|
129 130
130 131 $stdout.print "[#{test_num}]"
131 132 $stdout.flush
132 133
133 134 log "Test number: #{test_num}"
134 135
135 136 call_and_log("Cannot copy the compiled program into #{sandbox_dir}") {
136 137 FileUtils.cp("#{test_result_dir}/a.out", sandbox_dir, :preserve => true)
137 138 if language == "java" then Dir["#{test_result_dir}/*.class"].each { |file| FileUtils.cp(file,sandbox_dir)} end
139 + if language == "python" then Dir["#{test_result_dir}/*.pyc"].each { |file| FileUtils.cp(file,sandbox_dir)} end
138 140 }
139 141
140 142 begin
141 143 execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
142 144 rescue
143 145 # do nothing
144 146 end
145 147
146 148 call_and_log("Cannot create directory #{test_result_dir}/#{test_num}") {
147 149 FileUtils.mkdir "#{test_result_dir}/#{test_num}"
148 150 }
149 151 call_and_log("Cannot copy the result file into #{test_result_dir}/#{test_num}") {
@@ -87,27 +87,28
87 87 #run_command = "/usr/bin/time -f \"#{time_output_format}\" 2>run_result #{problem_home}/script/box_new -a 2 -f -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name}"
88 88 #
89 89
90 90
91 91
92 92
93 93 case language
94 94 when "java"
95 95 # for java, we have to add additional systemcall and we don't check the mem limit (dunno how to fix...)
96 96 run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s clone -s wait4 -p /usr/bin/ -p ./ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
97 97 when "ruby"
98 98 run_command = "#{problem_home}/script/box -T -t #{time_limit} -s getppid -s wait4 -s clone -s set_robust_list -s futex -s sigaltstack -p /dev/urandom -p ./ -p /home/dae/.rvm/rubies/ruby-1.9.2-p320/ -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
99 - when "c++"
100 - run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
101 - else
99 + when "python"
100 + #this code just run without any checking
101 + run_command = "#{problem_home}/script/box -T -t #{time_limit} -p #{problem_home}/ -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
102 + else # for c++, pascal, we do the normal checking
102 103 run_command = "#{problem_home}/script/box -a 2 -f -T -t #{time_limit} -m #{mem_limit} -i #{input_file_name} -o output.txt #{program_name} 2>run_result"
103 104 end
104 105
105 106
106 107 log "Running test #{test_num}..."
107 108 log run_command
108 109 log
109 110 system(run_command)
110 111
111 112 # Restore PROBLEM_HOME
112 113 ENV['PROBLEM_HOME'] = problem_home
113 114
You need to be logged in to leave comments. Login now