text: """Module for creating VRS objects"""
  from typing import List, Optional, Tuple, Union, Dict
  
  from ga4gh.vrs import models, normalize
  from ga4gh.vrs.dataproxy import SeqRepoDataProxy
  from ga4gh.core import ga4gh_identify
  from bioutils.accessions import coerce_namespace
  from uta_tools.data_sources import SeqRepoAccess
  
  
  class VRS:
      """VRS class"""
  
      def __init__(self, dp: SeqRepoDataProxy,
                   seqrepo_access: SeqRepoAccess) -> None:
          """Initialize VRS class
  
          :param SeqRepoAccess seqrepo_access: Access to SeqRepo
          :param SeqRepoDataProxy dp: SeqRepoDataProxy
          """
          self.seqrepo_access = seqrepo_access
          self.dp = dp
  
      @staticmethod
      def get_ival_start_end(
              coordinate: str, start: int, end: int, cds_start: int,
              errors: List) -> Optional[Tuple[int, int]]:
          """Get ival_start and ival_end coordinates.
  
          :param str coordinate: Coordinate used. Must be either `p`, `c`, or `g`
          :param int start: Start position change
          :param int end: End position change
          :param int cds_start: Coding start site
          :param List errors: List of errors
          :return: Tuple[ival_start, ival_end]
          """
          try:
              start = int(start)
              if end is None:
                  end = start
              end = int(end)
          except (ValueError, TypeError):
              errors.append("Start/End must be valid ints")
              return None
  
          if coordinate == "c":
              if cds_start:
                  start += cds_start
                  end += cds_start
          return start, end
  
      @staticmethod
      def get_start_indef_range(start: int) -> models.IndefiniteRange:
          """Return indefinite range given start coordinate
  
          :param int start: Start position (assumes 1-based)
          :return: Indefinite range model
          """
          return models.IndefiniteRange(value=start - 1, comparator="<=",
                                        type="IndefiniteRange")
  
      @staticmethod
      def get_end_indef_range(end: int) -> models.IndefiniteRange:
          """Return indefinite range given end coordinate
  
          :param int end: End position (assumes 1-based)
          :return: Indefinite range model
          """
          return models.IndefiniteRange(value=end, comparator=">=",
                                        type="IndefiniteRange")
  
      @staticmethod
      def get_ival_certain_range(start1: int, start2: int, end1: int,
                                 end2: int) -> models.SequenceInterval:
          """Return sequence interval
  
          :param int start1: Start left pos (assumes 1-based)
          :param int start2: Start right pos (assumes 1-based)
          :param int end1: End left pos (assumes 1-based)
          :param int end2: End right pos (assumes 1-based)
          :return: Sequence Interval model
          """
          return models.SequenceInterval(
              start=models.DefiniteRange(min=start1 - 1, max=start2 - 1,
                                         type="DefiniteRange"),
              end=models.DefiniteRange(min=end1 + 1, max=end2 + 1,
                                       type="DefiniteRange"),
              type="SequenceInterval"
          )
  
      @staticmethod
      def get_sequence_loc(
              ac: str, interval: models.SequenceInterval) -> models.Location:
          """Return VRS location
  
          :param str ac: Accession
          :param models.SequenceInterval interval: VRS sequence interval
          :return: VRS Location model
          """
          return models.SequenceLocation(
              sequence_id=coerce_namespace(ac),
              interval=interval, type="SequenceLocation")
  
      def vrs_allele(self, ac: str, interval: models.SequenceInterval,
                     sstate: Union[models.LiteralSequenceExpression,
                                   models.DerivedSequenceExpression,
                                   models.RepeatedSequenceExpression],
                     alt_type: str, errors: List) -> Optional[Dict]:
          """Create a VRS Allele object.
  
          :param str ac: Accession
          :param SequenceInterval interval: Sequence Interval
          :param sstate: State
          :type sstate: models.LiteralSequenceExpression or
              models.DerivedSequenceExpression or
              models.RepeatedSequenceExpression
          :param str alt_type: Type of alteration
          :param List errors: List of errors
          :return: VRS Allele object represented as a Dict
          """
          try:
              location = self.get_sequence_loc(ac, interval)
          except ValueError as e:
              errors.append(f"Unable to get sequence location: {e}")
              return None
          allele = models.Allele(location=location, state=sstate, type="Allele")
          # Ambiguous regions do not get normalized
          if alt_type not in ["uncertain_deletion", "uncertain_duplication",
                              "duplication_range", "deletion_range"]:
              try:
                  allele = normalize(allele, self.dp)
              except (KeyError, AttributeError) as e:
                  errors.append(f"vrs-python unable to normalize allele: {e}")
                  return None
  
          if not allele:
              errors.append("Unable to get allele")
              return None
  
          seq_id = self.dp.translate_sequence_identifier(
              allele.location.sequence_id._value, "ga4gh")[0]
          allele.location.sequence_id = seq_id
          allele.location._id = ga4gh_identify(allele.location)
          allele._id = ga4gh_identify(allele)
          return allele.as_dict()
  
      def to_vrs_allele(
              self, ac: str, start: int, end: int, coordinate: str,
              alt_type: str, errors: List, cds_start: int = None,
              alt: str = None) -> Optional[Dict]:
          """Translate accession and position to VRS Allele Object.
  
          :param str ac: Accession
          :param int start: Start position change
          :param int end: End position change
          :param str coordinate: Coordinate used. Must be either `p`, `c`, or `g`
          :param str alt_type: Type of alteration
          :param List errors: List of errors
          :param int cds_start: Coding start site
          :param str alt: Alteration
          :return: VRS Allele Object
          """
          ival_coords = self.get_ival_start_end(coordinate, start, end,
                                                cds_start, errors)
          if not ival_coords:
              return None
          if ival_coords[0] > ival_coords[1]:
              ival_end, ival_start = ival_coords
          else:
              ival_start, ival_end = ival_coords
  
          # Right now, this follows HGVS conventions
          # This will change once we support other representations
          if alt_type == "insertion":
              state = alt
              ival_end = ival_start
          elif alt_type in ["substitution", "deletion", "delins",
                            "silent_mutation", "nonsense"]:
              if alt_type == "silent_mutation":
                  state, _ = self.seqrepo_access.get_reference_sequence(ac, ival_start)
                  if state is None:
                      errors.append(f"Unable to get sequence on {ac} from "
                                    f"{ival_start}")
                      return None
              else:
                  state = alt or ""
              ival_start -= 1
          elif alt_type == "duplication":
              ref, _ = self.seqrepo_access.get_reference_sequence(
                  ac, ival_start, ival_end + 1)
              if ref is not None:
                  state = ref + ref
              else:
                  errors.append(f"Unable to get sequence on {ac} from "
                                f"{ival_start} to {ival_end + 1}")
                  return None
              ival_start -= 1
          else:
              errors.append(f"alt_type not supported: {alt_type}")
              return None
  
          interval = models.SequenceInterval(
              start=models.Number(value=ival_start, type="Number"),
              end=models.Number(value=ival_end, type="Number"),
              type="SequenceInterval")
          sstate = models.LiteralSequenceExpression(sequence=state,
                                                    type="LiteralSequenceExpression")
          return self.vrs_allele(ac, interval, sstate, alt_type, errors)
  
      def to_vrs_allele_ranges(
              self, ac: str, coordinate: str, alt_type: str, errors: List,
              ival: models.SequenceInterval) -> Optional[Dict]:
          """Translate variation ranges to VRS Allele Object.
  
          :param str ac: Accession
          :param str coordinate: Coordinate used. Must be either `p`, `c`, or `g`
          :param str alt_type: Type of alteration
          :param List errors: List of errors
          :param models.SequenceInterval ival: Sequence Interval
          :return: VRS Allele object
          """
          if coordinate == "c":
              # TODO: Once we add support for ranges on c. coord
              return None
          if alt_type in ["uncertain_deletion", "uncertain_duplication",
                          "duplication_range", "deletion_range"]:
              sstate = models.LiteralSequenceExpression(
                  sequence="", type="LiteralSequenceExpression"
              )
          else:
              errors.append("No state")
              return None
  
          return self.vrs_allele(ac, ival, sstate, alt_type, errors)
  