def _apply_decorators(context, node): """ Returns the function, that should to be executed in the end. This is also the places where the decorators are processed. """ if node.type == 'classdef': decoratee_value = ClassValue( context.inference_state, parent_context=context, tree_node=node ) else: decoratee_value = FunctionValue.from_context(context, node) initial = values = ValueSet([decoratee_value]) if is_big_annoying_library(context): return values for dec in reversed(node.get_decorators()): debug.dbg('decorator: %s %s', dec, values, color="MAGENTA") with debug.increase_indent_cm(): dec_values = context.infer_node(dec.children[1]) trailer_nodes = dec.children[2:-1] if trailer_nodes: # Create a trailer and infer it. trailer = tree.PythonNode('trailer', trailer_nodes) trailer.parent = dec dec_values = infer_trailer(context, dec_values, trailer) if not len(dec_values): code = dec.get_code(include_prefix=False) # For the short future, we don't want to hear about the runtime # decorator in typing that was intentionally omitted. This is not # "correct", but helps with debugging. if code != '@runtime\n': debug.warning('decorator not found: %s on %s', dec, node) return initial values = dec_values.execute(arguments.ValuesArguments([values])) if not len(values): debug.warning('not possible to resolve wrappers found %s', node) return initial debug.dbg('decorator end %s', values, color="MAGENTA") if values != initial: return ValueSet([Decoratee(c, decoratee_value) for c in values]) return values
def _stub_to_python_value_set(stub_value, ignore_compiled=False): stub_module_context = stub_value.get_root_context() if not stub_module_context.is_stub(): return ValueSet([stub_value]) decorates = None if isinstance(stub_value, Decoratee): decorates = stub_value._original_value was_instance = stub_value.is_instance() if was_instance: arguments = getattr(stub_value, '_arguments', None) stub_value = stub_value.py__class__() qualified_names = stub_value.get_qualified_names() if qualified_names is None: return NO_VALUES was_bound_method = stub_value.is_bound_method() if was_bound_method: # Infer the object first. We can infer the method later. method_name = qualified_names[-1] qualified_names = qualified_names[:-1] was_instance = True arguments = None values = _infer_from_stub(stub_module_context, qualified_names, ignore_compiled) if was_instance: values = ValueSet.from_sets( c.execute_with_values() if arguments is None else c.execute(arguments) for c in values if c.is_class() ) if was_bound_method: # Now that the instance has been properly created, we can simply get # the method. values = values.py__getattribute__(method_name) if decorates is not None: values = ValueSet(Decoratee(v, decorates) for v in values) return values