text: # -*- coding: utf-8 -*-
  
  """API utilities for KEGG."""
  
  import urllib.error
  from dataclasses import dataclass
  from typing import Mapping, Optional
  
  from pyobo import Reference, Term, ensure_path
  from pyobo.struct import from_species
  from pyobo.utils.path import ensure_df, prefix_directory_join
  
  KEGG_GENES_PREFIX = "kegg.genes"
  KEGG_GENOME_PREFIX = "kegg.genome"
  KEGG_PATHWAY_PREFIX = "kegg.pathway"
  
  BASE = "http://rest.kegg.jp"
  SKIP = {
      "T03333",
      "T03334",
      "T03356",
      "T03357",
      "T03358",
      "T03359",
  }
  
  
  @dataclass
  class KEGGGenome:
      """A data structure for a parsed line of the KEGG Genomes list."""
  
      identifier: str
      name: str
      code: Optional[str]
      long_code: Optional[str]
      taxonomy_id: Optional[str]
  
      def annotate_term(self, term: Term) -> None:
          """Annotate the term with the species represented by this object."""
          term.append_relationship(
              from_species,
              self.get_reference(),
          )
          if self.taxonomy_id is not None:
              term.set_species(self.taxonomy_id)
  
      def get_reference(self) -> Reference:
          """Get the reference for this genome."""
          return Reference(
              prefix="kegg.genome",
              identifier=self.identifier,
              name=self.name,
          )
  
  
  def ensure_list_genomes(version: str) -> str:
      """Ensure the KEGG Genome file is downloaded."""
      return ensure_path(
          KEGG_GENOME_PREFIX,
          url=f"{BASE}/list/genome",
          name="genome.tsv",
          version=version,
      )
  
  
  def ensure_list_pathways(version: str) -> Mapping[str, str]:
      """Ensure the KEGG Map (non species specific)."""
      rv = ensure_df(
          KEGG_PATHWAY_PREFIX,
          url=f"{BASE}/list/pathway",
          name="pathway.tsv",
          version=version,
      )
      return {k[len("path:") :]: v for k, v in rv.values}
  
  
  """GENOME SPECIFIC"""
  
  
  def ensure_list_genome(kegg_genome_id: str, *, version: str) -> str:
      """Get the list of genes for the given organism."""
      return ensure_path(
          KEGG_GENES_PREFIX,
          "genes",
          url=f"{BASE}/list/{kegg_genome_id}",
          name=f"{kegg_genome_id}.tsv",
          version=version,
      )
  
  
  def ensure_conv_genome_uniprot(
      kegg_genome_id: str, *, version: str, error_on_missing: bool = False
  ) -> Optional[str]:
      """Get the KEGG-UniProt protein map for the given organism."""
      return _ensure_conv_genome_helper(
          kegg_genome_id, "uniprot", version=version, error_on_missing=error_on_missing
      )
  
  
  def ensure_conv_genome_ncbigene(
      kegg_genome_id: str, *, version: str, error_on_missing: bool = False
  ) -> Optional[str]:
      """Get the KEGG-NCBIGENE protein map for the given organism."""
      return _ensure_conv_genome_helper(
          kegg_genome_id, "ncbi-geneid", version=version, error_on_missing=error_on_missing
      )
  
  
  def _ensure_conv_genome_helper(
      kegg_genome_id: str,
      target_database: str,
      *,
      version: str,
      error_on_missing: bool = False,
  ) -> Optional[str]:
      """Get the KEGG-external protein map for the given organism/database."""
      name = f"{kegg_genome_id}.tsv"
      try:
          rv = ensure_path(
              KEGG_GENES_PREFIX,
              f"conv_{target_database}",
              url=f"{BASE}/conv/{target_database}/{kegg_genome_id}",
              name=name,
              error_on_missing=error_on_missing,
              version=version,
          )
      except urllib.error.HTTPError:
          path_rv = prefix_directory_join(
              KEGG_GENES_PREFIX,
              f"conv_{target_database}",
              name=name,
              version=version,
          )
          with path_rv.open("w") as file:
              print(file=file)  # noqa: T201
          return path_rv.as_posix()
      except FileNotFoundError:
          return None
      else:
          return rv
  
  
  def ensure_link_pathway_genome(
      kegg_genome_id: str, *, version: str, error_on_missing: bool = False
  ) -> str:
      """Get the protein-pathway links for the given organism.
  
      :raises: FileNotFoundError
      """
      return ensure_path(
          KEGG_PATHWAY_PREFIX,
          "link_pathway",
          url=f"{BASE}/link/pathway/{kegg_genome_id}",
          name=f"{kegg_genome_id}.tsv",
          error_on_missing=error_on_missing,
          version=version,
      )
  
  
  def ensure_list_pathway_genome(
      kegg_genome_id: str, *, version: str, error_on_missing: bool = False
  ) -> str:
      """Get the list of pathways for the given organism.
  
      :raises: FileNotFoundError
      """
      return ensure_path(
          KEGG_PATHWAY_PREFIX,
          "pathways",
          url=f"{BASE}/list/pathway/{kegg_genome_id}",
          name=f"{kegg_genome_id}.tsv",
          error_on_missing=error_on_missing,
          version=version,
      )
  