docs: def convert_exchange_to_compounds(model):
      """Convert exchange reactions in model to exchange compounds.
  
      Only exchange reactions in the extracellular compartment are converted.
      The extracelluar compartment must be defined for the model.
  
      Args:
          model: :class:`NativeModel`.
      """
      # Build set of exchange reactions
      exchanges = set()
      for reaction in model.reactions:
          equation = reaction.properties.get('equation')
          if equation is None:
              continue
  
          if len(equation.compounds) != 1:
              # Provide warning for exchange reactions with more than
              # one compound, they won't be put into the exchange definition
              if (len(equation.left) == 0) != (len(equation.right) == 0):
                  logger.warning('Exchange reaction {} has more than one'
                                 ' compound, it was not converted to'
                                 ' exchange compound'.format(reaction.id))
              continue
  
          exchanges.add(reaction.id)
  
      # Convert exchange reactions into exchange compounds
      for reaction_id in exchanges:
          equation = model.reactions[reaction_id].equation
          compound, value = equation.compounds[0]
          if compound.compartment != model.extracellular_compartment:
              continue
  
          if compound in model.exchange:
              logger.warning(
                  'Compound {} is already defined in the exchange'
                  ' definition'.format(compound))
              continue
  
          # We multiply the flux bounds by value in order to create equivalent
          # exchange reactions with stoichiometric value of one. If the flux
          # bounds are not set but the reaction is unidirectional, the implicit
          # flux bounds must be used.
          lower_flux, upper_flux = None, None
          if reaction_id in model.limits:
              _, lower, upper = model.limits[reaction_id]
              if lower is not None:
                  lower_flux = lower * abs(value)
              if upper is not None:
                  upper_flux = upper * abs(value)
  
          if lower_flux is None and equation.direction == Direction.Forward:
              lower_flux = 0
          if upper_flux is None and equation.direction == Direction.Reverse:
              upper_flux = 0
  
          # If the stoichiometric value of the reaction is reversed, the flux
          # limits must be flipped.
          if value > 0:
              lower_flux, upper_flux = (
                  -upper_flux if upper_flux is not None else None,
                  -lower_flux if lower_flux is not None else None)
  
          model.exchange[compound] = (
              compound, reaction_id, lower_flux, upper_flux)
  
          model.reactions.discard(reaction_id)
          model.limits.pop(reaction_id, None)