          self.adj_weights[neighbor.key] = weight
          self.adj_nodes[neighbor.key] = neighbor
  
      def remove_neighbor(self, neighbor):
          if neighbor is None or neighbor.key not in self.adj_nodes:
              raise Exception('Invalid neighbor')
          neighbor.incoming_edges -= 1
          del self.adj_weights[neighbor.key]
          del self.adj_nodes[neighbor.key]
  
  
 
</s> remove     "        if neighbor is None or neighbor.key not in self.adj_nodes:\n",
    "            raise Exception('Invalid neighbor')\n",
 </s> add     "        if neighbor is None:\n",
    "            raise TypeError('neighbor cannot be None')\n",
    "        if neighbor.key not in self.adj_nodes:\n",
    "            raise KeyError('neighbor not found')\n", </s> remove         if neighbor is None:
            raise Exception('Invalid neighbor')
 </s> add         if neighbor is None or weight is None:
            raise TypeError('neighbor or weight cannot be None') </s> remove     "        if neighbor is None:\n",
    "            raise Exception('Invalid neighbor')\n",
 </s> add     "        if neighbor is None or weight is None:\n",
    "            raise TypeError('neighbor or weight cannot be None')\n", </s> remove             raise Exception('Invalid key')
 </s> add             raise TypeError('key cannot be None') </s> remove     "            raise Exception('Invalid key')\n",
 </s> add     "            raise TypeError('key cannot be None')\n",
        if neighbor is None:
            raise TypeError('neighbor cannot be None')
        if neighbor.key not in self.adj_nodes:
            raise KeyError('neighbor not found')
          self.adj_weights[neighbor.key] = weight
          self.adj_nodes[neighbor.key] = neighbor
  
      def remove_neighbor(self, neighbor):
        if neighbor is None:
            raise TypeError('neighbor cannot be None')
        if neighbor.key not in self.adj_nodes:
            raise KeyError('neighbor not found')
        if neighbor is None:
            raise TypeError('neighbor cannot be None')
        if neighbor.key not in self.adj_nodes:
            raise KeyError('neighbor not found')
          neighbor.incoming_edges -= 1
          del self.adj_weights[neighbor.key]
          del self.adj_nodes[neighbor.key]
  
  
keep keep keep keep replace replace keep keep keep keep keep
 Update graph challenge (#117)

Use more specific exception types. Update constraints. Update add_undirected_edge to use add_edge. 
graphs_trees/graph/graph.py