docs: def sssr(molecule):
      """molecule -> generate the molecule.cycles that contain
      the smallest set of smallest rings"""
      results = {}
      lookup = {}
      fullSet = {}
      oatoms = {}
      # XXX FIX ME
      # copy atom.oatoms to atom._oatoms
      # atom._oatoms will be modified my the routine
  
      for atom in molecule.atoms:
          atom.rings = []
  	fullSet[atom.handle] = 1
  	lookup[atom.handle] = atom
          oatoms[atom.handle] = atom.oatoms[:]
  
      for bond in molecule.bonds:
          bond.rings = []
          
      trimSet = []
  
      while fullSet:
  	nodesN2 = []
          minimum, minimum_degree = None, 100000
  
  
  	# find the N2 atoms and remove atoms with degree 0
  	for atomID in fullSet.keys():
  	    atom = lookup[atomID]
  	    degree = len(oatoms[atom.handle])
  	    if degree == 0:
  		del fullSet[atomID]
  		#fullSet.remove(atomID)
  	    elif degree == 2:
  		nodesN2.append(atom)
  
  	    # keep track of the minimum degree
  	    if (degree > 0) and ( (not minimum) or 
  		                (degree < minimum_degree)):
  		minimum, minimum_degree = atom, degree
  
  	if not minimum:
  	    # nothing to do!  (i.e. can't have a ring)
  	    break
  
  	if minimum_degree == 1:
  	    # these cannot be in rings so trim and remove
  	    # my version of trimming
              for oatom in oatoms[minimum.handle]:
  		oatoms[oatom.handle].remove(minimum)
              oatoms[minimum.handle] = []
  	    del fullSet[minimum.handle]
  
  	elif minimum_degree == 2:
  	    # find the rings!
  	    startNodes = []
  	    for atom in nodesN2:
  		ring, bonds = getRing(atom, fullSet, lookup, oatoms)
  
  		if ring:
                      rlookup = ring[:]
                      rlookup.sort()
                      rlookup = tuple(rlookup)
  		    if (not results.has_key(rlookup)):# not in results):
  			results[rlookup] = ring, bonds
  			startNodes.append(atom)
  
  	    # in case we didn't get a ring remove the head of the nodesN2
  	    startNodes = startNodes or [nodesN2[0]]
  	    for atom in startNodes:
  		# again, my version of trimming
                  if oatoms[atom.handle]:
  		    oatom = oatoms[atom.handle].pop()
  		    oatoms[oatom.handle].remove(atom)
  
  	elif minimum_degree > 2:
  	    # no N2 nodes so remove the "optimum" edge to create
  	    # N2 nodes in the next go-around.
  	    ring, bonds = getRing(minimum, fullSet, lookup, oatoms)
              if ring:
                  key = ring[:]
                  key.sort()
                  key = tuple(key)
                  if not results.has_key(key):
                      results[key] = ring, bonds
                      atoms = map(lookup.get, ring)
                      atoms, bonds = toposort(atoms, bonds)
                      checkEdges(atoms, lookup, oatoms)
              else:
                  del fullSet[minimum.handle]
   	else:
  	    raise ShouldntGetHereError
  
      # assign the ring index to the atom
      rings = []
      index = 0
  
      # transform the handles back to atoms
      for result, bonds in results.values():
  	ring = []
          for atomID in result:
  	    atom = lookup[atomID]
              assert atom.handle == atomID
  	    ring.append(atom)
  	rings.append((ring, bonds))
          index = index + 1
  
      molecule.rings = rings
      potentialCycles = []
      index = 0
      for atoms, bonds in rings:
          # due to the dictionaries used in getRing
          # the atoms are not in the order found
          # we need to topologically sort these
          # for the cycle
          atoms, bonds = toposort(atoms, bonds)
          potentialCycles.append((atoms, bonds))
  
      rings = potentialCycles#checkRings(potentialCycles)
      molecule.rings = rings
      molecule.cycles = [Cycle(atoms, bonds) for atoms, bonds in rings]
      return molecule