From 01aa46790c91fed751573528d2c1395465834688 Mon Sep 17 00:00:00 2001 From: Jianfeng Mao <4297243+jmao-denver@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:37:28 -0700 Subject: [PATCH] Add Py version check for using eval_str flag of the inspect.signature() (#5083) * Add Py version check for using eval_str flag * Add a clarifying comment * Empty commit to force CI rerun --- py/server/deephaven/_udf.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/py/server/deephaven/_udf.py b/py/server/deephaven/_udf.py index 4eef4bd697b..93073af361f 100644 --- a/py/server/deephaven/_udf.py +++ b/py/server/deephaven/_udf.py @@ -6,6 +6,7 @@ import inspect import re +import sys from dataclasses import dataclass, field from functools import wraps from typing import Callable, List, Any, Union, Tuple, _GenericAlias @@ -104,10 +105,15 @@ def _parse_param_annotation(annotation: Any) -> _ParsedParamAnnotation: return p_annotation -def _parse_type_no_nested(annotation: Any, p_annotation: _ParsedParamAnnotation, t: type) -> None: +def _parse_type_no_nested(annotation: Any, p_annotation: _ParsedParamAnnotation, t: Union[type, str]) -> None: """ Parse a specific type (top level or nested in a top-level Union annotation) without handling nested types (e.g. a nested Union). The result is stored in the given _ParsedAnnotation object. """ + # when from __future__ import annotations is used, the annotation is a string, we need to eval it to get the type + # when the minimum Python version is bumped to 3.10, we'll always use eval_str in _parse_signature, so that + # annotation is already a type, and we can remove this line. + t = eval(t) if isinstance(t, str) else t + p_annotation.orig_types.add(t) tc = _encode_param_type(t) if "[" in tc: @@ -232,7 +238,10 @@ def _parse_signature(fn: Callable) -> _ParsedSignature: return _parse_np_ufunc_signature(fn) else: p_sig = _ParsedSignature(fn=fn) - sig = inspect.signature(fn, eval_str=True) + if sys.version_info.major == 3 and sys.version_info.minor >= 10: + sig = inspect.signature(fn, eval_str=True) + else: + sig = inspect.signature(fn) for n, p in sig.parameters.items(): p_sig.params.append(_parse_param_annotation(p.annotation)) @@ -240,7 +249,7 @@ def _parse_signature(fn: Callable) -> _ParsedSignature: return p_sig -def _is_from_np_type(param_types:set[type], np_type_char: str) -> bool: +def _is_from_np_type(param_types: set[type], np_type_char: str) -> bool: """ Determine if the given numpy type char comes for a numpy type in the given set of parameter type annotations""" for t in param_types: if issubclass(t, np.generic) and np.dtype(t).char == np_type_char: