diff --git a/icepyx/core/APIformatting.py b/icepyx/core/APIformatting.py index 6d6c6edc6..a70b66e0a 100644 --- a/icepyx/core/APIformatting.py +++ b/icepyx/core/APIformatting.py @@ -3,6 +3,7 @@ import datetime as dt from typing import Any, Generic, Literal, Optional, TypeVar, Union, overload +from icepyx.core.exceptions import ExhaustiveTypeGuardException, TypeGuardException from icepyx.core.types import ( CMRParams, EGIParamsSubset, @@ -326,7 +327,7 @@ def poss_keys(self) -> dict[str, list[str]]: ], } else: - raise RuntimeError("Programmer error!") + raise ExhaustiveTypeGuardException # @property # def wanted_keys(self): @@ -362,7 +363,7 @@ def check_req_values(self) -> bool: ), "You cannot call this function for your parameter type" if not self._reqtype: - raise RuntimeError("Programmer error!") + raise TypeGuardException reqkeys = self.poss_keys[self._reqtype] @@ -427,7 +428,7 @@ def build_params(self, **kwargs) -> None: if self.partype == "required": if not self._reqtype: - raise RuntimeError("Programmer error!") + raise TypeGuardException if self.check_req_values() and kwargs == {}: pass @@ -496,7 +497,7 @@ def build_params(self, **kwargs) -> None: k = "Boundingshape" if not k: - raise RuntimeError("Programmer error!") + raise TypeGuardException self._fmted_keys.update({k: kwargs["spatial_extent"]}) diff --git a/icepyx/core/exceptions.py b/icepyx/core/exceptions.py index 94bbea768..085fed8c9 100644 --- a/icepyx/core/exceptions.py +++ b/icepyx/core/exceptions.py @@ -1,3 +1,10 @@ +ISSUE_REPORTING_INSTRUCTIONS = ( + "If you are a user seeing this message, the developers of this software have made a" + " mistake! Please report the full error traceback in the icepyx GitHub repository:" + " " +) + + class DeprecationError(Exception): """ Class raised for use of functionality that is no longer supported by icepyx. @@ -24,3 +31,25 @@ def __init__( def __str__(self): return f"{self.msgtxt}: {self.errmsg}" + + +class TypeGuardException(Exception): + """ + Should never be raised at runtime. + + Used in cases where a runtime check is not desired, but we want to add a "type guard" + (https://github.com/microsoft/pyright/blob/main/docs/type-concepts-advanced.md#type-guards) + to give the type checker more information. + """ + + def __str__(self): + return ISSUE_REPORTING_INSTRUCTIONS + + +class ExhaustiveTypeGuardException(TypeGuardException): + """ + Should never be raised at runtime. + + Used exclusively in cases where the typechecker needs a typeguard to tell it that a + check is exhaustive. + """