2020from sqlalchemy .orm import Session
2121from traitlets .config import Config
2222from traitlets .config .configurable import LoggingConfigurable
23- from traitlets .traitlets import Callable , TraitError , Unicode , validate
23+ from traitlets .traitlets import Callable , Int , TraitError , Unicode , validate
2424
2525from grader_service .autograding .utils import rmtree
2626from grader_service .convert .converters .autograde import Autograde
3232from grader_service .orm .submission_properties import SubmissionProperties
3333
3434
35- def default_timeout_func (lecture : Lecture ) -> int :
36- return 360
37-
38-
3935class LocalAutogradeExecutor (LoggingConfigurable ):
4036 """
4137 Runs an autograde job on the local machine
@@ -49,11 +45,20 @@ class LocalAutogradeExecutor(LoggingConfigurable):
4945 git_executable = Unicode ("git" , allow_none = False ).tag (config = True )
5046
5147 timeout_func = Callable (
52- default_timeout_func ,
5348 allow_none = False ,
5449 help = "Function that takes a lecture as an argument and returns the cell timeout in seconds." ,
5550 ).tag (config = True )
5651
52+ default_cell_timeout = Int (300 , help = "Default cell timeout in seconds, defaults to 300" ).tag (
53+ config = True
54+ )
55+
56+ min_cell_timeout = Int (10 , help = "Min cell timeout in seconds, defaults to 10." ).tag (config = True )
57+
58+ max_cell_timeout = Int (84600 , help = "Max cell timeout in seconds, defaults to 86400" ).tag (
59+ config = True
60+ )
61+
5762 def __init__ (
5863 self , grader_service_dir : str , submission : Submission , close_session = True , ** kwargs
5964 ):
@@ -87,6 +92,8 @@ def __init__(
8792 self .autograding_status : Optional [str ] = None
8893 self .grading_logs : Optional [str ] = None
8994
95+ self .timeout_func = self ._determine_cell_timeout
96+
9097 def start (self ):
9198 """
9299 Starts the autograding job.
@@ -218,7 +225,7 @@ def _run(self):
218225 self ._write_gradebook (self ._put_grades_in_assignment_properties ())
219226
220227 c = Config ()
221- c .ExecutePreprocessor .timeout = self .timeout_func (self . assignment . lecture )
228+ c .ExecutePreprocessor .timeout = self .timeout_func ()
222229
223230 autograder = Autograde (
224231 self .input_path ,
@@ -474,6 +481,28 @@ def _run_subprocess(self, command: str, cwd: str) -> subprocess.CompletedProcess
474481 self .log .error (e )
475482 raise
476483
484+ def _determine_cell_timeout (self ):
485+ cell_timeout = self .default_cell_timeout
486+ if self .assignment .settings .cell_timeout is not None :
487+ custom_cell_timeout = self .assignment .settings .cell_timeout
488+ self .log .info (
489+ f"Found custom cell timeout in assignment settings: { custom_cell_timeout } seconds."
490+ )
491+ if custom_cell_timeout < self .min_cell_timeout :
492+ custom_cell_timeout = self .min_cell_timeout
493+ self .log .info (
494+ f"Custom cell timeout is smaller than the minimum, setting it to the minimum value: { custom_cell_timeout } ."
495+ )
496+ elif custom_cell_timeout > self .max_cell_timeout :
497+ custom_cell_timeout = self .max_cell_timeout
498+ self .log .info (
499+ f"Custom cell timeout is bigger than the maximum, setting it to the maximum value: { custom_cell_timeout } ."
500+ )
501+
502+ cell_timeout = custom_cell_timeout
503+
504+ return cell_timeout
505+
477506 @validate ("relative_input_path" , "relative_output_path" )
478507 def _validate_service_dir (self , proposal ):
479508 path : str = proposal ["value" ]
0 commit comments