Loads the data necessary for instantiating a client from file storage.

  In addition to the required_client_values argument, the yaml file must supply
  the keys used to create OAuth2 credentials. It may also optionally set proxy
  configurations.

  Args:
    yaml_doc: the yaml document whose keys should be used.
    product_yaml_key: The key to read in the yaml as a string.
    required_client_values: A tuple of strings representing values which must
      be in the yaml file for a supported API. If one of these keys is not in
      the yaml file, an error will  be raised.
    optional_product_values: A tuple of strings representing optional values
      which may be in the yaml file.

  Returns:
    A dictionary map of the keys in the yaml file to their values. This will not
    contain the keys used for OAuth2 client creation and instead will have a
    GoogleOAuth2Client object stored in the 'oauth2_client' field.

  Raises:
    A GoogleAdsValueError if the given yaml file does not contain the
    information necessary to instantiate a client object - either a
    required_client_values key was missing or an OAuth2 key was missing.

def LoadFromString(yaml_doc, product_yaml_key, required_client_values,
                   optional_product_values):
  """Loads the data necessary for instantiating a client from file storage.

  In addition to the required_client_values argument, the yaml file must supply
  the keys used to create OAuth2 credentials. It may also optionally set proxy
  configurations.

  Args:
    yaml_doc: the yaml document whose keys should be used.
    product_yaml_key: The key to read in the yaml as a string.
    required_client_values: A tuple of strings representing values which must
      be in the yaml file for a supported API. If one of these keys is not in
      the yaml file, an error will  be raised.
    optional_product_values: A tuple of strings representing optional values
      which may be in the yaml file.

  Returns:
    A dictionary map of the keys in the yaml file to their values. This will not
    contain the keys used for OAuth2 client creation and instead will have a
    GoogleOAuth2Client object stored in the 'oauth2_client' field.

  Raises:
    A GoogleAdsValueError if the given yaml file does not contain the
    information necessary to instantiate a client object - either a
    required_client_values key was missing or an OAuth2 key was missing.
  """
  data = yaml.safe_load(yaml_doc) or {}

  if 'dfp' in data:
    raise googleads.errors.GoogleAdsValueError(
        'Please replace the "dfp" key in the configuration YAML string with'
        '"ad_manager" to fix this issue.')

  logging_config = data.get(_LOGGING_KEY)
  if logging_config:
    logging.config.dictConfig(logging_config)

  try:
    product_data = data[product_yaml_key]
  except KeyError:
    raise googleads.errors.GoogleAdsValueError(
        'The "%s" configuration is missing'
        % (product_yaml_key,))

  if not isinstance(product_data, dict):
    raise googleads.errors.GoogleAdsValueError(
        'The "%s" configuration is empty or invalid'
        % (product_yaml_key,))

  IncludeUtilitiesInUserAgent(data.get(_UTILITY_REGISTER_YAML_KEY, True))

  original_keys = list(product_data.keys())
  client_kwargs = {}
  try:
    for key in required_client_values:
      client_kwargs[key] = product_data[key]
      del product_data[key]
  except KeyError:
    raise googleads.errors.GoogleAdsValueError(
        'Some of the required values are missing. Required '
        'values are: %s, actual values are %s'
        % (required_client_values, original_keys))

  proxy_config_data = data.get(_PROXY_CONFIG_KEY, {})
  proxy_config = _ExtractProxyConfig(product_yaml_key, proxy_config_data)
  client_kwargs['proxy_config'] = proxy_config
  client_kwargs['oauth2_client'] = _ExtractOAuth2Client(
      product_yaml_key, product_data, proxy_config)

  client_kwargs[ENABLE_COMPRESSION_KEY] = data.get(
      ENABLE_COMPRESSION_KEY, False)

  client_kwargs[CUSTOM_HEADERS_KEY] = data.get(CUSTOM_HEADERS_KEY, None)

  if SOAP_IMPLEMENTATION_KEY in data:
    client_kwargs[SOAP_IMPLEMENTATION_KEY] = data[SOAP_IMPLEMENTATION_KEY]

  for value in optional_product_values:
    if value in product_data:
      client_kwargs[value] = product_data[value]
      del product_data[value]

  if product_data:
    warnings.warn('Could not recognize the following keys: %s. '
                  'They were ignored.' % (product_data,), stacklevel=3)

  return client_kwargs