def py__getitem__(context, typ, node): if not typ.get_root_context().name.string_name == "typing": return None # we assume that any class using [] in a module called # "typing" with a name for which we have a replacement # should be replaced by that class. This is not 100% # airtight but I don't have a better idea to check that it's # actually the PEP-0484 typing module and not some other if node.type == "subscriptlist": nodes = node.children[::2] # skip the commas else: nodes = [node] del node nodes = [_fix_forward_reference(context, node) for node in nodes] type_name = typ.name.string_name # hacked in Union and Optional, since it's hard to do nicely in parsed code if type_name in ("Union", '_Union'): # In Python 3.6 it's still called typing.Union but it's an instance # called _Union. return unite(context.eval_node(node) for node in nodes) if type_name in ("Optional", '_Optional'): # Here we have the same issue like in Union. Therefore we also need to # check for the instance typing._Optional (Python 3.6). return context.eval_node(nodes[0]) from jedi.evaluate.representation import ModuleContext typing = ModuleContext( context.evaluator, module_node=_get_typing_replacement_module(), path=None ) factories = typing.py__getattribute__("factory") assert len(factories) == 1 factory = list(factories)[0] assert factory function_body_nodes = factory.tree_node.children[4].children valid_classnames = set(child.name.value for child in function_body_nodes if isinstance(child, tree.Class)) if type_name not in valid_classnames: return None compiled_classname = compiled.create(context.evaluator, type_name) from jedi.evaluate.iterable import FakeSequence args = FakeSequence( context.evaluator, "tuple", [LazyTreeContext(context, n) for n in nodes] ) result = factory.execute_evaluated(compiled_classname, args) return result
def _execute_array_values(evaluator, array): """ Tuples indicate that there's not just one return value, but the listed ones. `(str, int)` means that it returns a tuple with both types. """ if isinstance(array, Array): values = [] for typ in array.values(): objects = _execute_array_values(evaluator, typ) values.append(AlreadyEvaluated(objects)) return [FakeSequence(evaluator, values, array.type)] else: return evaluator.execute(array)
def _execute_array_values(evaluator, array): """ Tuples indicate that there's not just one return value, but the listed ones. `(str, int)` means that it returns a tuple with both types. """ if isinstance(array, SequenceLiteralContext): values = [] for lazy_context in array.py__iter__(): objects = unite(_execute_array_values(evaluator, typ) for typ in lazy_context.infer()) values.append(context.LazyKnownContexts(objects)) return set([FakeSequence(evaluator, array.array_type, values)]) else: return array.execute_evaluated()
def get_types_for_typing_module(evaluator, typ, node): from jedi.evaluate.iterable import FakeSequence if not typ.base.get_parent_until().name.value == "typing": return None # we assume that any class using [] in a module called # "typing" with a name for which we have a replacement # should be replaced by that class. This is not 100% # airtight but I don't have a better idea to check that it's # actually the PEP-0484 typing module and not some other if tree.is_node(node, "subscriptlist"): nodes = node.children[::2] # skip the commas else: nodes = [node] del node nodes = [_fix_forward_reference(evaluator, node) for node in nodes] # hacked in Union and Optional, since it's hard to do nicely in parsed code if typ.name.value == "Union": return unite(evaluator.eval_element(node) for node in nodes) if typ.name.value == "Optional": return evaluator.eval_element(nodes[0]) typing = _get_typing_replacement_module() factories = evaluator.find_types(typing, "factory") assert len(factories) == 1 factory = list(factories)[0] assert factory function_body_nodes = factory.children[4].children valid_classnames = set(child.name.value for child in function_body_nodes if isinstance(child, tree.Class)) if typ.name.value not in valid_classnames: return None compiled_classname = compiled.create(evaluator, typ.name.value) args = FakeSequence(evaluator, nodes, "tuple") result = evaluator.execute_evaluated(factory, compiled_classname, args) return result