docs: def tuning_config(tuner, inputs, job_name=None):
      """Export Airflow tuning config from an estimator
  
      Args:
          tuner (sagemaker.tuner.HyperparameterTuner): The tuner to export tuning config from.
          inputs: Information about the training data. Please refer to the ``fit()`` method of
                  the associated estimator in the tuner, as this can take any of the following forms:
  
              * (str) - The S3 location where training data is saved.
              * (dict[str, str] or dict[str, sagemaker.session.s3_input]) - If using multiple channels for
                  training data, you can specify a dict mapping channel names
                  to strings or :func:`~sagemaker.session.s3_input` objects.
              * (sagemaker.session.s3_input) - Channel configuration for S3 data sources that can provide
                  additional information about the training dataset. See :func:`sagemaker.session.s3_input`
                  for full details.
              * (sagemaker.amazon.amazon_estimator.RecordSet) - A collection of
                  Amazon :class:~`Record` objects serialized and stored in S3.
                  For use with an estimator for an Amazon algorithm.
              * (list[sagemaker.amazon.amazon_estimator.RecordSet]) - A list of
                  :class:~`sagemaker.amazon.amazon_estimator.RecordSet` objects, where each instance is
                  a different channel of training data.
  
          job_name (str): Specify a tuning job name if needed.
  
      Returns:
          dict: Tuning config that can be directly used by SageMakerTuningOperator in Airflow.
      """
      train_config = training_base_config(tuner.estimator, inputs)
      hyperparameters = train_config.pop('HyperParameters', None)
      s3_operations = train_config.pop('S3Operations', None)
  
      if hyperparameters and len(hyperparameters) > 0:
          tuner.static_hyperparameters = \
              {utils.to_str(k): utils.to_str(v) for (k, v) in hyperparameters.items()}
  
      if job_name is not None:
          tuner._current_job_name = job_name
      else:
          base_name = tuner.base_tuning_job_name or utils.base_name_from_image(tuner.estimator.train_image())
          tuner._current_job_name = utils.name_from_base(base_name, tuner.TUNING_JOB_NAME_MAX_LENGTH, True)
  
      for hyperparameter_name in tuner._hyperparameter_ranges.keys():
          tuner.static_hyperparameters.pop(hyperparameter_name, None)
  
      train_config['StaticHyperParameters'] = tuner.static_hyperparameters
  
      tune_config = {
          'HyperParameterTuningJobName': tuner._current_job_name,
          'HyperParameterTuningJobConfig': {
              'Strategy': tuner.strategy,
              'HyperParameterTuningJobObjective': {
                  'Type': tuner.objective_type,
                  'MetricName': tuner.objective_metric_name,
              },
              'ResourceLimits': {
                  'MaxNumberOfTrainingJobs': tuner.max_jobs,
                  'MaxParallelTrainingJobs': tuner.max_parallel_jobs,
              },
              'ParameterRanges': tuner.hyperparameter_ranges(),
          },
          'TrainingJobDefinition': train_config
      }
  
      if tuner.metric_definitions is not None:
          tune_config['TrainingJobDefinition']['AlgorithmSpecification']['MetricDefinitions'] = \
              tuner.metric_definitions
  
      if tuner.tags is not None:
          tune_config['Tags'] = tuner.tags
  
      if s3_operations is not None:
          tune_config['S3Operations'] = s3_operations
  
      return tune_config