nbdev
nbdev copied to clipboard
`show_doc` errors on Python 3.10 union sub-type hints
show_doc
errors out when using Python 3.10 union sub-type hints. This occurs with typing.List List[Tensor|int]
or list list[Tensor|int]
Minimal reproducible code and error:
from __future__ import annotations
from nbdev.showdoc import *
def test(l:list[float|int]):
return l
show_doc(test)
Error:
Traceback (most recent call last):
Cell In [3], line 1
show_doc(test)
File ~/python3.9/site-packages/nbdev/showdoc.py:191 in show_doc
else:return renderer(sym or show_doc, name=name, title_level=title_level)
File ~/python3.9/site-packages/nbdev/showdoc.py:127 in __init__
try: self.sig = signature_ex(sym, eval_str=True)
File ~/python3.9/site-packages/fastcore/basics.py:350 in signature_ex
ann = type_hints(obj)
File ~/python3.9/site-packages/fastcore/basics.py:318 in type_hints
return {k:_eval_type(v,glb,loc) for k,v in ann.items()}
File ~/miniconda3/envs/fastai/lib/python3.9/site-packages/fastcore/basics.py:318 in <dictcomp>
return {k:_eval_type(v,glb,loc) for k,v in ann.items()}
File ~/python3.9/site-packages/fastcore/basics.py:311 in _eval_type
res = eval_type(t, glb, loc)
File ~python3.9/site-packages/fastcore/basics.py:304 in eval_type
if '|' in t: return Union[eval_type(tuple(t.split('|')), glb, loc)]
File ~/python3.9/site-packages/fastcore/basics.py:306 in eval_type
if isinstance(t,(tuple,list)): return type(t)([eval_type(c, glb, loc) for c in t])
File ~/python3.9/site-packages/fastcore/basics.py:306 in <listcomp>
if isinstance(t,(tuple,list)): return type(t)([eval_type(c, glb, loc) for c in t])
File ~/python3.9/site-packages/fastcore/basics.py:305 in eval_type
return eval(t, glb, loc)
File <string>:1
list[float
^
SyntaxError: unexpected EOF while parsing
However, using optional list[Optional[float]]
or union Union
list[Union[float, int]]
works.
from typing import Union
from nbdev.showdoc import *
def test(
l:list[Union[float, int]] # test comment
):
return l
show_doc(test)
Using user-defined generic types renders the table, but displays list[T]
as the type, not list[int, float]
(or something similar).
from typing import TypeVar
from nbdev.showdoc import *
T = TypeVar('T', int, float)
def test(
l:list[T] # test comment
):
return l
show_doc(test)
Here's a minimal repro:
from fastcore.basics import eval_type
eval_type('list[float|int]', {}, {})
The issue is that fastcore's backport of py310-style annotations (e.g. float|int
) doesn't support generic types, see this line: https://github.com/fastai/fastcore/blob/86337bad16a65f23c5335286ab73cd4d6425c586/fastcore/basics.py#L304
I wonder if we should be evaluating types for show_doc
at all? If we don't, we would avoid https://github.com/fastai/nbdev/issues/1116 too. cc @jph00
It would be worth trying removing eval and seeing how that changes, for instance, the fastai and nbdev docs