docs: def expand_entry(entry, ignore_xs=0x0):
      """Turn all Xs which are not marked in `ignore_xs` into ``0``\ s and
      ``1``\ s.
  
      The following will expand any Xs in bits ``1..3``\ ::
  
          >>> entry = RoutingTableEntry(set(), 0b0100, 0xfffffff0 | 0b1100)
          >>> list(expand_entry(entry, 0xfffffff1)) == [
          ...     RoutingTableEntry(set(), 0b0100, 0xfffffff0 | 0b1110),  # 010X
          ...     RoutingTableEntry(set(), 0b0110, 0xfffffff0 | 0b1110),  # 011X
          ... ]
          True
  
      Parameters
      ----------
      entry : :py:class:`~rig.routing_table.RoutingTableEntry` or similar
          The entry to expand.
      ignore_xs : int
          Bit-mask of Xs which should not be expanded.
  
      Yields
      ------
      :py:class:`~rig.routing_table.RoutingTableEntry`
          Routing table entries which represent the original entry but with all
          Xs not masked off by `ignore_xs` replaced with 1s and 0s.
      """
      # Get all the Xs in the entry that are not ignored
      xs = (~entry.key & ~entry.mask) & ~ignore_xs
  
      # Find the most significant X
      for bit in (1 << i for i in range(31, -1, -1)):
          if bit & xs:
              # Yield all the entries with this bit set as 0
              entry_0 = RoutingTableEntry(entry.route, entry.key,
                                          entry.mask | bit, entry.sources)
              for new_entry in expand_entry(entry_0, ignore_xs):
                  yield new_entry
  
              # And yield all the entries with this bit set as 1
              entry_1 = RoutingTableEntry(entry.route, entry.key | bit,
                                          entry.mask | bit, entry.sources)
              for new_entry in expand_entry(entry_1, ignore_xs):
                  yield new_entry
  
              # Stop looking for Xs
              break
      else:
          # If there are no Xs then yield the entry we were given.
          yield entry