Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/helpers.py: 20%

119 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-04-20 06:09 +0000

1import copy 

2import sys 

3import re 

4import os 

5from itertools import chain 

6from contextlib import contextmanager 

7 

8from parso.python import tree 

9 

10 

11def is_stdlib_path(path): 

12 # Python standard library paths look like this: 

13 # /usr/lib/python3.9/... 

14 # TODO The implementation below is probably incorrect and not complete. 

15 parts = path.parts 

16 if 'dist-packages' in parts or 'site-packages' in parts: 

17 return False 

18 

19 base_path = os.path.join(sys.prefix, 'lib', 'python') 

20 return bool(re.match(re.escape(base_path) + r'\d.\d', str(path))) 

21 

22 

23def deep_ast_copy(obj): 

24 """ 

25 Much, much faster than copy.deepcopy, but just for parser tree nodes. 

26 """ 

27 # If it's already in the cache, just return it. 

28 new_obj = copy.copy(obj) 

29 

30 # Copy children 

31 new_children = [] 

32 for child in obj.children: 

33 if isinstance(child, tree.Leaf): 

34 new_child = copy.copy(child) 

35 new_child.parent = new_obj 

36 else: 

37 new_child = deep_ast_copy(child) 

38 new_child.parent = new_obj 

39 new_children.append(new_child) 

40 new_obj.children = new_children 

41 

42 return new_obj 

43 

44 

45def infer_call_of_leaf(context, leaf, cut_own_trailer=False): 

46 """ 

47 Creates a "call" node that consist of all ``trailer`` and ``power`` 

48 objects. E.g. if you call it with ``append``:: 

49 

50 list([]).append(3) or None 

51 

52 You would get a node with the content ``list([]).append`` back. 

53 

54 This generates a copy of the original ast node. 

55 

56 If you're using the leaf, e.g. the bracket `)` it will return ``list([])``. 

57 

58 We use this function for two purposes. Given an expression ``bar.foo``, 

59 we may want to 

60 - infer the type of ``foo`` to offer completions after foo 

61 - infer the type of ``bar`` to be able to jump to the definition of foo 

62 The option ``cut_own_trailer`` must be set to true for the second purpose. 

63 """ 

64 trailer = leaf.parent 

65 if trailer.type == 'fstring': 

66 from jedi.inference import compiled 

67 return compiled.get_string_value_set(context.inference_state) 

68 

69 # The leaf may not be the last or first child, because there exist three 

70 # different trailers: `( x )`, `[ x ]` and `.x`. In the first two examples 

71 # we should not match anything more than x. 

72 if trailer.type != 'trailer' or leaf not in (trailer.children[0], trailer.children[-1]): 

73 if leaf == ':': 

74 # Basically happens with foo[:] when the cursor is on the colon 

75 from jedi.inference.base_value import NO_VALUES 

76 return NO_VALUES 

77 if trailer.type == 'atom': 

78 return context.infer_node(trailer) 

79 return context.infer_node(leaf) 

80 

81 power = trailer.parent 

82 index = power.children.index(trailer) 

83 if cut_own_trailer: 

84 cut = index 

85 else: 

86 cut = index + 1 

87 

88 if power.type == 'error_node': 

89 start = index 

90 while True: 

91 start -= 1 

92 base = power.children[start] 

93 if base.type != 'trailer': 

94 break 

95 trailers = power.children[start + 1:cut] 

96 else: 

97 base = power.children[0] 

98 trailers = power.children[1:cut] 

99 

100 if base == 'await': 

101 base = trailers[0] 

102 trailers = trailers[1:] 

103 

104 values = context.infer_node(base) 

105 from jedi.inference.syntax_tree import infer_trailer 

106 for trailer in trailers: 

107 values = infer_trailer(context, values, trailer) 

108 return values 

109 

110 

111def get_names_of_node(node): 

112 try: 

113 children = node.children 

114 except AttributeError: 

115 if node.type == 'name': 

116 return [node] 

117 else: 

118 return [] 

119 else: 

120 return list(chain.from_iterable(get_names_of_node(c) for c in children)) 

121 

122 

123def is_string(value): 

124 return value.is_compiled() and isinstance(value.get_safe_value(default=None), str) 

125 

126 

127def is_literal(value): 

128 return is_number(value) or is_string(value) 

129 

130 

131def _get_safe_value_or_none(value, accept): 

132 value = value.get_safe_value(default=None) 

133 if isinstance(value, accept): 

134 return value 

135 

136 

137def get_int_or_none(value): 

138 return _get_safe_value_or_none(value, int) 

139 

140 

141def get_str_or_none(value): 

142 return _get_safe_value_or_none(value, str) 

143 

144 

145def is_number(value): 

146 return _get_safe_value_or_none(value, (int, float)) is not None 

147 

148 

149class SimpleGetItemNotFound(Exception): 

150 pass 

151 

152 

153@contextmanager 

154def reraise_getitem_errors(*exception_classes): 

155 try: 

156 yield 

157 except exception_classes as e: 

158 raise SimpleGetItemNotFound(e) 

159 

160 

161def parse_dotted_names(nodes, is_import_from, until_node=None): 

162 level = 0 

163 names = [] 

164 for node in nodes[1:]: 

165 if node in ('.', '...'): 

166 if not names: 

167 level += len(node.value) 

168 elif node.type == 'dotted_name': 

169 for n in node.children[::2]: 

170 names.append(n) 

171 if n is until_node: 

172 break 

173 else: 

174 continue 

175 break 

176 elif node.type == 'name': 

177 names.append(node) 

178 if node is until_node: 

179 break 

180 elif node == ',': 

181 if not is_import_from: 

182 names = [] 

183 else: 

184 # Here if the keyword `import` comes along it stops checking 

185 # for names. 

186 break 

187 return level, names 

188 

189 

190def values_from_qualified_names(inference_state, *names): 

191 return inference_state.import_module(names[:-1]).py__getattribute__(names[-1]) 

192 

193 

194def is_big_annoying_library(context): 

195 string_names = context.get_root_context().string_names 

196 if string_names is None: 

197 return False 

198 

199 # Especially pandas and tensorflow are huge complicated Python libraries 

200 # that get even slower than they already are when Jedi tries to undrstand 

201 # dynamic features like decorators, ifs and other stuff. 

202 return string_names[0] in ('pandas', 'numpy', 'tensorflow', 'matplotlib')