human
Complete this python program:
def fake_ec_node_response(node_frags, policy):
assistant
#Here is the Python code you requested.

    """Given a list of entries for each node in ring order, where the entries
    are a dict (or list of dicts) which describes the fragment (or
    fragments) that are on the node; create a function suitable for use
    with capture_http_requests that will accept a req object and return a
    response that will suitably fake the behavior of an object server who
    had the given fragments on disk at the time.
    :param node_frags: a list. Each item in the list describes the
    fragments that are on a node; each item is a dict or list of dicts,
    each dict describing a single fragment; where the item is a list,
    repeated calls to get_response will return fragments in the order
    of the list; each dict has keys:
    - obj: an object stub, as generated by _make_ec_object_stub,
    that defines all of the fragments that compose an object
    at a specific timestamp.
    - frag: the index of a fragment to be selected from the object
    stub
    - durable (optional): True if the selected fragment is durable
    :param policy: storage policy to return
    """
    node_map = {}
    all_nodes = []
    call_count = {}
    def _build_node_map(req, policy):
        node_key = (lambda n: (n['ip'], n['port']))
        part = utils.split_path(req['path'], 5, 5, True)[1]
        all_nodes.extend(policy.object_ring.get_part_nodes(part))
        all_nodes.extend(policy.object_ring.get_more_nodes(part))
        for (i, node) in enumerate(all_nodes):
            node_map[node_key(node)] = i
            call_count[i] = 0
    for (i, frags) in enumerate(node_frags):
        if isinstance(frags, dict):
            node_frags[i] = [frags]
    def get_response(req):
        requested_policy = int(req['headers']['X-Backend-Storage-Policy-Index'])
        if (int(policy) != requested_policy):
            AssertionError("Requested    polciy    doesn't    fit    the    fake    response    policy")
        if (not node_map):
            _build_node_map(req, policy)
        try:
            node_index = node_map[(req['ip'], req['port'])]
        except KeyError:
            raise Exception(("Couldn't    find    node    %s:%s    in    %r" % (req['ip'], req['port'], all_nodes)))
        try:
            frags = node_frags[node_index]
        except IndexError:
            raise Exception(('Found    node    %r:%r    at    index    %s    -    but    only    got    %s    stub    response    nodes' % (req['ip'], req['port'], node_index, len(node_frags))))
        if (not frags):
            return StubResponse(404)
        resp_frag = frags[call_count[node_index]]
        call_count[node_index] += 1
        frag_prefs = req['headers'].get('X-Backend-Fragment-Preferences')
        if (not (frag_prefs or resp_frag.get('durable', True))):
            return StubResponse(404)
        obj_stub = resp_frag['obj']
        ts2frags = defaultdict(list)
        durable_timestamp = None
        for frag in frags:
            ts_frag = frag['obj']['timestamp']
            if frag.get('durable', True):
                durable_timestamp = ts_frag.internal
            ts2frags[ts_frag].append(frag['frag'])
 ...