@@ -91,7 +91,14 @@ def __init__(
9191 * ,
9292 interactive : bool ,
9393 ) -> None :
94- """Initialise a job scheduler."""
94+ """Initialise a job scheduler.
95+
96+ Args:
97+ items: sequence of jobs to deploy.
98+ launcher_cls: Launcher class to use to deploy the jobs.
99+ interactive: launch the tools in interactive mode.
100+
101+ """
95102 self .items : Sequence [Deploy ] = items
96103
97104 # 'scheduled[target][cfg]' is a list of Deploy objects for the chosen
@@ -148,7 +155,7 @@ def __init__(
148155 msg = self .msg_fmt .format (0 , 0 , 0 , 0 , 0 , self ._total [target ])
149156 self .status_printer .init_target (target = target , msg = msg )
150157
151- # A map from the Deploy object names tracked by this class to their
158+ # A map from the Deployment names tracked by this class to their
152159 # current status. This status is 'Q', 'D', 'P', 'F' or 'K',
153160 # corresponding to membership in the dicts above. This is not
154161 # per-target.
@@ -271,8 +278,13 @@ def _enqueue_successors(self, item: Deploy | None = None) -> None:
271278 them to _queued.
272279 """
273280 for next_item in self ._get_successors (item ):
274- assert next_item .full_name not in self .item_status
275- assert next_item not in self ._queued [next_item .target ]
281+ if (
282+ next_item .full_name in self .item_status
283+ or next_item in self ._queued [next_item .target ]
284+ ):
285+ msg = f"Job { next_item .full_name } already scheduled"
286+ raise RuntimeError (msg )
287+
276288 self .item_status [next_item .full_name ] = "Q"
277289 self ._queued [next_item .target ].append (next_item )
278290 self ._unschedule_item (next_item )
@@ -281,6 +293,10 @@ def _cancel_successors(self, item: Deploy) -> None:
281293 """Cancel an item's successors.
282294
283295 Recursively move them from _scheduled or _queued to _killed.
296+
297+ Args:
298+ item: job whose successors are to be canceled.
299+
284300 """
285301 items = list (self ._get_successors (item ))
286302 while items :
@@ -291,14 +307,17 @@ def _cancel_successors(self, item: Deploy) -> None:
291307 def _get_successors (self , item : Deploy | None = None ) -> Sequence [Deploy ]:
292308 """Find immediate successors of an item.
293309
294- 'item' is a job that has completed. We choose the target that follows
295- the 'item''s current target and find the list of successors whose
296- dependency list contains 'item'. If 'item' is None, we pick successors
297- from all cfgs, else we pick successors only from the cfg to which the
298- item belongs.
310+ We choose the target that follows the 'item''s current target and find
311+ the list of successors whose dependency list contains 'item'. If 'item'
312+ is None, we pick successors from all cfgs, else we pick successors only
313+ from the cfg to which the item belongs.
314+
315+ Args:
316+ item: is a job that has completed.
317+
318+ Returns:
319+ list of item's successors, or an empty list if there are none.
299320
300- Returns the list of item's successors, or an empty list if there are
301- none.
302321 """
303322 if item is None :
304323 target = next (iter (self ._scheduled ))
@@ -320,8 +339,10 @@ def _get_successors(self, item: Deploy | None = None) -> Sequence[Deploy]:
320339 while not found :
321340 if target == item .target :
322341 found = True
342+
323343 try :
324344 target = next (target_iterator )
345+
325346 except StopIteration :
326347 return []
327348
@@ -349,7 +370,15 @@ def _get_successors(self, item: Deploy | None = None) -> Sequence[Deploy]:
349370 return successors
350371
351372 def _ok_to_enqueue (self , item : Deploy ) -> bool :
352- """Return true if ALL dependencies of item are complete."""
373+ """Check if all dependencies jobs are completed.
374+
375+ Args:
376+ item: is a deployment job.
377+
378+ Returns:
379+ true if ALL dependencies of item are complete.
380+
381+ """
353382 for dep in item .dependencies :
354383 # Ignore dependencies that were not scheduled to run.
355384 if dep not in self .items :
@@ -366,11 +395,18 @@ def _ok_to_enqueue(self, item: Deploy) -> bool:
366395 return True
367396
368397 def _ok_to_run (self , item : Deploy ) -> bool :
369- """Return true if the required dependencies have passed .
398+ """Check if a job is ready to start .
370399
371400 The item's needs_all_dependencies_passing setting is used to figure
372401 out whether we can run this item or not, based on its dependent jobs'
373402 statuses.
403+
404+ Args:
405+ item: is a deployment job.
406+
407+ Returns:
408+ true if the required dependencies have passed.
409+
374410 """
375411 # 'item' can run only if its dependencies have passed (their results
376412 # should already show up in the item to status map).
@@ -395,7 +431,9 @@ def _ok_to_run(self, item: Deploy) -> bool:
395431 def _poll (self , hms : str ) -> bool :
396432 """Check for running items that have finished.
397433
398- Returns True if something changed.
434+ Returns:
435+ True if something changed.
436+
399437 """
400438 max_poll = min (
401439 self .launcher_cls .max_poll ,
@@ -615,6 +653,11 @@ def _cancel_item(self, item: Deploy, *, cancel_successors: bool = True) -> None:
615653
616654 Supplied item may be in _scheduled list or the _queued list. From
617655 either, we move it straight to _killed.
656+
657+ Args:
658+ item: is a deployment job.
659+ cancel_successors: if set then cancel successors as well (True).
660+
618661 """
619662 self .item_status [item .full_name ] = "K"
620663 self ._killed [item .target ].add (item )
@@ -627,7 +670,12 @@ def _cancel_item(self, item: Deploy, *, cancel_successors: bool = True) -> None:
627670 self ._cancel_successors (item )
628671
629672 def _kill_item (self , item : Deploy ) -> None :
630- """Kill a running item and cancel all of its successors."""
673+ """Kill a running item and cancel all of its successors.
674+
675+ Args:
676+ item: is a deployment job.
677+
678+ """
631679 self ._launchers [item .full_name ].kill ()
632680 self .item_status [item .full_name ] = "K"
633681 self ._killed [item .target ].add (item )
0 commit comments