Last active
February 28, 2019 16:10
-
-
Save feisuzhu/ba058d638edcd1b5bde3ca24569d684d to your computer and use it in GitHub Desktop.
batch list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
T = TypeVar('T') | |
class BatchList(List[T]): | |
__slots__ = () | |
def __getattribute__(self, name): | |
try: | |
list_attr = list.__getattribute__(self, name) | |
return list_attr | |
except AttributeError: | |
pass | |
return BatchList( | |
getattr(i, name) for i in self | |
) | |
def __call__(self, *a, **k): | |
return BatchList( | |
f(*a, **k) for f in self | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# -- stdlib -- | |
from typing import Callable, Optional, cast | |
# -- third party -- | |
from mypy.nodes import MemberExpr | |
from mypy.plugin import AttributeContext, MethodSigContext, Plugin | |
from mypy.types import AnyType, CallableType, Instance, Type, TypeOfAny | |
# -- own -- | |
# -- code -- | |
class BatchListPlugin(Plugin): | |
def get_method_signature_hook(self, fullname: str | |
) -> Optional[Callable[[MethodSigContext], CallableType]]: | |
print('method sig', fullname) | |
if fullname == 'utils.misc.BatchList.__call__': | |
return batchlist_method_signature_hook | |
return None | |
def get_attribute_hook(self, fullname: str | |
) -> Optional[Callable[[AttributeContext], Type]]: | |
if fullname.startswith('utils.misc.BatchList'): | |
return batchlist_attribute_hook | |
return None | |
def batchlist_attribute_hook(ctx: AttributeContext) -> Type: | |
instance = cast(Instance, ctx.type) | |
typeinfo = instance.type | |
expr = cast(MemberExpr, ctx.context) | |
field = expr.name | |
if field in typeinfo.names: | |
t = typeinfo.names[field].type | |
assert t | |
return t | |
names = cast(Instance, instance.args[0]).type.names | |
if field not in names: | |
ctx.api.fail( | |
'BatchList item {} has no attribute "{}"'.format( | |
instance.args[0], field, | |
), expr | |
) | |
return Instance(typeinfo, [AnyType(TypeOfAny.from_error)]) | |
t = names[field].type | |
assert t | |
return Instance(typeinfo, [t]) | |
def batchlist_method_signature_hook(ctx: MethodSigContext) -> CallableType: | |
instance = cast(Instance, ctx.type) | |
typeinfo = instance.type | |
expr = ctx.context | |
c = instance.args[0] | |
if isinstance(c, CallableType): | |
return c.copy_modified( | |
ret_type=Instance(typeinfo, [c.ret_type]) | |
) | |
else: | |
ctx.api.fail("BatchList item {} is not callable".format(instance.args[0]), expr) | |
return ctx.default_signature | |
def plugin(version: str) -> type: | |
return BatchListPlugin |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment