def combined_options_fingerprint_for_scope(cls, scope, options,
                                             build_graph=None, **kwargs):
    """Given options and a scope, compute a combined fingerprint for the scope.

    :param string scope: The scope to fingerprint.
    :param Options options: The `Options` object to fingerprint.
    :param BuildGraph build_graph: A `BuildGraph` instance, only needed if fingerprinting
                                   target options.
    :param dict **kwargs: Keyword parameters passed on to
                          `Options#get_fingerprintable_for_scope`.
    :return: Hexadecimal string representing the fingerprint for all `options`
             values in `scope`.
    """
    fingerprinter = cls(build_graph)
    hasher = sha1()
    pairs = options.get_fingerprintable_for_scope(scope, **kwargs)
    for (option_type, option_value) in pairs:
      fingerprint = fingerprinter.fingerprint(option_type, option_value)
      if fingerprint is None:
        # This isn't necessarily a good value to be using here, but it preserves behavior from
        # before the commit which added it. I suspect that using the empty string would be
        # reasonable too, but haven't done any archaeology to check.
        fingerprint = 'None'
      hasher.update(fingerprint.encode('utf-8'))
    return hasher.hexdigest()
Given options and a scope, compute a combined fingerprint for the scope.

    :param string scope: The scope to fingerprint.
    :param Options options: The `Options` object to fingerprint.
    :param BuildGraph build_graph: A `BuildGraph` instance, only needed if fingerprinting
                                   target options.
    :param dict **kwargs: Keyword parameters passed on to
                          `Options#get_fingerprintable_for_scope`.
    :return: Hexadecimal string representing the fingerprint for all `options`
             values in `scope`.