Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jedi/inference/gradual/conversion.py: 12%

139 statements  

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

1from jedi import debug 

2from jedi.inference.base_value import ValueSet, \ 

3 NO_VALUES 

4from jedi.inference.utils import to_list 

5from jedi.inference.gradual.stub_value import StubModuleValue 

6from jedi.inference.gradual.typeshed import try_to_load_stub_cached 

7from jedi.inference.value.decorator import Decoratee 

8 

9 

10def _stub_to_python_value_set(stub_value, ignore_compiled=False): 

11 stub_module_context = stub_value.get_root_context() 

12 if not stub_module_context.is_stub(): 

13 return ValueSet([stub_value]) 

14 

15 decorates = None 

16 if isinstance(stub_value, Decoratee): 

17 decorates = stub_value._original_value 

18 

19 was_instance = stub_value.is_instance() 

20 if was_instance: 

21 arguments = getattr(stub_value, '_arguments', None) 

22 stub_value = stub_value.py__class__() 

23 

24 qualified_names = stub_value.get_qualified_names() 

25 if qualified_names is None: 

26 return NO_VALUES 

27 

28 was_bound_method = stub_value.is_bound_method() 

29 if was_bound_method: 

30 # Infer the object first. We can infer the method later. 

31 method_name = qualified_names[-1] 

32 qualified_names = qualified_names[:-1] 

33 was_instance = True 

34 arguments = None 

35 

36 values = _infer_from_stub(stub_module_context, qualified_names, ignore_compiled) 

37 if was_instance: 

38 values = ValueSet.from_sets( 

39 c.execute_with_values() if arguments is None else c.execute(arguments) 

40 for c in values 

41 if c.is_class() 

42 ) 

43 if was_bound_method: 

44 # Now that the instance has been properly created, we can simply get 

45 # the method. 

46 values = values.py__getattribute__(method_name) 

47 if decorates is not None: 

48 values = ValueSet(Decoratee(v, decorates) for v in values) 

49 return values 

50 

51 

52def _infer_from_stub(stub_module_context, qualified_names, ignore_compiled): 

53 from jedi.inference.compiled.mixed import MixedObject 

54 stub_module = stub_module_context.get_value() 

55 assert isinstance(stub_module, (StubModuleValue, MixedObject)), stub_module_context 

56 non_stubs = stub_module.non_stub_value_set 

57 if ignore_compiled: 

58 non_stubs = non_stubs.filter(lambda c: not c.is_compiled()) 

59 for name in qualified_names: 

60 non_stubs = non_stubs.py__getattribute__(name) 

61 return non_stubs 

62 

63 

64@to_list 

65def _try_stub_to_python_names(names, prefer_stub_to_compiled=False): 

66 for name in names: 

67 module_context = name.get_root_context() 

68 if not module_context.is_stub(): 

69 yield name 

70 continue 

71 

72 if name.api_type == 'module': 

73 values = convert_values(name.infer(), ignore_compiled=prefer_stub_to_compiled) 

74 if values: 

75 for v in values: 

76 yield v.name 

77 continue 

78 else: 

79 v = name.get_defining_qualified_value() 

80 if v is not None: 

81 converted = _stub_to_python_value_set(v, ignore_compiled=prefer_stub_to_compiled) 

82 if converted: 

83 converted_names = converted.goto(name.get_public_name()) 

84 if converted_names: 

85 for n in converted_names: 

86 if n.get_root_context().is_stub(): 

87 # If it's a stub again, it means we're going in 

88 # a circle. Probably some imports make it a 

89 # stub again. 

90 yield name 

91 else: 

92 yield n 

93 continue 

94 yield name 

95 

96 

97def _load_stub_module(module): 

98 if module.is_stub(): 

99 return module 

100 return try_to_load_stub_cached( 

101 module.inference_state, 

102 import_names=module.string_names, 

103 python_value_set=ValueSet([module]), 

104 parent_module_value=None, 

105 sys_path=module.inference_state.get_sys_path(), 

106 ) 

107 

108 

109@to_list 

110def _python_to_stub_names(names, fallback_to_python=False): 

111 for name in names: 

112 module_context = name.get_root_context() 

113 if module_context.is_stub(): 

114 yield name 

115 continue 

116 

117 if name.api_type == 'module': 

118 found_name = False 

119 for n in name.goto(): 

120 if n.api_type == 'module': 

121 values = convert_values(n.infer(), only_stubs=True) 

122 for v in values: 

123 yield v.name 

124 found_name = True 

125 else: 

126 for x in _python_to_stub_names([n], fallback_to_python=fallback_to_python): 

127 yield x 

128 found_name = True 

129 if found_name: 

130 continue 

131 else: 

132 v = name.get_defining_qualified_value() 

133 if v is not None: 

134 converted = to_stub(v) 

135 if converted: 

136 converted_names = converted.goto(name.get_public_name()) 

137 if converted_names: 

138 yield from converted_names 

139 continue 

140 if fallback_to_python: 

141 # This is the part where if we haven't found anything, just return 

142 # the stub name. 

143 yield name 

144 

145 

146def convert_names(names, only_stubs=False, prefer_stubs=False, prefer_stub_to_compiled=True): 

147 if only_stubs and prefer_stubs: 

148 raise ValueError("You cannot use both of only_stubs and prefer_stubs.") 

149 

150 with debug.increase_indent_cm('convert names'): 

151 if only_stubs or prefer_stubs: 

152 return _python_to_stub_names(names, fallback_to_python=prefer_stubs) 

153 else: 

154 return _try_stub_to_python_names( 

155 names, prefer_stub_to_compiled=prefer_stub_to_compiled) 

156 

157 

158def convert_values(values, only_stubs=False, prefer_stubs=False, ignore_compiled=True): 

159 assert not (only_stubs and prefer_stubs) 

160 with debug.increase_indent_cm('convert values'): 

161 if only_stubs or prefer_stubs: 

162 return ValueSet.from_sets( 

163 to_stub(value) 

164 or (ValueSet({value}) if prefer_stubs else NO_VALUES) 

165 for value in values 

166 ) 

167 else: 

168 return ValueSet.from_sets( 

169 _stub_to_python_value_set(stub_value, ignore_compiled=ignore_compiled) 

170 or ValueSet({stub_value}) 

171 for stub_value in values 

172 ) 

173 

174 

175def to_stub(value): 

176 if value.is_stub(): 

177 return ValueSet([value]) 

178 

179 was_instance = value.is_instance() 

180 if was_instance: 

181 value = value.py__class__() 

182 

183 qualified_names = value.get_qualified_names() 

184 stub_module = _load_stub_module(value.get_root_context().get_value()) 

185 if stub_module is None or qualified_names is None: 

186 return NO_VALUES 

187 

188 was_bound_method = value.is_bound_method() 

189 if was_bound_method: 

190 # Infer the object first. We can infer the method later. 

191 method_name = qualified_names[-1] 

192 qualified_names = qualified_names[:-1] 

193 was_instance = True 

194 

195 stub_values = ValueSet([stub_module]) 

196 for name in qualified_names: 

197 stub_values = stub_values.py__getattribute__(name) 

198 

199 if was_instance: 

200 stub_values = ValueSet.from_sets( 

201 c.execute_with_values() 

202 for c in stub_values 

203 if c.is_class() 

204 ) 

205 if was_bound_method: 

206 # Now that the instance has been properly created, we can simply get 

207 # the method. 

208 stub_values = stub_values.py__getattribute__(method_name) 

209 return stub_values