fix annotation evaluation error backtrace
This commit is contained in:
parent
f532df7d5f
commit
cea7e8733f
|
@ -1,7 +1,8 @@
|
|||
import os
|
||||
import math
|
||||
import inspect
|
||||
import ast
|
||||
import collections
|
||||
from typing import BinaryIO, Generator, Callable, Union as U, Any, cast
|
||||
from typing import BinaryIO, Generator, Callable, Union as U, Tuple, Mapping, Any, cast
|
||||
from contextlib import contextmanager
|
||||
|
||||
|
||||
|
@ -65,3 +66,24 @@ def format_value(value: Any, formatter: Callable[[Any], str], indentation: int =
|
|||
fmt = '{}'
|
||||
values = [formatter(value)]
|
||||
return indent(fmt.format(*values), indentation)
|
||||
|
||||
|
||||
def get_annot_locations(cls: type) -> Tuple[str, Mapping[str, int]]:
|
||||
""" why """
|
||||
fn = inspect.getsourcefile(cls)
|
||||
slines, start = inspect.getsourcelines(cls)
|
||||
mdef = ast.parse(''.join(slines))
|
||||
|
||||
lines = {}
|
||||
for b in mdef.body[0].body:
|
||||
if isinstance(b, ast.Assign):
|
||||
ts = b.targets
|
||||
elif isinstance(b, (ast.AnnAssign, ast.AugAssign)):
|
||||
ts = [b.target]
|
||||
else:
|
||||
continue
|
||||
for t in ts:
|
||||
if isinstance(t, ast.Name):
|
||||
lines[t.id] = start + b.lineno - 2
|
||||
|
||||
return fn, lines
|
||||
|
|
|
@ -12,7 +12,7 @@ import sx
|
|||
from ..core import to_type
|
||||
from ..core.base import Context, Type, PathElement
|
||||
from ..core.io import Stream, Pos, add_sizes
|
||||
from ..core.util import indent, format_value
|
||||
from ..core.util import indent, format_value, get_annot_locations
|
||||
from ..core.meta import Generic
|
||||
from ..core.expr import IndirectExpr, TypeSource
|
||||
|
||||
|
@ -227,8 +227,16 @@ class Struct:
|
|||
annots = {}
|
||||
localns = {'Self': cls}
|
||||
for c in reversed(cls.__mro__):
|
||||
try:
|
||||
fn, lines = get_annot_locations(c)
|
||||
except:
|
||||
fn = None
|
||||
lines = {}
|
||||
globalns = sys.modules[c.__module__].__dict__
|
||||
annots.update({k: (globalns, v) for k, v in getattr(c, '__annotations__', {}).items()})
|
||||
annots.update({
|
||||
k: (fn or f'<annotation:{k}>', lines.get(k, 0), globalns, v)
|
||||
for k, v in getattr(c, '__annotations__', {}).items()
|
||||
})
|
||||
localns[c.__name__] = c
|
||||
if inject:
|
||||
localns.update({x: getattr(sx, x) for x in sx.__all__})
|
||||
|
@ -238,8 +246,9 @@ class Struct:
|
|||
proxy = StructProxy()
|
||||
localns['self'] = proxy
|
||||
fields = {}
|
||||
for name, (globalns, value) in annots.items():
|
||||
val = eval(value, globalns, localns)
|
||||
for name, (fn, line, globalns, value) in annots.items():
|
||||
code = compile('\n' * line + value, fn, 'eval')
|
||||
val = eval(code, globalns, localns)
|
||||
if isinstance(val, Annotated):
|
||||
val = next(v for v in val.__metadata__ if isinstance(v, Type))
|
||||
fields[name] = val
|
||||
|
|
Loading…
Reference in New Issue