def from_scope_node(scope_node, is_nested=True, node_is_object=False): if scope_node == base_node: return base_context is_funcdef = scope_node.type in ('funcdef', 'lambdef') parent_scope = parser_utils.get_parent_scope(scope_node) parent_context = from_scope_node(parent_scope) if is_funcdef: func = FunctionContext.from_context(parent_context, scope_node) if parent_context.is_class(): instance = AnonymousInstance( self, parent_context.parent_context, parent_context) func = BoundMethod( instance=instance, function=func ) if is_nested and not node_is_object: return func.get_function_execution() return func elif scope_node.type == 'classdef': return ClassContext(self, parent_context, scope_node) elif scope_node.type == 'comp_for': if node.start_pos >= scope_node.children[-1].start_pos: return parent_context return CompForContext.from_comp_for(parent_context, scope_node) raise Exception("There's a scope that was not managed.")
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_context = ClassContext(context.evaluator, parent_context=context, tree_node=node) else: decoratee_context = FunctionContext.from_context(context, node) initial = values = ContextSet(decoratee_context) for dec in reversed(node.get_decorators()): debug.dbg('decorator: %s %s', dec, values) dec_values = context.eval_node(dec.children[1]) trailer_nodes = dec.children[2:-1] if trailer_nodes: # Create a trailer and evaluate it. trailer = tree.PythonNode('trailer', trailer_nodes) trailer.parent = dec dec_values = eval_trailer(context, dec_values, trailer) if not len(dec_values): 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) return values
def goto_stub_definitions(self, context, name): def_ = name.get_definition(import_name_always=True) if def_ is not None: type_ = def_.type is_classdef = type_ == 'classdef' if is_classdef or type_ == 'funcdef': if is_classdef: c = ClassContext(self, context, name.parent) else: c = FunctionContext.from_context(context, name.parent) return ContextSet([c]) if type_ == 'expr_stmt': is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return eval_expr_stmt(context, def_, name) if type_ == 'for_stmt': container_types = context.eval_node(def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterate_contexts(container_types, cn) c_node = ContextualizedName(context, name) return check_tuple_assignments(self, c_node, for_types) if type_ in ('import_from', 'import_name'): return imports.infer_import(context, name) else: result = self._follow_error_node_imports_if_possible(context, name) if result is not None: return result return helpers.evaluate_call_of_leaf(context, name)
def collections_namedtuple(obj, arguments, callback): """ Implementation of the namedtuple function. This has to be done by processing the namedtuple class template and evaluating the result. """ evaluator = obj.evaluator # Process arguments name = u'jedi_unknown_namedtuple' for c in _follow_param(evaluator, arguments, 0): x = get_str_or_none(c) if x is not None: name = force_unicode(x) break # TODO here we only use one of the types, we should use all. param_contexts = _follow_param(evaluator, arguments, 1) if not param_contexts: return NO_CONTEXTS _fields = list(param_contexts)[0] string = get_str_or_none(_fields) if string is not None: fields = force_unicode(string).replace(',', ' ').split() elif isinstance(_fields, iterable.Sequence): fields = [ force_unicode(get_str_or_none(v)) for lazy_context in _fields.py__iter__() for v in lazy_context.infer() ] fields = [f for f in fields if f is not None] else: return NO_CONTEXTS # Build source code code = _NAMEDTUPLE_CLASS_TEMPLATE.format( typename=name, field_names=tuple(fields), num_fields=len(fields), arg_list=repr(tuple(fields)).replace("u'", "").replace("'", "")[1:-1], repr_fmt='', field_defs='\n'.join( _NAMEDTUPLE_FIELD_TEMPLATE.format(index=index, name=name) for index, name in enumerate(fields))) # Parse source code module = evaluator.grammar.parse(code) generated_class = next(module.iter_classdefs()) parent_context = ModuleContext( evaluator, module, file_io=None, string_names=None, code_lines=parso.split_lines(code, keepends=True), ) return ContextSet( [ClassContext(evaluator, parent_context, generated_class)])
def collections_namedtuple(evaluator, obj, arguments): """ Implementation of the namedtuple function. This has to be done by processing the namedtuple class template and evaluating the result. """ collections_context = obj.parent_context _class_template_set = collections_context.py__getattribute__( u'_class_template') if not _class_template_set: # Namedtuples are not supported on Python 2.6, early 2.7, because the # _class_template variable is not defined, there. return NO_CONTEXTS # Process arguments # TODO here we only use one of the types, we should use all. # TODO this is buggy, doesn't need to be a string name = list(_follow_param(evaluator, arguments, 0))[0].get_safe_value() _fields = list(_follow_param(evaluator, arguments, 1))[0] if isinstance(_fields, compiled.CompiledObject): fields = _fields.get_safe_value().replace(',', ' ').split() elif isinstance(_fields, iterable.Sequence): fields = [ v.get_safe_value() for lazy_context in _fields.py__iter__() for v in lazy_context.infer() if is_string(v) ] else: return NO_CONTEXTS def get_var(name): x, = collections_context.py__getattribute__(name) return x.get_safe_value() base = next(iter(_class_template_set)).get_safe_value() base += _NAMEDTUPLE_INIT # Build source code code = base.format( typename=name, field_names=tuple(fields), num_fields=len(fields), arg_list=repr(tuple(fields)).replace("u'", "").replace("'", "")[1:-1], repr_fmt=', '.join( get_var(u'_repr_template').format(name=name) for name in fields), field_defs='\n'.join( get_var(u'_field_template').format(index=index, name=name) for index, name in enumerate(fields))) # Parse source code module = evaluator.grammar.parse(code) generated_class = next(module.iter_classdefs()) parent_context = ModuleContext( evaluator, module, None, code_lines=parso.split_lines(code, keepends=True), ) return ContextSet(ClassContext(evaluator, parent_context, generated_class))
def collections_namedtuple(evaluator, obj, arguments): """ Implementation of the namedtuple function. This has to be done by processing the namedtuple class template and evaluating the result. .. note:: |jedi| only supports namedtuples on Python >2.6. """ # Namedtuples are not supported on Python 2.6 if not hasattr(collections, '_class_template'): return NO_CONTEXTS # Process arguments # TODO here we only use one of the types, we should use all. id:464 gh:465 name = list(_follow_param(evaluator, arguments, 0))[0].obj _fields = list(_follow_param(evaluator, arguments, 1))[0] if isinstance(_fields, compiled.CompiledObject): fields = _fields.obj.replace(',', ' ').split() elif isinstance(_fields, iterable.AbstractIterable): fields = [ v.obj for lazy_context in _fields.py__iter__() for v in lazy_context.infer() if hasattr(v, 'obj') ] else: return NO_CONTEXTS base = collections._class_template base += _NAMEDTUPLE_INIT # Build source source = base.format( typename=name, field_names=tuple(fields), num_fields=len(fields), arg_list=repr(tuple(fields)).replace("'", "")[1:-1], repr_fmt=', '.join( collections._repr_template.format(name=name) for name in fields), field_defs='\n'.join( collections._field_template.format(index=index, name=name) for index, name in enumerate(fields))) # Parse source module = evaluator.grammar.parse(source) generated_class = next(module.iter_classdefs()) parent_context = ModuleContext(evaluator, module, '') return ContextSet(ClassContext(evaluator, parent_context, generated_class))
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_context = ClassContext( context.evaluator, parent_context=context, tree_node=node ) else: decoratee_context = FunctionContext.from_context(context, node) initial = values = ContextSet([decoratee_context]) for dec in reversed(node.get_decorators()): debug.dbg('decorator: %s %s', dec, values, color="MAGENTA") with debug.increase_indent_cm(): dec_values = context.eval_node(dec.children[1]) trailer_nodes = dec.children[2:-1] if trailer_nodes: # Create a trailer and evaluate it. trailer = tree.PythonNode('trailer', trailer_nodes) trailer.parent = dec dec_values = eval_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 ContextSet([Decoratee(c, decoratee_context) for c in values]) return values
def goto_definitions(self, context, name): def_ = name.get_definition(import_name_always=True) if def_ is not None: type_ = def_.type if type_ == 'classdef': return [ClassContext(self, context, name.parent)] elif type_ == 'funcdef': return [FunctionContext(self, context, name.parent)] if type_ == 'expr_stmt': is_simple_name = name.parent.type not in ('power', 'trailer') if is_simple_name: return eval_expr_stmt(context, def_, name) if type_ == 'for_stmt': container_types = context.eval_node(def_.children[3]) cn = ContextualizedNode(context, def_.children[3]) for_types = iterate_contexts(container_types, cn) c_node = ContextualizedName(context, name) return check_tuple_assignments(self, c_node, for_types) if type_ in ('import_from', 'import_name'): return imports.infer_import(context, name) return helpers.evaluate_call_of_leaf(context, name)