class_docstr: The real implementation behind external facing ``Tuner``.
  
  The external facing ``Tuner`` multiplexes between local Tuner and remote Tuner
  depending on whether in Ray client mode.
  
  In Ray client mode, external ``Tuner`` wraps ``TunerInternal`` into a remote actor,
  which is guaranteed to be placed on head node.
  
  ``TunerInternal`` can be constructed from fresh, in which case, ``trainable`` needs
  to be provided, together with optional ``param_space``, ``tune_config`` and
  ``run_config``.
  
  It can also be restored from a previous failed run (given ``restore_path``).
  
  Args:
      restore_path: The path from where the Tuner can be restored. If provided, None
          of the rest args are needed.
      resume_config: Resume config to configure which trials to continue.
      trainable: The trainable to be tuned.
      param_space: Search space of the tuning job.
          One thing to note is that both preprocessor and dataset can be tuned here.
      tune_config: Tuning algorithm specific configs.
          Refer to ray.tune.tune_config.TuneConfig for more info.
      run_config: Runtime configuration that is specific to individual trials.
          If passed, this will overwrite the run config passed to the Trainer,
          if applicable. Refer to ray.train.RunConfig for more info.
code: def __init__(
      self,
      restore_path: str = None,
      storage_filesystem: Optional[pyarrow.fs.FileSystem] = None,
      resume_config: Optional[_ResumeConfig] = None,
      trainable: Optional[TrainableTypeOrTrainer] = None,
      param_space: Optional[Dict[str, Any]] = None,
      tune_config: Optional[TuneConfig] = None,
      run_config: Optional[RunConfig] = None,
      _tuner_kwargs: Optional[Dict] = None,
      _entrypoint: AirEntrypoint = AirEntrypoint.TUNER,
  ):
      from ray.train.trainer import BaseTrainer
  
      if isinstance(trainable, BaseTrainer):
          run_config = self._choose_run_config(
              tuner_run_config=run_config,
              trainer=trainable,
              param_space=param_space,
          )
  
      self._tune_config = tune_config or TuneConfig()
      self._run_config = run_config or RunConfig()
      self._entrypoint = _entrypoint
  
      # Restore from Tuner checkpoint.
      if restore_path:
          self._restore_from_path_or_uri(
              path_or_uri=restore_path,
              trainable=trainable,
              overwrite_param_space=param_space,
              resume_config=resume_config,
              storage_filesystem=storage_filesystem,
          )
          return
  
      # Start from fresh
      if not trainable:
          raise TuneError("You need to provide a trainable to tune.")
  
      self.trainable = trainable
      assert self.converted_trainable
      self._validate_trainable(self.converted_trainable)
  
      self.param_space = param_space
  
      self._resume_config = None
      self._is_restored = False
      self._tuner_kwargs = copy.deepcopy(_tuner_kwargs) or {}
      (
          self._local_experiment_dir,
          self._experiment_dir_name,
      ) = self.setup_create_experiment_checkpoint_dir(
          self.converted_trainable, self._run_config
      )
      self._experiment_analysis = None
  
      # This needs to happen before `tune.run()` is kicked in.
      # This is because currently tune does not exit gracefully if
      # run in ray client mode - if crash happens, it just exits immediately
      # without allowing for checkpointing tuner and trainable.
      # Thus this has to happen before tune.run() so that we can have something
      # to restore from.
      experiment_checkpoint_path = Path(
          self._local_experiment_dir, _TUNER_PKL
      )
      with open(experiment_checkpoint_path, "wb") as fp:
          pickle.dump(self.__getstate__(), fp)
  
imports: import copy
  import io
  import os
  import math
  import logging
  from pathlib import Path
  from typing import Any, Callable, Dict, List, Optional, Type, Union, TYPE_CHECKING, Tuple
  import pyarrow.fs
  import ray.cloudpickle
  from ray.util import inspect_serializability
  from ray.air._internal.uri_utils import URI
  from ray.air._internal.usage import AirEntrypoint
  from ray.air.config import RunConfig, ScalingConfig
  from ray.train._internal.storage import StorageContext, get_fs_and_path
  from ray.tune import Experiment, TuneError, ExperimentAnalysis
  from ray.tune.execution.experiment_state import _ResumeConfig
  from ray.tune.tune import _Config
  from ray.tune.registry import is_function_trainable
  from ray.tune.result import _get_defaults_results_dir
  from ray.tune.result_grid import ResultGrid
  from ray.tune.trainable import Trainable
  from ray.tune.tune import run
  from ray.tune.tune_config import TuneConfig
  from ray.tune.utils import flatten_dict
label_desc: Use image node_id 1 to create a new TunerInternal object  with example: obj = TunerInternal(restore_path, storage_filesystem, resume_config, trainable, param_space, tune_config, run_config, _tuner_kwargs, _entrypoint)