From 6d0122dabcda83772f0d3108b6fdc34e4e303c31 Mon Sep 17 00:00:00 2001 From: "Michael J. Sullivan" Date: Thu, 9 Oct 2025 11:29:20 -0700 Subject: [PATCH] Give a better name for the protocol in eval_call --- tests/test_call.py | 3 +-- typemap/type_eval/_eval_call.py | 21 ++++++++++++++++----- typemap/type_eval/_eval_typing.py | 4 +++- typemap/typing.py | 5 ++++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/tests/test_call.py b/tests/test_call.py index a0e92e0..ae4abc7 100644 --- a/tests/test_call.py +++ b/tests/test_call.py @@ -17,9 +17,8 @@ def test_call_1(): ret = eval_call(func, a=1, b=2, c="aaa") fmt = format_helper.format_class(ret) - # XXX: We want better than this for a name assert fmt == textwrap.dedent("""\ - class NewProtocol: + class func[...]: a: int b: int c: int diff --git a/typemap/type_eval/_eval_call.py b/typemap/type_eval/_eval_call.py index 027102f..415fa26 100644 --- a/typemap/type_eval/_eval_call.py +++ b/typemap/type_eval/_eval_call.py @@ -11,11 +11,17 @@ def eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any: - with _eval_typing._ensure_context(): - return _eval_call(func, *args, **kwargs) + with _eval_typing._ensure_context() as ctx: + return _eval_call(func, ctx, *args, **kwargs) -def _eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any: +def _eval_call( + func: types.FunctionType, + ctx: _eval_typing.EvalContext, + /, + *args: Any, + **kwargs: Any, +) -> Any: vars: dict[str, Any] = {} params = func.__type_params__ @@ -39,6 +45,11 @@ def _eval_call(func: types.FunctionType, /, *args: Any, **kwargs: Any) -> Any: ff = types.FunctionType( af.__code__, af.__globals__, af.__name__, None, af_args ) - rr = ff(annotationlib.Format.VALUE) - return _eval_typing.eval_typing(rr["return"]) + old_obj = ctx.current_alias + ctx.current_alias = func + try: + rr = ff(annotationlib.Format.VALUE) + return _eval_typing.eval_typing(rr["return"]) + finally: + ctx.current_alias = old_obj diff --git a/typemap/type_eval/_eval_typing.py b/typemap/type_eval/_eval_typing.py index 24319c8..29f1f37 100644 --- a/typemap/type_eval/_eval_typing.py +++ b/typemap/type_eval/_eval_typing.py @@ -22,7 +22,9 @@ @dataclasses.dataclass class EvalContext: seen: dict[Any, Any] - current_alias: types.GenericAlias | None = None + # The typing.Any is really a types.FunctionType, but mypy gets + # confused and wants to treat it as a MethodType. + current_alias: types.GenericAlias | typing.Any | None = None # `eval_types()` calls can be nested, context must be preserved diff --git a/typemap/typing.py b/typemap/typing.py index 9146038..7de8c92 100644 --- a/typemap/typing.py +++ b/typemap/typing.py @@ -95,7 +95,10 @@ def __getitem__(cls, val: list[Property]): # If the type evaluation context ctx = type_eval._get_current_context() if ctx.current_alias: - name = str(ctx.current_alias) + if isinstance(ctx.current_alias, types.GenericAlias): + name = str(ctx.current_alias) + else: + name = f"{ctx.current_alias.__name__}[...]" module_name = ctx.current_alias.__module__ dct["__module__"] = module_name