docs: def _to_map_job_config(cls,
                           mr_spec,
                           # TODO(user): Remove this parameter after it can be
                           # read from mr_spec.
                           queue_name):
      """Converts model.MapreduceSpec back to JobConfig.
  
      This method allows our internal methods to use JobConfig directly.
      This method also allows us to expose JobConfig as an API during execution,
      despite that it is not saved into datastore.
  
      Args:
        mr_spec: model.MapreduceSpec.
        queue_name: queue name.
  
      Returns:
        The JobConfig object for this job.
      """
      mapper_spec = mr_spec.mapper
      # 0 means all the old APIs before api_version is introduced.
      api_version = mr_spec.params.get("api_version", 0)
      old_api = api_version == 0
  
      # Deserialize params from json if input_reader/output_writer are new API.
      input_reader_cls = mapper_spec.input_reader_class()
      input_reader_params = input_readers._get_params(mapper_spec)
      if issubclass(input_reader_cls, input_reader.InputReader):
        input_reader_params = input_reader_cls.params_from_json(
            input_reader_params)
  
      output_writer_cls = mapper_spec.output_writer_class()
      output_writer_params = output_writers._get_params(mapper_spec)
      # TODO(user): Call json (de)serialization for writer.
      # if (output_writer_cls and
      #     issubclass(output_writer_cls, output_writer.OutputWriter)):
      #   output_writer_params = output_writer_cls.params_from_json(
      #       output_writer_params)
  
      # We can not always convert MapreduceSpec generated by older API
      # to JobConfig. Thus, mr framework should use/expose the returned JobConfig
      # object with caution when a job is started with an old API.
      # In this case, this method only tries not to blow up and assemble a
      # JobConfig object as accurate as possible.
      return cls(_lenient=old_api,
                 job_name=mr_spec.name,
                 job_id=mr_spec.mapreduce_id,
                 # handler_spec from older API may not have map_job.Mapper type.
                 mapper=util.for_name(mapper_spec.handler_spec),
                 input_reader_cls=input_reader_cls,
                 input_reader_params=input_reader_params,
                 output_writer_cls=output_writer_cls,
                 output_writer_params=output_writer_params,
                 shard_count=mapper_spec.shard_count,
                 queue_name=queue_name,
                 user_params=mr_spec.params.get("user_params"),
                 shard_max_attempts=mr_spec.params.get("shard_max_attempts"),
                 done_callback_url=mr_spec.params.get("done_callback"),
                 _force_writes=mr_spec.params.get("force_writes"),
                 _base_path=mr_spec.params["base_path"],
                 _task_max_attempts=mr_spec.params.get("task_max_attempts"),
                 _task_max_data_processing_attempts=(
                     mr_spec.params.get("task_max_data_processing_attempts")),
                 _hooks_cls=util.for_name(mr_spec.hooks_class_name),
                 _app=mr_spec.params.get("app_id"),
                 _api_version=api_version)