Skip to content

Commit 9050257

Browse files
authored
Implement RaiseError (#68)
1 parent cf4620c commit 9050257

6 files changed

Lines changed: 71 additions & 2 deletions

File tree

pep.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,10 +785,12 @@ All of the operators in this section are :ref:`lifted over union types
785785
Raise error
786786
'''''''''''
787787

788-
* ``RaiseError[S: Literal[str]]``: If this type needs to be evaluated
788+
* ``RaiseError[S: Literal[str], *Ts]``: If this type needs to be evaluated
789789
to determine some actual type, generate a type error with the
790790
provided message.
791791

792+
Any additional type arguments should be included in the message.
793+
792794
Update class
793795
''''''''''''
794796

tests/test_fastapilike_1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class _Default:
7878
7979
type AddInit[T] = NewProtocol[
8080
InitFnType[T],
81-
*Members[T]],
81+
*Members[T],
8282
]
8383
8484
but we struggle here because typing wants to unpack the Members tuple

tests/test_type_eval.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,3 +1645,29 @@ def test_type_eval_annotated_03():
16451645
def test_type_eval_annotated_04():
16461646
res = eval_typing(GetAnnotations[GetMemberType[AnnoTest, Literal["b"]]])
16471647
assert res == Literal["blah"]
1648+
1649+
1650+
##############
1651+
# RaiseError tests
1652+
1653+
from typemap.typing import RaiseError
1654+
from typemap.type_eval import TypeMapError
1655+
1656+
1657+
def test_raise_error_basic():
1658+
with pytest.raises(TypeMapError, match="Test error message"):
1659+
eval_typing(RaiseError[Literal["Test error message"]])
1660+
1661+
1662+
def test_raise_error_with_types():
1663+
with pytest.raises(TypeMapError, match="Broadcast mismatch.*int.*str"):
1664+
eval_typing(RaiseError[Literal["Broadcast mismatch"], int, str])
1665+
1666+
1667+
def test_raise_error_with_literal_types():
1668+
with pytest.raises(
1669+
TypeMapError, match="Shape mismatch.*Literal\\[4\\].*Literal\\[3\\]"
1670+
):
1671+
eval_typing(
1672+
RaiseError[Literal["Shape mismatch"], Literal[4], Literal[3]]
1673+
)

typemap/type_eval/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# This one is imported for registering handlers
1515
from . import _eval_operators # noqa
1616

17+
from ._eval_operators import TypeMapError
18+
1719

1820
__all__ = (
1921
"eval_typing",
@@ -23,6 +25,7 @@
2325
"flatten_class",
2426
"issubtype",
2527
"issubsimilar",
28+
"TypeMapError",
2629
"_EvalProxy",
2730
"_get_current_context",
2831
)

typemap/type_eval/_eval_operators.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
Members,
4040
NewProtocol,
4141
Param,
42+
RaiseError,
4243
Slice,
4344
SpecialFormEllipsis,
4445
StrConcat,
@@ -1020,6 +1021,30 @@ def func(*args, ctx):
10201021
##################################################################
10211022

10221023

1024+
class TypeMapError(TypeError):
1025+
"""Exception raised when RaiseError is evaluated."""
1026+
1027+
pass
1028+
1029+
1030+
@type_eval.register_evaluator(RaiseError)
1031+
@_lift_evaluated
1032+
def _eval_RaiseError(msg, *extra_types, ctx):
1033+
"""Evaluate RaiseError by raising a TypeMapError.
1034+
1035+
RaiseError[S, *Ts] raises a type error with message S,
1036+
including the string representations of any extra type arguments.
1037+
"""
1038+
message = _from_literal(msg)
1039+
if extra_types:
1040+
type_strs = ", ".join(repr(t) for t in extra_types)
1041+
message = f"{message}: {type_strs}"
1042+
raise TypeMapError(message)
1043+
1044+
1045+
##################################################################
1046+
1047+
10231048
def _add_quals(typ, quals):
10241049
for qual in (typing.ClassVar, typing.Final):
10251050
if type_eval.issubsimilar(typing.Literal[qual.__name__], quals):

typemap/typing.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,19 @@ class NewProtocol[*T]:
183183
pass
184184

185185

186+
class RaiseError[S: str, *Ts]:
187+
"""Raise a type error with the given message when evaluated.
188+
189+
RaiseError[S: Literal[str], *Ts]: If this type needs to be evaluated
190+
to determine some actual type, generate a type error with the
191+
provided message.
192+
193+
Any additional type arguments should be included in the message.
194+
"""
195+
196+
pass
197+
198+
186199
##################################################################
187200

188201
# TODO: type better

0 commit comments

Comments
 (0)