Repository: ga4gh/vrs-python

Issue:
DataProxy.is_valid_ref_seq() return signature simplificiation
I think the return object could be simplified here. If `is_valid` is always false when `err_msg` is anything other than an empty string, and always true if `err_msg` is an empty string, does it add any additional information? Could we rephrase this to simply check for invalidity, returning `None` if there are no invalidations, and a string description if it is invalid? Alternatively -- maybe raise an exception if invalid and do nothing if valid? (there's a similar pattern in the popular `requests` library where the `raise_for_status()` method raises an Exception if an HTTP request returns an error code, but is silent otherwise)

_Originally posted by @jsstevenson in https://github.com/ga4gh/vrs-python/pull/366#discussion_r1536120504_
            

Discussion:

Patch:
diff --git a/src/ga4gh/vrs/dataproxy.py b/src/ga4gh/vrs/dataproxy.py
index 47732ff..51d70d9 100644
--- a/src/ga4gh/vrs/dataproxy.py
+++ b/src/ga4gh/vrs/dataproxy.py
@@ -22,6 +22,10 @@ import requests
 _logger = logging.getLogger(__name__)
 
 
+class DataProxyValidationError(Exception):
+    """Class for validation errors during data proxy methods"""
+
+
 class _DataProxy(ABC):
     """abstract class / interface for VRS data needs
 
@@ -119,7 +123,7 @@ class _DataProxy(ABC):
             nsd = namespace + ":"
             aliases = [a for a in aliases if a.startswith(nsd)]
         return aliases
-        
+
     def derive_refget_accession(self, ac: str):
         """Derive the refget accession from a public accession identifier
 
@@ -129,9 +133,9 @@ class _DataProxy(ABC):
 
         if ac is None:
             return None
-        
+
         if ":" not in ac[1:]:
-            # always coerce the namespace if none provided 
+            # always coerce the namespace if none provided
             ac = coerce_namespace(ac)
 
         refget_accession = None
@@ -144,32 +148,38 @@ class _DataProxy(ABC):
                 refget_accession = aliases[0].split("ga4gh:")[-1]
 
         return refget_accession
-    
-    def is_valid_ref_seq(
-        self, sequence_id: str, start_pos: int, end_pos: int, ref: str
-    ) -> Tuple[bool, str]:
-        """Return wether or not the expected reference sequence matches the actual
-        reference sequence
+
+    def validate_ref_seq(
+        self, sequence_id: str, start_pos: int, end_pos: int, ref: str,
+        require_validation: bool = True
+    ) -> None:
+        """Determine whether or not the expected reference sequence matches the actual
+        reference sequence. Returns ``None``, but invalid results are logged at level
+        WARN by default. If ``require_validation`` is ``True``, then invalid data will
+        cause a ``DataProxyValidationError`` to be raised.
 
         :param sequence_id: Sequence ID to use
         :param start_pos: Start pos (inter-residue) on the sequence_id
         :param end_pos: End pos (inter-residue) on the sequence_id
         :param ref: The expected reference sequence on the sequence_id given the
             start_pos and end_pos
-        :return: Tuple containing whether or not actual reference sequence matches
-            the expected reference sequence and error message if mismatch
+        :param require_validation: If ``True`` and if validation checks fail, a
+            ``DataProxyValidationError`` will be raised. Error message will always be
+            logged.
+        :raises DataProxyValidationError: If excepted reference sequence does not match
+            the actual reference sequence and ``require_validation`` is ``True``.
         """
         actual_ref = self.get_sequence(sequence_id, start_pos, end_pos)
-        is_valid = actual_ref == ref
-        err_msg = ""
-        if not is_valid:
+
+        if actual_ref != ref:
             err_msg = (
                 f"Expected reference sequence {ref} on {sequence_id} at positions "
                 f"({start_pos}, {end_pos}) but found {actual_ref}"
             )
             _logger.warning(err_msg)
-        return is_valid, err_msg
 
+            if require_validation:
+                raise DataProxyValidationError(err_msg)
 
 class _SeqRepoDataProxyBase(_DataProxy):
     # wraps seqreqpo classes in order to provide translation to/from
diff --git a/src/ga4gh/vrs/extras/translator.py b/src/ga4gh/vrs/extras/translator.py
index 168bc2b..e6e2435 100644
--- a/src/ga4gh/vrs/extras/translator.py
+++ b/src/ga4gh/vrs/extras/translator.py
@@ -19,9 +19,6 @@ from ga4gh.vrs.utils.hgvs_tools import HgvsTools
 
 _logger = logging.getLogger(__name__)
 
-class ValidationError(Exception):
-    """Class for validation errors during translation"""
-
 class _Translator(ABC):
     """abstract class / interface for VRS to/from translation needs
 
@@ -75,9 +72,9 @@ class _Translator(ABC):
                 assembly_name (str): Assembly used for `var`. Defaults to the
                     `default_assembly_name`. Only used for beacon and gnomad.
                 require_validation (bool): If `True` then validation checks must pass in
-                    order to return a VRS object. A `ValidationError` will be raised if
-                    validation checks fail. If `False` then VRS object will be returned
-                    even if validation checks fail. Defaults to `True`.
+                    order to return a VRS object. A `DataProxyValidationError` will be
+                    raised if validation checks fail. If `False` then VRS object will be
+                    returned even if validation checks fail. Defaults to `True`.
                 rle_seq_limit Optional(int): If RLE is set as the new state after
                     normalization, this sets the limit for the length of the `sequence`.
                     To exclude `sequence` from the response, set to 0.
@@ -239,9 +236,9 @@ class AlleleTranslator(_Translator):
         kwargs:
             assembly_name (str): Assembly used for `gnomad_expr`.
             require_validation (bool): If `True` then validation checks must pass in
-                order to return a VRS object. A `ValidationError` will be raised if
-                validation checks fail. If `False` then VRS object will be returned even
-                if validation checks fail. Defaults to `True`.
+                order to return a VRS object. A `DataProxyValidationError` will be
+                raised if validation checks fail. If `False` then VRS object will be
+                returned even if validation checks fail. Defaults to `True`.
             rle_seq_limit Optional(int): If RLE is set as the new state after
                 normalization, this sets the limit for the length of the `sequence`.
                 To exclude `sequence` from the response, set to 0.
@@ -290,12 +287,14 @@ class AlleleTranslator(_Translator):
         end = start + len(ref)
         ins_seq = alt
 
-        # TODO: ask other devs if this should be down on all _from_...  methods?
-        if kwargs.get("require_validation", True):
-            # validation check for matching reference sequence bases
-            valid_ref_seq, err_msg = self.data_proxy.is_valid_ref_seq(sequence, start, end, ref)
-            if not valid_ref_seq:
-                raise ValidationError(err_msg)
+        # validation checks
+        self.data_proxy.validate_ref_seq(
+            sequence,
+            start,
+            end,
+            ref,
+            require_validation=kwargs.get("require_validation", True)
+        )
 
         values = {"refget_accession": refget_accession, "start": start, "end": end, "literal_sequence": ins_seq}
         allele = self._create_allele(values, **kwargs)
diff --git a/src/ga4gh/vrs/extras/vcf_annotation.py b/src/ga4gh/vrs/extras/vcf_annotation.py
index 3b69a69..766e57e 100644
--- a/src/ga4gh/vrs/extras/vcf_annotation.py
+++ b/src/ga4gh/vrs/extras/vcf_annotation.py
@@ -16,8 +16,8 @@ from biocommons.seqrepo import SeqRepo
 from pydantic import ValidationError
 
 from ga4gh.core import VrsObjectIdentifierIs, use_ga4gh_compute_identifier_when
-from ga4gh.vrs.dataproxy import SeqRepoDataProxy, SeqRepoRESTDataProxy
-from ga4gh.vrs.extras.translator import AlleleTranslator, ValidationError as TranslatorValidationError
+from ga4gh.vrs.dataproxy import SeqRepoDataProxy, SeqRepoRESTDataProxy, DataProxyValidationError
+from ga4gh.vrs.extras.translator import AlleleTranslator
 
 
 _logger = logging.getLogger(__name__)
@@ -306,7 +306,7 @@ class VCFAnnotator:  # pylint: disable=too-few-public-methods
                 assembly_name=assembly,
                 require_validation=require_validation
             )
-        except (ValidationError, TranslatorValidationError) as e:
+        except (ValidationError, DataProxyValidationError) as e:
             vrs_obj = None
             _logger.error("ValidationError when translating %s from gnomad: %s", vcf_coords, str(e))
             raise
@@ -377,7 +377,7 @@ class VCFAnnotator:  # pylint: disable=too-few-public-methods
             returned.
         :param compute_for_ref: If true, compute VRS IDs for the reference allele
         :param bool require_validation: If `True` then validation checks must pass in
-            order to return a VRS object. A `ValidationError` will be raised if
+            order to return a VRS object. A `DataProxyValidationError` will be raised if
             validation checks fail. If `False` then VRS object will be returned even if
             validation checks fail. Defaults to `True`.
         """


Test patch:
diff --git a/tests/extras/cassettes/test_from_gnomad.yaml b/tests/extras/cassettes/test_from_gnomad.yaml
index ce239fc..1827e90 100644
--- a/tests/extras/cassettes/test_from_gnomad.yaml
+++ b/tests/extras/cassettes/test_from_gnomad.yaml
@@ -23,7 +23,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -53,7 +53,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -95,7 +95,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -125,7 +125,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -155,7 +155,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -185,7 +185,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -227,7 +227,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -257,7 +257,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -304,7 +304,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -334,7 +334,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -376,7 +376,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -406,7 +406,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -436,7 +436,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -466,7 +466,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -496,7 +496,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -526,7 +526,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -556,7 +556,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -586,7 +586,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -616,7 +616,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -646,7 +646,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -676,7 +676,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -706,7 +706,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -736,7 +736,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -766,7 +766,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -796,7 +796,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -826,7 +826,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -868,7 +868,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -898,7 +898,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -940,7 +940,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -970,7 +970,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1000,7 +1000,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1030,7 +1030,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1060,7 +1060,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1090,7 +1090,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1120,7 +1120,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1150,7 +1150,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1180,7 +1180,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1210,7 +1210,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1240,7 +1240,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1281,7 +1281,37 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:33 GMT
+      Server:
+      - Werkzeug/2.2.2 Python/3.10.4
+    status:
+      code: 200
+      message: OK
+- request:
+    body: null
+    headers:
+      Accept:
+      - '*/*'
+      Accept-Encoding:
+      - gzip, deflate
+      Connection:
+      - keep-alive
+      User-Agent:
+      - python-requests/2.31.0
+    method: GET
+    uri: http://localhost:5000/seqrepo/1/sequence/GRCh38:7?start=1&end=17
+  response:
+    body:
+      string: NNNNNNNNNNNNNNNN
+    headers:
+      Connection:
+      - close
+      Content-Length:
+      - '16'
+      Content-Type:
+      - text/plain; charset=utf-8
+      Date:
+      - Thu, 28 Mar 2024 15:00:33 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1322,7 +1352,7 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:34 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1352,7 +1382,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:34 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1382,7 +1412,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:34 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1412,7 +1442,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:34 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -1442,7 +1472,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:17 GMT
+      - Thu, 28 Mar 2024 15:00:34 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
diff --git a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181220del-expected2].yaml b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181220del-expected2].yaml
index 387d201..06aa6cf 100644
--- a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181220del-expected2].yaml
+++ b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181220del-expected2].yaml
@@ -23,7 +23,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -53,7 +53,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -83,7 +83,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -113,7 +113,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -143,7 +143,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -183,20 +183,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 322C87E474B568E50000500CF156D9CB.1.1.m_5
+      - 322C9662D163BFD50000605DCE15069A.1.1.m_5
       NCBI-SID:
-      - 7DF84EF59B652830_EBC4SID
+      - 487EEE7EF37B53E5_9446SID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=7DF84EF59B652830_EBC4SID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:22 GMT
+      - ncbi_sid=487EEE7EF37B53E5_9446SID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:02 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
@@ -249,20 +249,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:23 GMT
+      - Thu, 28 Mar 2024 15:00:02 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 939B0CF92DC7363500005DD0884C7440.1.1.m_5
+      - 939B7646BC81992500006332510A2C8B.1.1.m_5
       NCBI-SID:
-      - B992B44D3C0793C9_B8F1SID
+      - C0234088172A450C_3F2ESID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=B992B44D3C0793C9_B8F1SID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:22 GMT
+      - ncbi_sid=C0234088172A450C_3F2ESID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:02 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
diff --git a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181230_55181231insGGCT-expected3].yaml b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181230_55181231insGGCT-expected3].yaml
index 47b5d20..03f8e99 100644
--- a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181230_55181231insGGCT-expected3].yaml
+++ b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181230_55181231insGGCT-expected3].yaml
@@ -23,7 +23,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:23 GMT
+      - Thu, 28 Mar 2024 15:00:03 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -53,7 +53,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:23 GMT
+      - Thu, 28 Mar 2024 15:00:03 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -83,7 +83,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:23 GMT
+      - Thu, 28 Mar 2024 15:00:03 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -123,20 +123,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:22 GMT
+      - Thu, 28 Mar 2024 15:00:03 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - D0BDBF1F4546BFE50000380F4240CA38.1.1.m_5
+      - 939B7646BC81992500005A3255164524.1.1.m_5
       NCBI-SID:
-      - 33D174921ADAFB60_2FFCSID
+      - 0E05DFAA948F83FD_FB54SID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=33D174921ADAFB60_2FFCSID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:23 GMT
+      - ncbi_sid=0E05DFAA948F83FD_FB54SID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:03 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
@@ -189,20 +189,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:23 GMT
+      - Thu, 28 Mar 2024 15:00:04 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 322C87E474B568E500004D0CFA4384A0.1.1.m_5
+      - 322C9662D163BFD50000355DD3E92316.1.1.m_5
       NCBI-SID:
-      - 5BF7F69CE7DE3DE9_F2D8SID
+      - 8DA5A9543416CABD_D0FESID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=5BF7F69CE7DE3DE9_F2D8SID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:23 GMT
+      - ncbi_sid=8DA5A9543416CABD_D0FESID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:04 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
@@ -254,20 +254,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:24 GMT
+      - Thu, 28 Mar 2024 15:00:05 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 322C87E474B568E500005F0CFD8FDC9B.1.1.m_5
+      - 939B7646BC819925000040325BF28229.1.1.m_5
       NCBI-SID:
-      - 16C07FA3234426CC_4BC4SID
+      - 46CB48F237EB28EB_248DSID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=16C07FA3234426CC_4BC4SID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:24 GMT
+      - ncbi_sid=46CB48F237EB28EB_248DSID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:05 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
diff --git a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181320A>T-expected1].yaml b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181320A>T-expected1].yaml
index eb9b24e..e6abbe8 100644
--- a/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181320A>T-expected1].yaml
+++ b/tests/extras/cassettes/test_hgvs[NC_000007.14:g.55181320A>T-expected1].yaml
@@ -34,7 +34,48 @@ interactions:
       Content-Type:
       - application/json
       Date:
-      - Tue, 26 Mar 2024 16:28:20 GMT
+      - Thu, 28 Mar 2024 15:00:00 GMT
+      Server:
+      - Werkzeug/2.2.2 Python/3.10.4
+    status:
+      code: 200
+      message: OK
+- request:
+    body: null
+    headers:
+      Accept:
+      - '*/*'
+      Accept-Encoding:
+      - gzip, deflate
+      Connection:
+      - keep-alive
+      User-Agent:
+      - python-requests/2.31.0
+    method: GET
+    uri: http://localhost:5000/seqrepo/1/metadata/ga4gh:SQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul
+  response:
+    body:
+      string: "{\n  \"added\": \"2016-08-27T21:23:35Z\",\n  \"aliases\": [\n    \"GRCh38:7\",\n
+        \   \"GRCh38:chr7\",\n    \"GRCh38.p1:7\",\n    \"GRCh38.p1:chr7\",\n    \"GRCh38.p10:7\",\n
+        \   \"GRCh38.p10:chr7\",\n    \"GRCh38.p11:7\",\n    \"GRCh38.p11:chr7\",\n
+        \   \"GRCh38.p12:7\",\n    \"GRCh38.p12:chr7\",\n    \"GRCh38.p2:7\",\n    \"GRCh38.p2:chr7\",\n
+        \   \"GRCh38.p3:7\",\n    \"GRCh38.p3:chr7\",\n    \"GRCh38.p4:7\",\n    \"GRCh38.p4:chr7\",\n
+        \   \"GRCh38.p5:7\",\n    \"GRCh38.p5:chr7\",\n    \"GRCh38.p6:7\",\n    \"GRCh38.p6:chr7\",\n
+        \   \"GRCh38.p7:7\",\n    \"GRCh38.p7:chr7\",\n    \"GRCh38.p8:7\",\n    \"GRCh38.p8:chr7\",\n
+        \   \"GRCh38.p9:7\",\n    \"GRCh38.p9:chr7\",\n    \"MD5:cc044cc2256a1141212660fb07b6171e\",\n
+        \   \"NCBI:NC_000007.14\",\n    \"refseq:NC_000007.14\",\n    \"SEGUID:4+JjCcBVhPCr8vdIhUKFycPv8bY\",\n
+        \   \"SHA1:e3e26309c05584f0abf2f748854285c9c3eff1b6\",\n    \"VMC:GS_F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul\",\n
+        \   \"sha512t24u:F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul\",\n    \"ga4gh:SQ.F-LrLMe1SRpfUZHkQmvkVKFEGaoDeHul\"\n
+        \ ],\n  \"alphabet\": \"ACGNRSTY\",\n  \"length\": 159345973\n}\n"
+    headers:
+      Connection:
+      - close
+      Content-Length:
+      - '977'
+      Content-Type:
+      - application/json
+      Date:
+      - Thu, 28 Mar 2024 15:00:00 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -64,7 +105,7 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:20 GMT
+      - Thu, 28 Mar 2024 15:00:00 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -104,20 +145,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:21 GMT
+      - Thu, 28 Mar 2024 15:00:01 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 322C87E474B568E500002E0CEAE70D07.1.1.m_5
+      - 939B7646BC81992500003E3244C9BAF7.1.1.m_5
       NCBI-SID:
-      - 7DC076DBAEAC9F26_EA72SID
+      - 386EAB5CACA13AAF_83A0SID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=7DC076DBAEAC9F26_EA72SID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:20 GMT
+      - ncbi_sid=386EAB5CACA13AAF_83A0SID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:01 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
@@ -170,20 +211,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:21 GMT
+      - Thu, 28 Mar 2024 15:00:01 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 939B0CF92DC73635000056D082C3DD0B.1.1.m_5
+      - 322C9662D163BFD50000395DCBFAEF8B.1.1.m_5
       NCBI-SID:
-      - 31494E6B0300111E_3FADSID
+      - 12E58AF58AF52241_BFD4SID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=31494E6B0300111E_3FADSID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:21 GMT
+      - ncbi_sid=12E58AF58AF52241_BFD4SID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:01 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
diff --git a/tests/extras/cassettes/test_hgvs[NC_000013.11:g.32936732=-expected0].yaml b/tests/extras/cassettes/test_hgvs[NC_000013.11:g.32936732=-expected0].yaml
index c62f8b7..5c1213e 100644
--- a/tests/extras/cassettes/test_hgvs[NC_000013.11:g.32936732=-expected0].yaml
+++ b/tests/extras/cassettes/test_hgvs[NC_000013.11:g.32936732=-expected0].yaml
@@ -23,7 +23,37 @@ interactions:
       Content-Type:
       - text/plain; charset=utf-8
       Date:
-      - Tue, 26 Mar 2024 16:28:18 GMT
+      - Thu, 28 Mar 2024 15:00:00 GMT
+      Server:
+      - Werkzeug/2.2.2 Python/3.10.4
+    status:
+      code: 200
+      message: OK
+- request:
+    body: null
+    headers:
+      Accept:
+      - '*/*'
+      Accept-Encoding:
+      - gzip, deflate
+      Connection:
+      - keep-alive
+      User-Agent:
+      - python-requests/2.31.0
+    method: GET
+    uri: http://localhost:5000/seqrepo/1/sequence/ga4gh:SQ._0wi-qoDrvram155UmcSC-zA5ZK4fpLT?start=32936731&end=32936732
+  response:
+    body:
+      string: C
+    headers:
+      Connection:
+      - close
+      Content-Length:
+      - '1'
+      Content-Type:
+      - text/plain; charset=utf-8
+      Date:
+      - Thu, 28 Mar 2024 15:00:00 GMT
       Server:
       - Werkzeug/2.2.2 Python/3.10.4
     status:
@@ -63,20 +93,20 @@ interactions:
       Content-Type:
       - text/plain
       Date:
-      - Tue, 26 Mar 2024 16:28:19 GMT
+      - Thu, 28 Mar 2024 15:00:00 GMT
       Keep-Alive:
       - timeout=4, max=40
       NCBI-PHID:
-      - 322C87E474B568E50000600CE754183C.1.1.m_5
+      - 322C9662D163BFD50000455DC8C5F803.1.1.m_5
       NCBI-SID:
-      - 21AF3205303F2075_8B0BSID
+      - B4EFF4C120F51122_C2F5SID
       Referrer-Policy:
       - origin-when-cross-origin
       Server:
       - Finatra
       Set-Cookie:
-      - ncbi_sid=21AF3205303F2075_8B0BSID; domain=.nih.gov; path=/; expires=Wed, 26
-        Mar 2025 16:28:20 GMT
+      - ncbi_sid=B4EFF4C120F51122_C2F5SID; domain=.nih.gov; path=/; expires=Fri, 28
+        Mar 2025 15:00:00 GMT
       Strict-Transport-Security:
       - max-age=31536000; includeSubDomains; preload
       Transfer-Encoding:
diff --git a/tests/extras/test_allele_translator.py b/tests/extras/test_allele_translator.py
index 637b182..c244976 100644
--- a/tests/extras/test_allele_translator.py
+++ b/tests/extras/test_allele_translator.py
@@ -1,7 +1,8 @@
 import pytest
 
 from ga4gh.vrs import models
-from ga4gh.vrs.extras.translator import AlleleTranslator, ValidationError
+from ga4gh.vrs.dataproxy import DataProxyValidationError
+from ga4gh.vrs.extras.translator import AlleleTranslator
 
 
 @pytest.fixture(scope="module")
@@ -246,11 +247,11 @@ def test_from_gnomad(tlr):
     invalid_var = "13-32936732-G-C"
     error_msg = "Expected reference sequence G on GRCh38:13 at positions (32936731, 32936732) but found C"
 
-    with pytest.raises(ValidationError) as e:
+    with pytest.raises(DataProxyValidationError) as e:
         tlr._from_gnomad(invalid_var)
     assert str(e.value) == error_msg
 
-    with pytest.raises(ValidationError) as e:
+    with pytest.raises(DataProxyValidationError) as e:
         tlr.translate_from(invalid_var, fmt="gnomad")
     assert str(e.value) == error_msg
 
diff --git a/tests/extras/test_vcf_annotation.py b/tests/extras/test_vcf_annotation.py
index 6f5989e..e0242ee 100644
--- a/tests/extras/test_vcf_annotation.py
+++ b/tests/extras/test_vcf_annotation.py
@@ -4,8 +4,8 @@ import os
 import re
 
 import pytest
-from ga4gh.vrs.extras.translator import ValidationError
 
+from ga4gh.vrs.dataproxy import DataProxyValidationError
 from ga4gh.vrs.extras.vcf_annotation import VCFAnnotator, VCFAnnotatorException
 
 TEST_DATA_DIR = "tests/extras/data"
@@ -173,7 +173,7 @@ def test_get_vrs_object_invalid_input(vcf_annotator, caplog):
 
     # Invalid ref, but requiring validation checks so an error is raised
     invalid_ref_seq_msg = "Expected reference sequence C on GRCh38:7 at positions (140753335, 140753336) but found A"
-    with pytest.raises(ValidationError, match=re.escape(invalid_ref_seq_msg)):
+    with pytest.raises(DataProxyValidationError, match=re.escape(invalid_ref_seq_msg)):
         vcf_annotator._get_vrs_object(
             "7-140753336-C-T", {}, [], "GRCh38", require_validation=True
         )