<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def uniprot_mapping_and_metadata(self, model_gene_source, custom_gene_mapping=None, outdir=None, set_as_representative=False, force_rerun=False):
 """Map all genes in the model to UniProt IDs using the UniProt mapping service. Also download all metadata and sequences. Args: model_gene_source (str):
 the database source of your model gene IDs. See: http://www.uniprot.org/help/api_idmapping Common model gene sources are: * Ensembl Genomes - ``ENSEMBLGENOME_ID`` (i.e. E. coli b-numbers) * Entrez Gene (GeneID) - ``P_ENTREZGENEID`` * RefSeq Protein - ``P_REFSEQ_AC`` custom_gene_mapping (dict):
 If your model genes differ from the gene IDs you want to map, custom_gene_mapping allows you to input a dictionary which maps model gene IDs to new ones. Dictionary keys must match model genes. outdir (str):
 Path to output directory of downloaded files, must be set if GEM-PRO directories were not created initially set_as_representative (bool):
 If mapped UniProt IDs should be set as representative sequences force_rerun (bool):
 If you want to overwrite any existing mappings and files """


        # Allow model gene --> custom ID mapping ({'TM_1012':'TM1012'})
        if custom_gene_mapping:
            genes_to_map = list(custom_gene_mapping.values())
        else:
            genes_to_map = [x.id for x in self.genes]

        # Map all IDs first to available UniProts
        genes_to_uniprots = bs_unip.mapping(fr=model_gene_source, to='ACC', query=genes_to_map)

        successfully_mapped_counter = 0
        for g in tqdm(self.genes):
            if custom_gene_mapping and g.id in custom_gene_mapping.keys():
                uniprot_gene = custom_gene_mapping[g.id]
            else:
                uniprot_gene = g.id

            if uniprot_gene not in genes_to_uniprots:
                log.debug('{}: unable to map to UniProt'.format(g.id))
                continue

            for mapped_uniprot in genes_to_uniprots[uniprot_gene]:
                try:
                    uniprot_prop = g.protein.load_uniprot(uniprot_id=mapped_uniprot, download=True, outdir=outdir,
                                                          set_as_representative=set_as_representative,
                                                          force_rerun=force_rerun)
                except HTTPError as e:
                    log.error('{}, {}: unable to complete web request'.format(g.id, mapped_uniprot))
                    print(e)
                    continue

                if uniprot_prop.sequence_file or uniprot_prop.metadata_file:
                    successfully_mapped_counter += 1

        log.info('{}/{}: number of genes mapped to UniProt'.format(successfully_mapped_counter, len(self.genes)))
        log.info('Completed ID mapping --> UniProt. See the "df_uniprot_metadata" attribute for a summary dataframe.')