-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Copy pathcollections.py
121 lines (97 loc) · 3.93 KB
/
collections.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from .. import types, utils, errors
import operator
from .templates import (AttributeTemplate, ConcreteTemplate, AbstractTemplate,
infer_global, infer, infer_getattr,
signature, bound_function, make_callable_template)
from .builtins import normalize_1d_index
@infer_global(operator.contains)
class InContainer(AbstractTemplate):
key = operator.contains
def generic(self, args, kws):
cont, item = args
if isinstance(cont, types.Container):
return signature(types.boolean, cont, cont.dtype)
@infer_global(len)
class ContainerLen(AbstractTemplate):
def generic(self, args, kws):
assert not kws
(val,) = args
if isinstance(val, (types.Container)):
return signature(types.intp, val)
@infer_global(operator.truth)
class SequenceBool(AbstractTemplate):
key = operator.truth
def generic(self, args, kws):
assert not kws
(val,) = args
if isinstance(val, (types.Sequence)):
return signature(types.boolean, val)
@infer_global(operator.getitem)
class GetItemSequence(AbstractTemplate):
key = operator.getitem
def generic(self, args, kws):
seq, idx = args
if isinstance(seq, types.Sequence):
idx = normalize_1d_index(idx)
if isinstance(idx, types.SliceType):
# Slicing a tuple only supported with static_getitem
if not isinstance(seq, types.BaseTuple):
return signature(seq, seq, idx)
elif isinstance(idx, types.Integer):
return signature(seq.dtype, seq, idx)
@infer_global(operator.setitem)
class SetItemSequence(AbstractTemplate):
def generic(self, args, kws):
seq, idx, value = args
if isinstance(seq, types.MutableSequence):
idx = normalize_1d_index(idx)
if isinstance(idx, types.SliceType):
return signature(types.none, seq, idx, seq)
elif isinstance(idx, types.Integer):
if not self.context.can_convert(value, seq.dtype):
msg = "invalid setitem with value of {} to element of {}"
raise errors.TypingError(msg.format(types.unliteral(value), seq.dtype))
return signature(types.none, seq, idx, seq.dtype)
@infer_global(operator.delitem)
class DelItemSequence(AbstractTemplate):
def generic(self, args, kws):
seq, idx = args
if isinstance(seq, types.MutableSequence):
idx = normalize_1d_index(idx)
return signature(types.none, seq, idx)
# --------------------------------------------------------------------------
# named tuples
@infer_getattr
class NamedTupleAttribute(AttributeTemplate):
key = types.BaseNamedTuple
def resolve___class__(self, tup):
return types.NamedTupleClass(tup.instance_class)
def generic_resolve(self, tup, attr):
# Resolution of other attributes
try:
index = tup.fields.index(attr)
except ValueError:
return
return tup[index]
@infer_getattr
class NamedTupleClassAttribute(AttributeTemplate):
key = types.NamedTupleClass
def resolve___call__(self, classty):
"""
Resolve the named tuple constructor, aka the class's __call__ method.
"""
instance_class = classty.instance_class
pysig = utils.pysignature(instance_class)
def typer(*args, **kws):
# Fold keyword args
try:
bound = pysig.bind(*args, **kws)
except TypeError as e:
msg = "In '%s': %s" % (instance_class, e)
e.args = (msg,)
raise
assert not bound.kwargs
return types.BaseTuple.from_types(bound.args, instance_class)
# Override the typer's pysig to match the namedtuple constructor's
typer.pysig = pysig
return types.Function(make_callable_template(self.key, typer))