@@ -310,16 +310,6 @@ def configure_subparser(self, subparser):
310310 parsers .add_compilation_arguments (parser )
311311 return parser
312312
313- def parse_time (self , time_str ):
314- if len (time_str ) < 3 : return - 1
315- return int (time_str [:- 2 ])
316-
317-
318- def parse_memory (self , memory_str ):
319- if len (memory_str ) < 3 : return - 1
320- return int (memory_str [:- 2 ])
321-
322-
323313 def extract_file_name (self , file_path ):
324314 return os .path .split (file_path )[1 ]
325315
@@ -335,9 +325,6 @@ def get_solution_from_exe(self, executable):
335325 return file + ext
336326 util .exit_with_error ("Source file not found for executable %s" % executable )
337327
338- def get_executables (self , args_solutions ):
339- return [package_util .get_executable (solution ) for solution in package_util .get_solutions (self .ID , args_solutions )]
340-
341328
342329 def get_possible_score (self , groups ):
343330 possible_score = 0
@@ -397,246 +384,6 @@ def compile(self, solution, use_extras=False, remove_all_cache=False):
397384 compile .print_compile_log (compile_log_file )
398385 return False
399386
400- def check_output_diff (self , output_file , answer_file ):
401- """
402- Checks whether the output file and the answer file are the same.
403- """
404- return util .file_diff (output_file , answer_file )
405-
406- def check_output_checker (self , name , input_file , output_file , answer_file ):
407- """
408- Checks if the output file is correct with the checker.
409- Returns True if the output file is correct, False otherwise and number of points.
410- """
411- command = [self .checker_executable , input_file , output_file , answer_file ]
412- process = subprocess .Popen (command , stdout = subprocess .PIPE , stderr = subprocess .DEVNULL )
413- process .wait ()
414- checker_output = process .communicate ()[0 ].decode ("utf-8" ).splitlines ()
415-
416- if len (checker_output ) == 0 :
417- raise CheckerOutputException ("Checker output is empty." )
418-
419- if checker_output [0 ].strip () == "OK" :
420- points = 100
421- if len (checker_output ) >= 3 :
422- try :
423- points = int (checker_output [2 ].strip ())
424- except ValueError :
425- pass
426-
427- return True , points
428- else :
429- return False , 0
430-
431-
432- def check_output (self , name , input_file , output_file_path , output , answer_file_path ):
433- """
434- Checks if the output file is correct.
435- Returns a tuple (is correct, number of points).
436- """
437- try :
438- has_checker = self .checker is not None
439- except AttributeError :
440- has_checker = False
441-
442- if not has_checker :
443- with open (answer_file_path , "r" ) as answer_file :
444- correct = util .lines_diff (output , answer_file .readlines ())
445- return correct , 100 if correct else 0
446- else :
447- with open (output_file_path , "w" ) as output_file :
448- output_file .write ("\n " .join (output ) + "\n " )
449- return self .check_output_checker (name , input_file , output_file_path , answer_file_path )
450-
451- def execute_oiejq (self , name , timetool_path , executable , result_file_path , input_file_path , output_file_path , answer_file_path ,
452- time_limit , memory_limit , hard_time_limit , execution_dir ):
453- command = f'"{ timetool_path } " "{ executable } "'
454- env = os .environ .copy ()
455- env ["MEM_LIMIT" ] = f'{ memory_limit } K'
456- env ["MEASURE_MEM" ] = "1"
457- env ["UNDER_OIEJQ" ] = "1"
458-
459- timeout = False
460- with open (input_file_path , "r" ) as input_file , open (output_file_path , "w" ) as output_file , \
461- open (result_file_path , "w" ) as result_file :
462- process = subprocess .Popen (command , shell = True , stdin = input_file , stdout = output_file ,
463- stderr = result_file , env = env , preexec_fn = os .setsid , cwd = execution_dir )
464-
465- def sigint_handler (signum , frame ):
466- try :
467- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
468- except ProcessLookupError :
469- pass
470- sys .exit (1 )
471- signal .signal (signal .SIGINT , sigint_handler )
472-
473- try :
474- process .wait (timeout = hard_time_limit )
475- except subprocess .TimeoutExpired :
476- timeout = True
477- try :
478- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
479- except ProcessLookupError :
480- pass
481- process .communicate ()
482-
483- with open (result_file_path , "r" ) as result_file :
484- lines = result_file .read ()
485- with open (output_file_path , "r" ) as output_file :
486- output = output_file .read ()
487- result = ExecutionResult ()
488-
489- if not timeout :
490- lines = lines .splitlines ()
491- output = output .splitlines ()
492-
493- for line in lines :
494- line = line .strip ()
495- if ": " in line :
496- (key , value ) = line .split (": " )[:2 ]
497- if key == "Time" :
498- result .Time = self .parse_time (value )
499- elif key == "Memory" :
500- result .Memory = self .parse_memory (value )
501- else :
502- setattr (result , key , value )
503-
504- if timeout :
505- result .Status = Status .TL
506- elif getattr (result , "Time" ) is not None and result .Time > time_limit :
507- result .Status = Status .TL
508- elif getattr (result , "Memory" ) is not None and result .Memory > memory_limit :
509- result .Status = Status .ML
510- elif getattr (result , "Status" ) is None :
511- result .Status = Status .RE
512- elif result .Status == "OK" : # Here OK is a string, because it is set while parsing oiejq's output.
513- if result .Time > time_limit :
514- result .Status = Status .TL
515- elif result .Memory > memory_limit :
516- result .Status = Status .ML
517- else :
518- try :
519- correct , result .Points = self .task_type .check_output (input_file_path , output_file_path ,
520- output , answer_file_path )
521- if not correct :
522- result .Status = Status .WA
523- except CheckerOutputException as e :
524- result .Status = Status .CE
525- result .Error = e .message
526- else :
527- result .Status = result .Status [:2 ]
528-
529- return result
530-
531-
532- def execute_time (self , name , executable , result_file_path , input_file_path , output_file_path , answer_file_path ,
533- time_limit , memory_limit , hard_time_limit , execution_dir ):
534- if sys .platform == 'darwin' :
535- time_name = 'gtime'
536- elif sys .platform == 'linux' :
537- time_name = 'time'
538- elif sys .platform == 'win32' or sys .platform == 'cygwin' :
539- raise Exception ("Measuring time with GNU time on Windows is not supported." )
540-
541- command = [f'{ time_name } ' , '-f' , '%U\\ n%M\\ n%x' , '-o' , result_file_path , executable ]
542- timeout = False
543- mem_limit_exceeded = False
544- with open (input_file_path , "r" ) as input_file , open (output_file_path , "w" ) as output_file :
545- process = subprocess .Popen (command , stdin = input_file , stdout = output_file , stderr = subprocess .DEVNULL ,
546- preexec_fn = os .setsid , cwd = execution_dir )
547-
548- def sigint_handler (signum , frame ):
549- try :
550- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
551- except ProcessLookupError :
552- pass
553- sys .exit (1 )
554- signal .signal (signal .SIGINT , sigint_handler )
555-
556- start_time = time .time ()
557- while process .poll () is None :
558- try :
559- time_process = psutil .Process (process .pid )
560- executable_process = None
561- for child in time_process .children ():
562- if child .name () == executable :
563- executable_process = child
564- break
565- if executable_process is not None and executable_process .memory_info ().rss > memory_limit * 1024 :
566- try :
567- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
568- except ProcessLookupError :
569- pass
570- mem_limit_exceeded = True
571- break
572- except psutil .NoSuchProcess :
573- pass
574-
575- if time .time () - start_time > hard_time_limit :
576- try :
577- os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
578- except ProcessLookupError :
579- pass
580- timeout = True
581- break
582-
583- with open (output_file_path , "r" ) as output_file :
584- output = output_file .read ()
585- result = ExecutionResult ()
586- program_exit_code = None
587- if not timeout :
588- output = output .splitlines ()
589- with open (result_file_path , "r" ) as result_file :
590- lines = result_file .readlines ()
591- if len (lines ) == 3 :
592- """
593- If programs runs successfully, the output looks like this:
594- - first line is CPU time in seconds
595- - second line is memory in KB
596- - third line is exit code
597- This format is defined by -f flag in time command.
598- """
599- result .Time = round (float (lines [0 ].strip ()) * 1000 )
600- result .Memory = int (lines [1 ].strip ())
601- program_exit_code = int (lines [2 ].strip ())
602- elif len (lines ) > 0 and "Command terminated by signal " in lines [0 ]:
603- """
604- If there was a runtime error, the first line is the error message with signal number.
605- For example:
606- Command terminated by signal 11
607- """
608- program_exit_code = int (lines [0 ].strip ().split (" " )[- 1 ])
609- elif not mem_limit_exceeded :
610- result .Status = Status .RE
611- result .Error = "Unexpected output from time command: " + "" .join (lines )
612- return result
613-
614- if program_exit_code is not None and program_exit_code != 0 :
615- result .Status = Status .RE
616- elif timeout :
617- result .Status = Status .TL
618- elif mem_limit_exceeded :
619- result .Memory = memory_limit + 1 # Add one so that the memory is red in the table
620- result .Status = Status .ML
621- elif result .Time > time_limit :
622- result .Status = Status .TL
623- elif result .Memory > memory_limit :
624- result .Status = Status .ML
625- else :
626- try :
627- correct , result .Points = self .task_type .check_output (input_file_path , output_file_path ,
628- output , answer_file_path )
629- if correct :
630- result .Status = Status .OK
631- else :
632- result .Status = Status .WA
633- except CheckerOutputException as e :
634- result .Status = Status .CE
635- result .Error = e .message
636-
637- return result
638-
639-
640387 def run_solution (self , data_for_execution : ExecutionData ):
641388 """
642389 Run an execution and return the result as ExecutionResult object.
@@ -1173,16 +920,6 @@ def check_errors(self, results: Dict[str, Dict[str, Dict[str, ExecutionResult]]]
1173920 if error_msg != "" :
1174921 print (util .error (error_msg ))
1175922
1176- def compile_checker (self ):
1177- checker_basename = os .path .basename (self .checker )
1178- self .checker_executable = paths .get_executables_path (checker_basename + ".e" )
1179-
1180- checker_compilation = self .compile_solutions ([self .checker ], remove_all_cache = True )
1181- if not checker_compilation [0 ]:
1182- util .exit_with_error ('Checker compilation failed.' )
1183-
1184-
1185-
1186923 def compile_additional_files (self , files ):
1187924 for name , args , kwargs in files :
1188925 print (f'Compiling { name } ...' )
0 commit comments