|
23 | 23 |
|
24 | 24 | __all__ = ['base'] |
25 | 25 |
|
26 | | -from moretools import cached |
| 26 | +from inspect import getfullargspec, isclass |
| 27 | + |
| 28 | +from decorator import decorator |
| 29 | +from moretools import cached, qualname |
27 | 30 |
|
28 | 31 | from .base import base |
29 | 32 |
|
@@ -77,5 +80,27 @@ def new(self, value, func): |
77 | 80 | return value |
78 | 81 | raise TypeError( |
79 | 82 | "%s.new.func() must return an instance of '%s', not '%s'" |
80 | | - % (type(self).__name__, self.mtype.__name__, |
81 | | - type(value).__name__)) |
| 83 | + % (qualname(type(self)), qualname(self.mtype), |
| 84 | + qualname(type(value)))) |
| 85 | + |
| 86 | + |
| 87 | +def typed(func): |
| 88 | + spec = getfullargspec(func) |
| 89 | + |
| 90 | + def typed(func, *args, **kwargs): |
| 91 | + iargs = iter(args) |
| 92 | + args = [] |
| 93 | + for name, value in zip(spec.args, iargs): |
| 94 | + mtype = wrapper.mtypes.get(name) |
| 95 | + if isclass(mtype) and not isinstance(value, mtype): |
| 96 | + value = mtype(value) |
| 97 | + args.append(value) |
| 98 | + result = func(*args, **kwargs) |
| 99 | + mtype = wrapper.mtypes.get('return') |
| 100 | + if isclass(mtype) and not isinstance(result, mtype): |
| 101 | + result = mtype(result) |
| 102 | + return result |
| 103 | + |
| 104 | + wrapper = decorator(typed, func) |
| 105 | + wrapper.mtypes = spec.annotations |
| 106 | + return wrapper |
0 commit comments