class_docstr: The execution engine will submit every model onto training service.
  
  Resource management is implemented in this class.
  
  This engine doesn't include any optimization across graphs.
  
  NOTE: Due to the design of `nni.experiment`,
  the execution engine resorts to NasExperiment to submit trials as well as waiting for results.
  This is not ideal, because this engine might be one of the very few engines which need the training service.
  Ideally, the training service should be a part of the execution engine, not the experiment.
  
  Ideally, this class should not have any states. Its save and load methods should be empty.
  
  Parameters
  ----------
  nodejs_binding
      The nodejs binding of the experiment.
  fetch_intermediates
      Whether to fetch intermediate results from the training service when list models.
      Setting it to false for large-scale experiments can improve performance.
class_docstr_tok: ["The","execution","engine","will","submit","every","model","onto","training","service",".","Resource","management","is","implemented","in","this","class",".","This","engine","does","n't","include","any","optimization","across","graphs",".","NOTE",":","Due","to","the","design","of","`","nni.experiment","`",",","the","execution","engine","resorts","to","NasExperiment","to","submit","trials","as","well","as","waiting","for","results",".","This","is","not","ideal",",","because","this","engine","might","be","one","of","the","very","few","engines","which","need","the","training","service",".","Ideally",",","the","training","service","should","be","a","part","of","the","execution","engine",",","not","the","experiment",".","Ideally",",","this","class","should","not","have","any","states",".","Its","save","and","load","methods","should","be","empty",".","Parameters","--","--","--","--","--","nodejs_binding","The","nodejs","binding","of","the","experiment",".","fetch_intermediates","Whether","to","fetch","intermediate","results","from","the","training","service","when","list","models",".","Setting","it","to","false","for","large-scale","experiments","can","improve","performance","."]
docstr: Wait models to finish training.
  
  If argument models is empty, wait for all models to finish.
  Using the experiment status as an indicator of all models' status,
  which is more efficient.
  
  For the models to receive status changes, the models must be the exact same instances as the ones submitted.
  Dumping and reloading the models, or retrieving the unsaved models from :meth:`list_models` won't work.
docstr_tok: ["Wait","models","to","finish","training",".","If","argument","models","is","empty",",","wait","for","all","models","to","finish",".","Using","the","experiment","status","as","an","indicator","of","all","models","'","status",",","which","is","more","efficient",".","For","the","models","to","receive","status","changes",",","the","models","must","be","the","exact","same","instances","as","the","ones","submitted",".","Dumping","and","reloading","the","models",",","or","retrieving","the","unsaved","models","from",":","meth",":","`","list_models","`","wo","n't","work","."]
code: def wait_models(self, *models: ExecutableModelSpace) -> None:
      """Wait models to finish training.
  
      If argument models is empty, wait for all models to finish.
      Using the experiment status as an indicator of all models' status,
      which is more efficient.
  
      For the models to receive status changes, the models must be the exact same instances as the ones submitted.
      Dumping and reloading the models, or retrieving the unsaved models from :meth:`list_models` won't work.
      """
      if not models:
          self._check_running()
  
          _logger.debug(
              "Waiting for models. Using experiment status as an indicator of all models' status."
          )
  
          training_model_patience = 0
  
          while True:
              status = self.nodejs_binding.get_status()
              if status in ["DONE", "STOPPED", "ERROR"]:
                  # Nodejs status changed. Stop waiting.
                  # (even if there are UNKNOWN trials)
                  return
  
              # If no more trial is not set, the experiment will always show as running.
              # We need to check trial status statistics to determine whether the experiment is done.
              stats = self.nodejs_binding.get_job_statistics()
              training_models_found = False
              for stat in stats:
                  if (
                      self._interpret_trial_job_status(
                          stat["trialJobStatus"]
                      )
                      == ModelStatus.Training
                  ):
                      training_models_found = True
                      break
  
              if training_models_found:
                  if training_model_patience != 0:
                      _logger.debug(
                          "Running models found. Resetting patience. Current stats: %s",
                          stats,
                      )
                      training_model_patience = 0
              else:
                  # The submit models could take up to 5 seconds to show up in the statistics.
                  _logger.debug(
                      "Waiting for running models to show up (patience: %d). Current stats: %s",
                      training_model_patience,
                      stats,
                  )
                  training_model_patience += 1
                  if training_model_patience > 6:
                      _logger.debug(
                          "No running models found. Assuming all models are done."
                      )
                      return
  
              time.sleep(1)
  
      super().wait_models(*models)
  
imports: from __future__ import annotations
  import logging
  import sys
  import time
  import weakref
  from threading import Event, Thread
  from typing import Iterable, TYPE_CHECKING, Any, cast
  import nni
  from nni.runtime.tuner_command_channel import command_type, TunerCommandChannel
  from nni.typehint import TrialMetric
  from nni.utils import MetricType
  from nni.nas.space import ExecutableModelSpace, ModelStatus, GraphModelSpace
  from .engine import ExecutionEngine
  from .event import FinalMetricEvent, IntermediateMetricEvent, TrainingEndEvent
label_desc: Use image node_id 2 for calling the TrainingServiceExecutionEngine obj's underlying member method code with example usage: obj.wait_models() without return types