Skip to content

Commit cc4449a

Browse files
committed
🐛 Fix evaluating stringified annotations in Python 3.9 and less (also from __future__ import annotations)
1 parent 3b17788 commit cc4449a

File tree

4 files changed

+32
-12
lines changed

4 files changed

+32
-12
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ classifiers = [
3535
]
3636
dependencies = [
3737
"click >= 8.0.0",
38-
"typing-extensions >= 3.7.4.3",
38+
"typing-extensions >= 4.13.0",
3939
]
4040
readme = "README.md"
4141
[project.urls]

tests/test_annotated.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from typer.testing import CliRunner
33
from typing_extensions import Annotated
44

5-
from .utils import needs_py310
6-
75
runner = CliRunner()
86

97

@@ -23,7 +21,6 @@ def cmd(val: Annotated[int, typer.Argument()] = 0):
2321
assert "hello 42" in result.output
2422

2523

26-
@needs_py310
2724
def test_annotated_argument_in_string_type_with_default():
2825
app = typer.Typer()
2926

typer/_inspect.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import inspect
2+
import sys
3+
4+
if sys.version_info >= (3, 10):
5+
from inspect import signature
6+
else:
7+
from typing import Any
8+
9+
from typing_extensions import get_annotations
10+
11+
def signature(func, eval_str=False, **kwargs: Any):
12+
sig = inspect.signature(func, **kwargs)
13+
ann = get_annotations(
14+
func,
15+
globals=kwargs.get("globals"),
16+
locals=kwargs.get("locals"),
17+
eval_str=eval_str,
18+
)
19+
return sig.replace(
20+
parameters=[
21+
param.replace(annotation=ann.get(name, param.annotation))
22+
for name, param in sig.parameters.items()
23+
],
24+
return_annotation=ann.get("return", sig.return_annotation),
25+
)
26+
27+
28+
__all__ = ["signature"]

typer/utils.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import inspect
2-
import sys
31
from copy import copy
42
from typing import Any, Callable, Dict, List, Tuple, Type, cast
53

4+
from ._inspect import signature as inspect_signature
65
from ._typing import Annotated, get_args, get_origin, get_type_hints
76
from .models import ArgumentInfo, OptionInfo, ParameterInfo, ParamMeta
87

@@ -105,12 +104,8 @@ def _split_annotation_from_typer_annotations(
105104

106105

107106
def get_params_from_function(func: Callable[..., Any]) -> Dict[str, ParamMeta]:
108-
if sys.version_info >= (3, 10):
109-
signature = inspect.signature(func, eval_str=True)
110-
else:
111-
signature = inspect.signature(func)
112-
113-
type_hints = get_type_hints(func)
107+
signature = inspect_signature(func, eval_str=True)
108+
type_hints = get_type_hints(func, include_extras=True)
114109
params = {}
115110
for param in signature.parameters.values():
116111
annotation, typer_annotations = _split_annotation_from_typer_annotations(

0 commit comments

Comments
 (0)