]>
Commit | Line | Data |
---|---|---|
53e6db90 DC |
1 | """ |
2 | This module is about generics, like the `int` in `List[int]`. It's not about | |
3 | the Generic class. | |
4 | """ | |
5 | ||
6 | from jedi import debug | |
7 | from jedi.cache import memoize_method | |
8 | from jedi.inference.utils import to_tuple | |
9 | from jedi.inference.base_value import ValueSet, NO_VALUES | |
10 | from jedi.inference.value.iterable import SequenceLiteralValue | |
11 | from jedi.inference.helpers import is_string | |
12 | ||
13 | ||
14 | def _resolve_forward_references(context, value_set): | |
15 | for value in value_set: | |
16 | if is_string(value): | |
17 | from jedi.inference.gradual.annotation import _get_forward_reference_node | |
18 | node = _get_forward_reference_node(context, value.get_safe_value()) | |
19 | if node is not None: | |
20 | for c in context.infer_node(node): | |
21 | yield c | |
22 | else: | |
23 | yield value | |
24 | ||
25 | ||
26 | class _AbstractGenericManager: | |
27 | def get_index_and_execute(self, index): | |
28 | try: | |
29 | return self[index].execute_annotation() | |
30 | except IndexError: | |
31 | debug.warning('No param #%s found for annotation %s', index, self) | |
32 | return NO_VALUES | |
33 | ||
34 | def get_type_hint(self): | |
35 | return '[%s]' % ', '.join(t.get_type_hint(add_class_info=False) for t in self.to_tuple()) | |
36 | ||
37 | ||
38 | class LazyGenericManager(_AbstractGenericManager): | |
39 | def __init__(self, context_of_index, index_value): | |
40 | self._context_of_index = context_of_index | |
41 | self._index_value = index_value | |
42 | ||
43 | @memoize_method | |
44 | def __getitem__(self, index): | |
45 | return self._tuple()[index]() | |
46 | ||
47 | def __len__(self): | |
48 | return len(self._tuple()) | |
49 | ||
50 | @memoize_method | |
51 | @to_tuple | |
52 | def _tuple(self): | |
53 | def lambda_scoping_in_for_loop_sucks(lazy_value): | |
54 | return lambda: ValueSet(_resolve_forward_references( | |
55 | self._context_of_index, | |
56 | lazy_value.infer() | |
57 | )) | |
58 | ||
59 | if isinstance(self._index_value, SequenceLiteralValue): | |
60 | for lazy_value in self._index_value.py__iter__(contextualized_node=None): | |
61 | yield lambda_scoping_in_for_loop_sucks(lazy_value) | |
62 | else: | |
63 | yield lambda: ValueSet(_resolve_forward_references( | |
64 | self._context_of_index, | |
65 | ValueSet([self._index_value]) | |
66 | )) | |
67 | ||
68 | @to_tuple | |
69 | def to_tuple(self): | |
70 | for callable_ in self._tuple(): | |
71 | yield callable_() | |
72 | ||
73 | def is_homogenous_tuple(self): | |
74 | if isinstance(self._index_value, SequenceLiteralValue): | |
75 | entries = self._index_value.get_tree_entries() | |
76 | if len(entries) == 2 and entries[1] == '...': | |
77 | return True | |
78 | return False | |
79 | ||
80 | def __repr__(self): | |
81 | return '<LazyG>[%s]' % (', '.join(repr(x) for x in self.to_tuple())) | |
82 | ||
83 | ||
84 | class TupleGenericManager(_AbstractGenericManager): | |
85 | def __init__(self, tup): | |
86 | self._tuple = tup | |
87 | ||
88 | def __getitem__(self, index): | |
89 | return self._tuple[index] | |
90 | ||
91 | def __len__(self): | |
92 | return len(self._tuple) | |
93 | ||
94 | def to_tuple(self): | |
95 | return self._tuple | |
96 | ||
97 | def is_homogenous_tuple(self): | |
98 | return False | |
99 | ||
100 | def __repr__(self): | |
101 | return '<TupG>[%s]' % (', '.join(repr(x) for x in self.to_tuple())) |