def _GetKeys(self, data, keys, depth=1):
    """Helper function to return keys nested in a bencode dict.

    By default this function will return the values for the named keys requested
    by a plugin in match{}. The default setting is to look a single layer down
    from the root (same as the check for plugin applicability). This level is
    suitable for most cases.

    For cases where there is variability in the name at the first level
    (e.g. it is the MAC addresses of a device, or a UUID) it is possible to
    override the depth limit and use _GetKeys to fetch from a deeper level.

    Args:
      data (dict[str, object]): bencode data values.
      keys (list[str]): keys that should be returned.
      depth (int): how many levels deep to check for a match.

    Returns:
      dict[str, object]: a dictionary with just the keys requested.
    """
    keys = set(keys)
    match = {}

    if depth == 1:
      for key in keys:
        match[key] = data[key]
    else:
      for _, parsed_key, parsed_value in self._RecurseKey(
          data, depth=depth):
        if parsed_key in keys:
          match[parsed_key] = parsed_value
          if set(match.keys()) == keys:
            return match
    return match
Helper function to return keys nested in a bencode dict.

    By default this function will return the values for the named keys requested
    by a plugin in match{}. The default setting is to look a single layer down
    from the root (same as the check for plugin applicability). This level is
    suitable for most cases.

    For cases where there is variability in the name at the first level
    (e.g. it is the MAC addresses of a device, or a UUID) it is possible to
    override the depth limit and use _GetKeys to fetch from a deeper level.

    Args:
      data (dict[str, object]): bencode data values.
      keys (list[str]): keys that should be returned.
      depth (int): how many levels deep to check for a match.

    Returns:
      dict[str, object]: a dictionary with just the keys requested.