<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def readGraph(edgeList, nodeList = None, directed = False, idKey = 'ID', eSource = 'From', eDest = 'To'):
 """Reads the files given by _edgeList_ and _nodeList_ and creates a networkx graph for the files. This is designed only for the files produced by metaknowledge and is meant to be the reverse of [writeGraph()](#metaknowledge.graphHelpers.writeGraph), if this does not produce the desired results the networkx builtin [networkx.read_edgelist()](https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.readwrite.edgelist.read_edgelist.html) could be tried as it is aimed at a more general usage. The read edge list format assumes the column named _eSource_ (default `'From'`) is the source node, then the column _eDest_ (default `'To'`) givens the destination and all other columns are attributes of the edges, e.g. weight. The read node list format assumes the column _idKey_ (default `'ID'`) is the ID of the node for the edge list and the resulting network. All other columns are considered attributes of the node, e.g. count. **Note**: If the names of the columns do not match those given to **readGraph()** a `KeyError` exception will be raised. **Note**: If nodes appear in the edgelist but not the nodeList they will be created silently with no attributes. # Parameters _edgeList_ : `str` > a string giving the path to the edge list file _nodeList_ : `optional [str]` > default `None`, a string giving the path to the node list file _directed_ : `optional [bool]` > default `False`, if `True` the produced network is directed from _eSource_ to _eDest_ _idKey_ : `optional [str]` > default `'ID'`, the name of the ID column in the node list _eSource_ : `optional [str]` > default `'From'`, the name of the source column in the edge list _eDest_ : `optional [str]` > default `'To'`, the name of the destination column in the edge list # Returns `networkx Graph` > the graph described by the input files """

    progArgs = (0, "Starting to reading graphs")
    if metaknowledge.VERBOSE_MODE:
        progKwargs = {'dummy' : False}
    else:
        progKwargs = {'dummy' : True}
    with _ProgressBar(*progArgs, **progKwargs) as PBar:
        if directed:
            grph = nx.DiGraph()
        else:
            grph = nx.Graph()
        if nodeList:
            PBar.updateVal(0, "Reading " + nodeList)
            f = open(os.path.expanduser(os.path.abspath(nodeList)))
            nFile = csv.DictReader(f)
            for line in nFile:
                vals = line
                ndID = vals[idKey]
                del vals[idKey]
                if len(vals) > 0:
                    grph.add_node(ndID, **vals)
                else:
                    grph.add_node(ndID)
            f.close()
        PBar.updateVal(.25, "Reading " + edgeList)
        f = open(os.path.expanduser(os.path.abspath(edgeList)))
        eFile = csv.DictReader(f)
        for line in eFile:
            vals = line
            eFrom = vals[eSource]
            eTo = vals[eDest]
            del vals[eSource]
            del vals[eDest]
            if len(vals) > 0:
                grph.add_edge(eFrom, eTo, **vals)
            else:
                grph.add_edge(eFrom, eTo)
        PBar.finish("{} nodes and {} edges found".format(len(grph.nodes()), len(grph.edges())))
        f.close()
        return grph