Generates attributes values of specific edges

    Args:
        on_missing (str): Strategy for handling nodes missing from G.
            Can be {'error', 'default'}.  defaults to 'error'.
        on_keyerr (str): Strategy for handling keys missing from node dicts.
            Can be {'error', 'default'}.  defaults to 'default'
            if default is specified, otherwise defaults to 'error'.

def nx_gen_edge_values(G, key, edges=None, default=util_const.NoParam,
                       on_missing='error', on_keyerr='default'):
    """
    Generates attributes values of specific edges

    Args:
        on_missing (str): Strategy for handling nodes missing from G.
            Can be {'error', 'default'}.  defaults to 'error'.
        on_keyerr (str): Strategy for handling keys missing from node dicts.
            Can be {'error', 'default'}.  defaults to 'default'
            if default is specified, otherwise defaults to 'error'.
    """
    if edges is None:
        edges = G.edges()
    if on_missing is None:
        on_missing = 'error'
    if on_keyerr is None:
        on_keyerr = 'default'
    if default is util_const.NoParam and on_keyerr == 'default':
        on_keyerr = 'error'
    # Generate `data_iter` edges and data dictionary
    if on_missing == 'error':
        data_iter = (G.adj[u][v] for u, v in edges)
    elif on_missing == 'default':
        data_iter = (G.adj[u][v] if G.has_edge(u, v) else {}
                     for u, v in edges)
    else:
        raise KeyError('on_missing={} must be error, filter or default'.format(
            on_missing))
    # Get `value_iter` desired value out of dictionary
    if on_keyerr == 'error':
        value_iter = (d[key] for d in data_iter)
    elif on_keyerr == 'default':
        value_iter = (d.get(key, default) for d in data_iter)
    else:
        raise KeyError('on_keyerr={} must be error or default'.format(on_keyerr))
    return value_iter