docs: def write_model(self, file, model, pretty=False):
          """Write a given model to file.
  
          Args:
              file: File-like object open for writing.
              model: Instance of :class:`NativeModel` to write.
              pretty: Whether to format the XML output for readability.
          """
          ET.register_namespace('mathml', MATHML_NS)
          ET.register_namespace('xhtml', XHTML_NS)
          ET.register_namespace('fbc', FBC_V2)
  
          # Load compound information
          compound_name = {}
          compound_properties = {}
          for compound in model.compounds:
              compound_name[compound.id] = (
                  compound.name if compound.name is not None else compound.id)
              compound_properties[compound.id] = compound.properties
  
          model_reactions = set(model.model)
  
          reaction_properties = {}
          biomass_id = None
          for r in model.reactions:
              if (model_reactions is not None and
                      r.id not in model_reactions):
                  continue
  
              reaction_id = util.create_unique_id(
                  self._make_safe_id(r.id), reaction_properties)
              if r.id == model.biomass_reaction:
                  biomass_id = reaction_id
  
              reaction_properties[reaction_id] = r.properties
  
          # Add exchange reactions to reaction_properties,
          # also add flux limit info to flux_limits
          flux_limits = {}
          for compound, reaction_id, lower, upper in itervalues(model.exchange):
              # Create exchange reaction
              if reaction_id is None:
                  reaction_id = create_exchange_id(reaction_properties, compound)
              reaction_id = util.create_unique_id(
                  self._make_safe_id(reaction_id), reaction_properties)
  
              reaction_properties[reaction_id] = {
                  'id': reaction_id,
                  'equation': Reaction(Direction.Both, {compound: -1})
              }
  
              if lower is None:
                  lower = -model.default_flux_limit
              if upper is None:
                  upper = model.default_flux_limit
              flux_limits[reaction_id] = (lower, upper)
  
              # Create a dummy properties dict for undefined compounds
              if compound.name not in compound_properties:
                  compound_properties[compound.name] = {
                      'id': compound.name
                  }
  
          root = ET.Element(self._sbml_tag('sbml'))
          root.set(self._sbml_tag('level'), '3')
          root.set(self._sbml_tag('version'), '1')
          root.set(_tag('required', FBC_V2), 'false')
          if model.version_string is not None:
              notes_tag = ET.SubElement(root, self._sbml_tag('notes'))
              body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
              self._add_properties_notes(
                  body_tag, {'model version': model.version_string})
  
          model_tag = ET.SubElement(root, self._sbml_tag('model'))
          model_tag.set(_tag('strict', FBC_V2), 'true')
          if model.name is not None:
              model_tag.set(self._sbml_tag('name'), model.name)
  
          # Build mapping from Compound to species ID
          model_compartments = {}
          model_species = {}
          species_ids = set()
          for _, properties in iteritems(reaction_properties):
              for compound, _ in properties['equation'].compounds:
                  if compound in model_species:
                      continue
  
                  # Create a dummy properties dict for undefined compounds
                  if compound.name not in compound_properties:
                      compound_properties[compound.name] = {
                          'id': compound.name
                      }
  
                  compound_id = util.create_unique_id(
                      self._make_safe_id(compound.name), species_ids)
                  model_species[compound] = compound_id
                  species_ids.add(compound_id)
                  if compound.compartment not in model_compartments:
                      model_compartments[
                          compound.compartment] = 'C_' + util.create_unique_id(
                              self._make_safe_id(compound.compartment),
                              model_compartments)
  
          # Create list of compartments
          compartments = ET.SubElement(
              model_tag, self._sbml_tag('listOfCompartments'))
          for _, compartment_id in iteritems(model_compartments):
              compartment_tag = ET.SubElement(
                  compartments, self._sbml_tag('compartment'))
              compartment_tag.set(self._sbml_tag('id'), compartment_id)
              compartment_tag.set(self._sbml_tag('constant'), 'true')
  
          # Create list of species
          species_list = ET.SubElement(
              model_tag, self._sbml_tag('listOfSpecies'))
          for species, species_id in sorted(
                  iteritems(model_species), key=lambda x: x[1]):
              species_tag = ET.SubElement(species_list,
                                          self._sbml_tag('species'))
              species_tag.set(self._sbml_tag('id'), 'M_' + species_id)
              species_tag.set(
                  self._sbml_tag('name'),
                  compound_name.get(species.name, species.name))
              species_tag.set(
                  self._sbml_tag('compartment'),
                  model_compartments[species.compartment])
              species_tag.set(self._sbml_tag('constant'), 'false')
              species_tag.set(self._sbml_tag('boundaryCondition'), 'false')
              species_tag.set(self._sbml_tag('hasOnlySubstanceUnits'), 'true')
              if 'charge' in compound_properties[species.name]:
                  species_tag.set(_tag('charge', FBC_V2), text_type(
                      compound_properties[species.name]['charge']))
              if 'formula' in compound_properties[species.name]:
                  species_tag.set(_tag(
                      'chemicalFormula', FBC_V2), text_type(
                          compound_properties[species.name]['formula']))
  
              notes_tag = ET.SubElement(species_tag, self._sbml_tag('notes'))
              body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
              self._add_properties_notes(
                  body_tag, compound_properties[species.name])
  
          params_list = ET.SubElement(
              model_tag, self._sbml_tag('listOfParameters'))
  
          # Create mapping for reactions containing flux limit definitions
          for rxn_id, lower_lim, upper_lim in itervalues(model.limits):
              flux_limits[rxn_id] = lower_lim, upper_lim
  
          params = {}
          gene_ids = {}
  
          if biomass_id is not None:
              self._add_fbc_objective(model_tag, biomass_id)
  
          # Create list of reactions
          reactions = ET.SubElement(model_tag, self._sbml_tag('listOfReactions'))
          for eq_id, properties in sorted(iteritems(reaction_properties)):
              reaction_tag = ET.SubElement(reactions, self._sbml_tag('reaction'))
              equation = properties['equation']
  
              reaction_tag.set(self._sbml_tag('id'), 'R_' + eq_id)
              if 'name' in properties:
                  reaction_tag.set(self._sbml_tag('name'), properties['name'])
              reaction_tag.set(self._sbml_tag('reversible'), text_type(
                  equation.direction == Direction.Both).lower())
              reaction_tag.set(self._sbml_tag('fast'), 'false')
              lower_str, upper_str = self._get_flux_bounds(
                  eq_id, model, flux_limits, equation)
  
              params[upper_str] = 'P_'+self._make_safe_numerical_id(upper_str)
              params[lower_str] = 'P_'+self._make_safe_numerical_id(lower_str)
              reaction_tag.set(
                  _tag('upperFluxBound', FBC_V2), params[upper_str])
              reaction_tag.set(
                  _tag('lowerFluxBound', FBC_V2), params[lower_str])
  
              if 'genes' in properties:
                  self._add_gene_associations(
                      eq_id, properties['genes'], gene_ids, reaction_tag)
  
              if any(value < 0 for _, value in equation.compounds):
                  reactants = ET.SubElement(
                      reaction_tag, self._sbml_tag('listOfReactants'))
  
              if any(value > 0 for _, value in equation.compounds):
                  products = ET.SubElement(
                      reaction_tag, self._sbml_tag('listOfProducts'))
  
              for compound, value in sorted(equation.compounds):
                  dest_list = reactants if value < 0 else products
                  spec_ref = ET.SubElement(
                      dest_list, self._sbml_tag('speciesReference'))
                  spec_ref.set(
                      self._sbml_tag('species'), 'M_' + model_species[compound])
                  spec_ref.set(
                      self._sbml_tag('constant'), 'true')
                  spec_ref.set(
                      self._sbml_tag('stoichiometry'), text_type(abs(value)))
  
              notes_tag = ET.SubElement(reaction_tag, self._sbml_tag('notes'))
              body_tag = ET.SubElement(notes_tag, _tag('body', XHTML_NS))
              self._add_properties_notes(body_tag, reaction_properties[eq_id])
  
              if self._cobra_flux_bounds is True:
                  # Create COBRA-compliant parameter list
                  kl_tag = ET.SubElement(
                      reaction_tag, self._sbml_tag('kineticLaw'))
                  math_tag = ET.SubElement(kl_tag, self._sbml_tag('math'))
                  ci_tag = ET.SubElement(math_tag, _tag('ci', MATHML_NS))
                  ci_tag.text = 'FLUX_VALUE'
                  param_list = ET.SubElement(
                      kl_tag, self._sbml_tag('listOfParameters'))
  
                  ET.SubElement(param_list, self._sbml_tag('parameter'), {
                      self._sbml_tag('id'): 'LOWER_BOUND',
                      self._sbml_tag('name'): 'LOWER_BOUND',
                      self._sbml_tag('value'): lower_str,
                      self._sbml_tag('constant'): 'true'
                  })
                  ET.SubElement(param_list, self._sbml_tag('parameter'), {
                      self._sbml_tag('id'): 'UPPER_BOUND',
                      self._sbml_tag('name'): 'UPPER_BOUND',
                      self._sbml_tag('value'): upper_str,
                      self._sbml_tag('constant'): 'true'
                  })
  
          for val, id in iteritems(params):
              param_tag = ET.SubElement(params_list, self._sbml_tag('parameter'))
              param_tag.set(self._sbml_tag('id'), id)
              param_tag.set(self._sbml_tag('value'), val)
              param_tag.set(self._sbml_tag('constant'), 'true')
  
          self._add_gene_list(model_tag, gene_ids)
  
          tree = ET.ElementTree(root)
          if pretty:
              self._indent(root)
  
          write_options = dict(
              encoding='utf-8',
              default_namespace=self._namespace)
          if PY3:
              write_options['encoding'] = 'unicode'
          tree.write(file, **write_options)