Ejemplo n.º 1
0
def builtins_isinstance(evaluator, objects, types, arguments):
    bool_results = set([])
    for o in objects:
        try:
            mro_func = o.py__class__().py__mro__
        except AttributeError:
            # This is temporary. Everything should have a class attribute in
            # Python?! Maybe we'll leave it here, because some numpy objects or
            # whatever might not.
            return set([compiled.create(True), compiled.create(False)])

        mro = mro_func()

        for cls_or_tup in types:
            if cls_or_tup.is_class():
                bool_results.add(cls_or_tup in mro)
            elif cls_or_tup.name.string_name == 'tuple' \
                    and cls_or_tup.get_root_context() == evaluator.BUILTINS:
                # Check for tuples.
                classes = unite(
                    lazy_context.infer()
                    for lazy_context in cls_or_tup.py__iter__()
                )
                bool_results.add(any(cls in mro for cls in classes))
            else:
                _, lazy_context = list(arguments.unpack())[1]
                if isinstance(lazy_context, LazyTreeContext):
                    node = lazy_context.data
                    message = 'TypeError: isinstance() arg 2 must be a ' \
                              'class, type, or tuple of classes and types, ' \
                              'not %s.' % cls_or_tup
                    analysis.add(lazy_context._context, 'type-error-isinstance', node, message)

    return set(compiled.create(evaluator, x) for x in bool_results)
Ejemplo n.º 2
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or _is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or _is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or _is_string(left) and _is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, er.Instance) and obj.name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Ejemplo n.º 3
0
def _element_calculate(evaluator, context, left, operator, right):
    from jedi.evaluate import iterable, instance
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.AbstractSequence) or is_string(left):
            return set([left])
        elif isinstance(right, iterable.AbstractSequence) or is_string(right):
            return set([right])
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return set([create(evaluator, left.obj + right.obj)])
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return set([iterable.MergedArray(evaluator, (left, right))])
    elif operator == '-':
        if l_is_num and r_is_num:
            return set([create(evaluator, left.obj - right.obj)])
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return set([left])
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            result = operation(left, right)
        except TypeError:
            # Could be True or False.
            return set([create(evaluator, True), create(evaluator, False)])
        else:
            return set([create(evaluator, result)])
    elif operator == 'in':
        return set()

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, instance.CompiledInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    return set([left, right])
Ejemplo n.º 4
0
def _element_calculate(evaluator, context, left, operator, right):
    from jedi.evaluate import iterable, instance
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.AbstractSequence) or is_string(left):
            return set([left])
        elif isinstance(right, iterable.AbstractSequence) or is_string(right):
            return set([right])
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return set([create(evaluator, left.obj + right.obj)])
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return set([iterable.MergedArray(evaluator, (left, right))])
    elif operator == '-':
        if l_is_num and r_is_num:
            return set([create(evaluator, left.obj - right.obj)])
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return set([left])
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            result = operation(left, right)
        except TypeError:
            # Could be True or False.
            return set([create(evaluator, True), create(evaluator, False)])
        else:
            return set([create(evaluator, result)])
    elif operator == 'in':
        return set()

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, instance.CompiledInstance) and \
            obj.name.string_name in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(context, 'type-error-operation', operator,
                     message % (left, right))

    return set([left, right])
Ejemplo n.º 5
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(
                left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(
                right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            return [keyword_from_value(operation(left, right))]
        except TypeError:
            # Could be True or False.
            return [true_obj, false_obj]
    elif operator == 'in':
        return []

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(
            obj, er.Instance) and obj.name.get_code() in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
def _element_calculate(evaluator, left, operator, right):
    if operator == '*':
        # for iterables, ignore * operations
        from jedi.evaluate import iterable
        if isinstance(left, iterable.Array) or _is_string(left):
            return [left]
    elif operator == '+':
        if _is_number(left) and _is_number(right) or _is_string(left) and _is_string(right):
            return [create(evaluator, left.obj + right.obj)]
    elif operator == '-':
        if _is_number(left) and _is_number(right):
            return [create(evaluator, left.obj - right.obj)]
    return [left, right]
Ejemplo n.º 7
0
def _element_calculate(evaluator, left, operator, right):
    if operator == '*':
        # for iterables, ignore * operations
        from jedi.evaluate import iterable
        if isinstance(left, iterable.Array) or _is_string(left):
            return [left]
    elif operator == '+':
        if _is_number(left) and _is_number(right) or _is_string(
                left) and _is_string(right):
            return [create(evaluator, left.obj + right.obj)]
    elif operator == '-':
        if _is_number(left) and _is_number(right):
            return [create(evaluator, left.obj - right.obj)]
    return [left, right]
Ejemplo n.º 8
0
def _element_calculate(evaluator, left, operator, right):
    from jedi.evaluate import iterable, representation as er
    l_is_num = _is_number(left)
    r_is_num = _is_number(right)
    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
        elif isinstance(right, iterable.Array) or is_string(right):
            return [right]
    elif operator == '+':
        if l_is_num and r_is_num or is_string(left) and is_string(right):
            return [create(evaluator, left.obj + right.obj)]
        elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
            return [iterable.MergedArray(evaluator, (left, right))]
    elif operator == '-':
        if l_is_num and r_is_num:
            return [create(evaluator, left.obj - right.obj)]
    elif operator == '%':
        # With strings and numbers the left type typically remains. Except for
        # `int() % float()`.
        return [left]
    elif operator in COMPARISON_OPERATORS:
        operation = COMPARISON_OPERATORS[operator]
        if isinstance(left, CompiledObject) and isinstance(right, CompiledObject):
            # Possible, because the return is not an option. Just compare.
            left = left.obj
            right = right.obj

        try:
            return [keyword_from_value(operation(left, right))]
        except TypeError:
            # Could be True or False.
            return [true_obj, false_obj]
    elif operator == 'in':
        return []

    def check(obj):
        """Checks if a Jedi object is either a float or an int."""
        return isinstance(obj, er.Instance) and obj.name.get_code() in ('int', 'float')

    # Static analysis, one is a number, the other one is not.
    if operator in ('+', '-') and l_is_num != r_is_num \
            and not (check(left) or check(right)):
        message = "TypeError: unsupported operand type(s) for +: %s and %s"
        analysis.add(evaluator, 'type-error-operation', operator,
                     message % (left, right))

    return [left, right]
Ejemplo n.º 9
0
def eval_factor(context_set, operator):
    """
    Calculates `+`, `-`, `~` and `not` prefixes.
    """
    for context in context_set:
        if operator == '-':
            if is_number(context):
                yield compiled.create(context.evaluator, -context.obj)
        elif operator == 'not':
            value = context.py__bool__()
            if value is None:  # Uncertainty.
                return
            yield compiled.create(context.evaluator, not value)
        else:
            yield context
def factor_calculate(evaluator, types, operator):
    """
    Calculates `+`, `-`, `~` and `not` prefixes.
    """
    for typ in types:
        if operator == '-':
            if _is_number(typ):
                yield create(evaluator, -typ.obj)
        elif operator == 'not':
            value = typ.py__bool__()
            if value is None:  # Uncertainty.
                return
            yield create(evaluator, not value)
        else:
            yield typ
Ejemplo n.º 11
0
def eval_factor(context_set, operator):
    """
    Calculates `+`, `-`, `~` and `not` prefixes.
    """
    for context in context_set:
        if operator == '-':
            if is_number(context):
                yield compiled.create(context.evaluator, -context.obj)
        elif operator == 'not':
            value = context.py__bool__()
            if value is None:  # Uncertainty.
                return
            yield compiled.create(context.evaluator, not value)
        else:
            yield context
Ejemplo n.º 12
0
def factor_calculate(evaluator, types, operator):
    """
    Calculates `+`, `-`, `~` and `not` prefixes.
    """
    for typ in types:
        if operator == '-':
            if _is_number(typ):
                yield create(evaluator, -typ.obj)
        elif operator == 'not':
            value = typ.py__bool__()
            if value is None:  # Uncertainty.
                return
            yield create(evaluator, not value)
        else:
            yield typ
    def get_return_values(self, check_yields=False):
        funcdef = self.tree_node
        if funcdef.type == 'lambdef':
            return self.evaluator.eval_element(self, funcdef.children[-1])

        if check_yields:
            types = set()
            returns = get_yield_exprs(self.evaluator, funcdef)
        else:
            returns = funcdef.iter_return_stmts()
            types = set(docstrings.infer_return_types(self.function_context))
            types |= set(pep0484.infer_return_types(self.function_context))

        for r in returns:
            check = flow_analysis.reachability_check(self, funcdef, r)
            if check is flow_analysis.UNREACHABLE:
                debug.dbg('Return unreachable: %s', r)
            else:
                if check_yields:
                    types |= set(self._eval_yield(r))
                else:
                    try:
                        children = r.children
                    except AttributeError:
                        types.add(compiled.create(self.evaluator, None))
                    else:
                        types |= self.eval_node(children[1])
            if check is flow_analysis.REACHABLE:
                debug.dbg('Return reachable: %s', r)
                break
        return types
Ejemplo n.º 14
0
 def py__bases__(self):
     arglist = self.base.get_super_arglist()
     if arglist:
         args = param.Arguments(self._evaluator, arglist)
         return list(chain.from_iterable(args.eval_args()))
     else:
         return [compiled.create(self._evaluator, object)]
Ejemplo n.º 15
0
 def _eval_element_not_cached(self, element):
     debug.dbg('eval_element %s@%s', element, element.start_pos)
     types = set()
     if isinstance(element, (tree.Name, tree.Literal)) or tree.is_node(
             element, 'atom'):
         types = self._eval_atom(element)
     elif isinstance(element, tree.Keyword):
         # For False/True/None
         if element.value in ('False', 'True', 'None'):
             types.add(compiled.builtin_from_name(self, element.value))
         # else: print e.g. could be evaluated like this in Python 2.7
     elif element.isinstance(tree.Lambda):
         types = set([er.LambdaWrapper(self, element)])
     elif element.isinstance(er.LambdaWrapper):
         types = set([element
                      ])  # TODO this is no real evaluation. id:121 gh:122
     elif element.type == 'expr_stmt':
         types = self.eval_statement(element)
     elif element.type in ('power', 'atom_expr'):
         types = self._eval_atom(element.children[0])
         for trailer in element.children[1:]:
             if trailer == '**':  # has a power operation.
                 right = self.eval_element(element.children[2])
                 types = set(
                     precedence.calculate(self, types, trailer, right))
                 break
             types = self.eval_trailer(types, trailer)
     elif element.type in (
             'testlist_star_expr',
             'testlist',
     ):
         # The implicit tuple in statements.
         types = set([iterable.ImplicitTuple(self, element)])
     elif element.type in ('not_test', 'factor'):
         types = self.eval_element(element.children[-1])
         for operator in element.children[:-1]:
             types = set(precedence.factor_calculate(self, types, operator))
     elif element.type == 'test':
         # `x if foo else y` case.
         types = (self.eval_element(element.children[0])
                  | self.eval_element(element.children[-1]))
     elif element.type == 'operator':
         # Must be an ellipsis, other operators are not evaluated.
         assert element.value == '...'
         types = set([compiled.create(self, Ellipsis)])
     elif element.type == 'dotted_name':
         types = self._eval_atom(element.children[0])
         for next_name in element.children[2::2]:
             types = set(
                 chain.from_iterable(
                     self.find_types(typ, next_name) for typ in types))
         types = types
     elif element.type == 'eval_input':
         types = self._eval_element_not_cached(element.children[0])
     elif element.type == 'annassign':
         types = self.eval_element(element.children[1])
     else:
         types = precedence.calculate_children(self, element.children)
     debug.dbg('eval_element result %s', types)
     return types
Ejemplo n.º 16
0
def _create(evaluator, obj, parent_context=None, *args):
    tree_node, path = find_syntax_node_name(evaluator, obj)

    compiled_object = compiled.create(
        evaluator, obj, parent_context=parent_context.compiled_object)
    if tree_node is None:
        return compiled_object

    module_node = tree_node.get_root_node()
    if parent_context.tree_node.get_root_node() == module_node:
        module_context = parent_context.get_root_context()
    else:
        module_context = ModuleContext(evaluator, module_node, path=path)
        # TODO this __name__ is probably wrong.
        name = compiled_object.get_root_context().py__name__()
        imports.add_module(evaluator, name, module_context)

    tree_context = module_context.create_context(
        tree_node,
        node_is_context=True,
        node_is_object=True
    )
    if tree_node.type == 'classdef':
        if not inspect.isclass(obj):
            # Is an instance, not a class.
            tree_context, = tree_context.execute_evaluated()

    return MixedObject(
        evaluator,
        parent_context,
        compiled_object,
        tree_context=tree_context
    )
Ejemplo n.º 17
0
 def py__bases__(self):
     arglist = self.tree_node.get_super_arglist()
     if arglist:
         args = param.TreeArguments(self.evaluator, self, arglist)
         return [value for key, value in args.unpack() if key is None]
     else:
         return [context.LazyKnownContext(compiled.create(self.evaluator, object))]
Ejemplo n.º 18
0
 def py__bases__(self):
     arglist = self.tree_node.get_super_arglist()
     if arglist:
         args = param.TreeArguments(self.evaluator, self, arglist)
         return [value for key, value in args.unpack() if key is None]
     else:
         return [context.LazyKnownContext(compiled.create(self.evaluator, object))]
Ejemplo n.º 19
0
def create(evaluator, obj, parent_context=None, *args):
    tree_node, path = find_syntax_node_name(evaluator, obj)

    compiled_object = compiled.create(
        evaluator, obj, parent_context=parent_context.compiled_object)
    if tree_node is None:
        return compiled_object

    module_node = tree_node.get_root_node()
    if parent_context.tree_node.get_root_node() == module_node:
        module_context = parent_context.get_root_context()
    else:
        from jedi.evaluate.representation import ModuleContext
        module_context = ModuleContext(evaluator, module_node, path=path)
        name = compiled_object.get_root_context().py__name__()
        imports.add_module(evaluator, name, module_context)

    tree_context = module_context.create_context(
        tree_node,
        node_is_context=True,
        node_is_object=True
    )

    return MixedObject(
        evaluator,
        parent_context,
        compiled_object,
        tree_context=tree_context
    )
 def py__bases__(self):
     arglist = self.base.get_super_arglist()
     if arglist:
         args = param.Arguments(self._evaluator, arglist)
         return list(chain.from_iterable(args.eval_args()))
     else:
         return [compiled.create(self._evaluator, object)]
Ejemplo n.º 21
0
    def eval_call_path(self, path, scope, position):
        """
        Follows a path generated by `pr.StatementElement.generate_call_path()`.
        """
        current = next(path)

        if isinstance(current, pr.Array):
            if current.type == pr.Array.NOARRAY:
                try:
                    lst_cmp = current[0].expression_list()[0]
                    if not isinstance(lst_cmp, pr.ListComprehension):
                        raise IndexError
                except IndexError:
                    types = list(chain.from_iterable(self.eval_statement(s)
                                                     for s in current))
                else:
                    types = [iterable.GeneratorComprehension(self, lst_cmp)]
            else:
                types = [iterable.Array(self, current)]
        else:
            if isinstance(current, pr.Name):
                # This is the first global lookup.
                types = self.find_types(scope, current, position=position,
                                        search_global=True)
            else:
                # for pr.Literal
                types = [compiled.create(self, current.value)]
            types = imports.follow_imports(self, types)

        return self.follow_path(path, types, scope)
Ejemplo n.º 22
0
 def _eval_atom(self, atom):
     """
     Basically to process ``atom`` nodes. The parser sometimes doesn't
     generate the node (because it has just one child). In that case an atom
     might be a name or a literal as well.
     """
     if isinstance(atom, pr.Name):
         # This is the first global lookup.
         stmt = atom.get_definition()
         scope = stmt.get_parent_until(pr.IsScope, include_current=True)
         if isinstance(stmt, pr.CompFor):
             stmt = stmt.get_parent_until((pr.ClassOrFunc, pr.ExprStmt))
         if stmt.type != 'expr_stmt':
             # We only need to adjust the start_pos for statements, because
             # there the name cannot be used.
             stmt = atom
         return self.find_types(scope, atom, stmt.start_pos, search_global=True)
     elif isinstance(atom, pr.Literal):
         return [compiled.create(self, atom.eval())]
     else:
         c = atom.children
         # Parentheses without commas are not tuples.
         if c[0] == '(' and not len(c) == 2 \
                 and not(pr.is_node(c[1], 'testlist_comp')
                         and len(c[1].children) > 1):
             return self.eval_element(c[1])
         try:
             comp_for = c[1].children[1]
         except (IndexError, AttributeError):
             pass
         else:
             if isinstance(comp_for, pr.CompFor):
                 return [iterable.Comprehension.from_atom(self, atom)]
         return [iterable.Array(self, atom)]
Ejemplo n.º 23
0
    def get_return_values(self, check_yields=False):
        funcdef = self.tree_node
        if funcdef.type == 'lambdef':
            return self.evaluator.eval_element(self, funcdef.children[-1])

        if check_yields:
            types = set()
            returns = get_yield_exprs(self.evaluator, funcdef)
        else:
            returns = funcdef.iter_return_stmts()
            types = set(docstrings.infer_return_types(self.function_context))
            types |= set(pep0484.infer_return_types(self.function_context))

        for r in returns:
            check = flow_analysis.reachability_check(self, funcdef, r)
            if check is flow_analysis.UNREACHABLE:
                debug.dbg('Return unreachable: %s', r)
            else:
                if check_yields:
                    types |= set(self._eval_yield(r))
                else:
                    try:
                        children = r.children
                    except AttributeError:
                        types.add(compiled.create(self.evaluator, None))
                    else:
                        types |= self.eval_node(children[1])
            if check is flow_analysis.REACHABLE:
                debug.dbg('Return reachable: %s', r)
                break
        return types
Ejemplo n.º 24
0
 def _eval_atom(self, atom):
     """
     Basically to process ``atom`` nodes. The parser sometimes doesn't
     generate the node (because it has just one child). In that case an atom
     might be a name or a literal as well.
     """
     if isinstance(atom, pr.Name):
         # This is the first global lookup.
         stmt = atom.get_definition()
         scope = stmt.get_parent_until(pr.IsScope, include_current=True)
         if isinstance(stmt, pr.CompFor):
             stmt = stmt.get_parent_until((pr.ClassOrFunc, pr.ExprStmt))
         if stmt.type != 'expr_stmt':
             # We only need to adjust the start_pos for statements, because
             # there the name cannot be used.
             stmt = atom
         return self.find_types(scope, atom, stmt.start_pos, search_global=True)
     elif isinstance(atom, pr.Literal):
         return [compiled.create(self, atom.eval())]
     else:
         c = atom.children
         # Parentheses without commas are not tuples.
         if c[0] == '(' and not len(c) == 2 \
                 and not(pr.is_node(c[1], 'testlist_comp')
                         and len(c[1].children) > 1):
             return self.eval_element(c[1])
         try:
             comp_for = c[1].children[1]
         except (IndexError, AttributeError):
             pass
         else:
             if isinstance(comp_for, pr.CompFor):
                 return [iterable.Comprehension.from_atom(self, atom)]
         return [iterable.Array(self, atom)]
Ejemplo n.º 25
0
def create(evaluator, obj, parent_context=None, *args):
    tree_node, path = find_syntax_node_name(evaluator, obj)

    compiled_object = compiled.create(
        evaluator, obj, parent_context=parent_context.compiled_object)
    if tree_node is None:
        return compiled_object

    module_node = tree_node.get_root_node()
    if parent_context.tree_node.get_root_node() == module_node:
        module_context = parent_context.get_root_context()
    else:
        from jedi.evaluate.representation import ModuleContext
        module_context = ModuleContext(evaluator, module_node, path=path)
        name = compiled_object.get_root_context().py__name__()
        imports.add_module(evaluator, name, module_context)

    tree_context = module_context.create_context(tree_node,
                                                 node_is_context=True,
                                                 node_is_object=True)

    return MixedObject(evaluator,
                       parent_context,
                       compiled_object,
                       tree_context=tree_context)
Ejemplo n.º 26
0
def test_fake_loading():
    assert isinstance(compiled.create(Evaluator(), next), Function)

    string = compiled.builtin.get_subscope_by_name('str')
    from_name = compiled._create_from_name(compiled.builtin, string,
                                           '__init__')
    assert isinstance(from_name, Function)
Ejemplo n.º 27
0
    def _eval_atom(self, atom):
        """
        Basically to process ``atom`` nodes. The parser sometimes doesn't
        generate the node (because it has just one child). In that case an atom
        might be a name or a literal as well.
        """
        if isinstance(atom, tree.Name):
            # This is the first global lookup.
            stmt = atom.get_definition()
            scope = stmt.get_parent_until(tree.IsScope, include_current=True)
            if isinstance(scope, (tree.Function, er.FunctionExecution)):
                # Adjust scope: If the name is not in the suite, it's a param
                # default or annotation and will be resolved as part of the
                # parent scope.
                colon = scope.children.index(':')
                if atom.start_pos < scope.children[colon + 1].start_pos:
                    scope = scope.get_parent_scope()
            if isinstance(stmt, tree.CompFor):
                stmt = stmt.get_parent_until((tree.ClassOrFunc, tree.ExprStmt))
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = atom
            return self.find_types(scope,
                                   atom,
                                   stmt.start_pos,
                                   search_global=True)
        elif isinstance(atom, tree.Literal):
            return set([compiled.create(self, atom.eval())])
        else:
            c = atom.children
            if c[0].type == 'string':
                # Will be one string.
                types = self._eval_atom(c[0])
                for string in c[1:]:
                    right = self._eval_atom(string)
                    types = precedence.calculate(self, types, '+', right)
                return types
            # Parentheses without commas are not tuples.
            elif c[0] == '(' and not len(c) == 2 \
                    and not(tree.is_node(c[1], 'testlist_comp')
                            and len(c[1].children) > 1):
                return self.eval_element(c[1])

            try:
                comp_for = c[1].children[1]
            except (IndexError, AttributeError):
                pass
            else:
                if comp_for == ':':
                    # Dict comprehensions have a colon at the 3rd index.
                    try:
                        comp_for = c[1].children[3]
                    except IndexError:
                        pass

                if comp_for.type == 'comp_for':
                    return set([iterable.Comprehension.from_atom(self, atom)])
            return set([iterable.Array(self, atom)])
Ejemplo n.º 28
0
 def _eval_element_not_cached(self, context, element):
     debug.dbg('eval_element %s@%s', element, element.start_pos)
     types = set()
     typ = element.type
     if typ in ('name', 'number', 'string', 'atom'):
         types = self.eval_atom(context, element)
     elif typ == 'keyword':
         # For False/True/None
         if element.value in ('False', 'True', 'None'):
             types.add(compiled.builtin_from_name(self, element.value))
         # else: print e.g. could be evaluated like this in Python 2.7
     elif typ == 'lambdef':
         types = set([er.FunctionContext(self, context, element)])
     elif typ == 'expr_stmt':
         types = self.eval_statement(context, element)
     elif typ in ('power', 'atom_expr'):
         first_child = element.children[0]
         if not (first_child.type == 'keyword' and first_child.value == 'await'):
             types = self.eval_atom(context, first_child)
             for trailer in element.children[1:]:
                 if trailer == '**':  # has a power operation.
                     right = self.eval_element(context, element.children[2])
                     types = set(precedence.calculate(self, context, types, trailer, right))
                     break
                 types = self.eval_trailer(context, types, trailer)
     elif typ in ('testlist_star_expr', 'testlist',):
         # The implicit tuple in statements.
         types = set([iterable.SequenceLiteralContext(self, context, element)])
     elif typ in ('not_test', 'factor'):
         types = self.eval_element(context, element.children[-1])
         for operator in element.children[:-1]:
             types = set(precedence.factor_calculate(self, types, operator))
     elif typ == 'test':
         # `x if foo else y` case.
         types = (self.eval_element(context, element.children[0]) |
                  self.eval_element(context, element.children[-1]))
     elif typ == 'operator':
         # Must be an ellipsis, other operators are not evaluated.
         # In Python 2 ellipsis is coded as three single dot tokens, not
         # as one token 3 dot token.
         assert element.value in ('.', '...')
         types = set([compiled.create(self, Ellipsis)])
     elif typ == 'dotted_name':
         types = self.eval_atom(context, element.children[0])
         for next_name in element.children[2::2]:
             # TODO add search_global=True?
             types = unite(
                 typ.py__getattribute__(next_name, name_context=context)
                 for typ in types
             )
         types = types
     elif typ == 'eval_input':
         types = self._eval_element_not_cached(context, element.children[0])
     elif typ == 'annassign':
         types = pep0484._evaluate_for_annotation(context, element.children[1])
     else:
         types = precedence.calculate_children(self, context, element.children)
     debug.dbg('eval_element result %s', types)
     return types
Ejemplo n.º 29
0
 def _module_attributes(self):
     names = [
         '__file__', '__package__', '__doc__', '__name__', '__version__'
     ]
     # All the additional module attributes are strings.
     parent = Instance(self._evaluator,
                       compiled.create(self._evaluator, str))
     return [helpers.FakeName(n, parent) for n in names]
Ejemplo n.º 30
0
def create(evaluator, obj, parent_context=None, *args):
    tree_name = find_syntax_node_name(evaluator, obj)

    compiled_object = compiled.create(
        evaluator, obj, parent_context=parent_context.compiled_object)
    if tree_name is None:
        return compiled_object
    return MixedObject(evaluator, parent_context, compiled_object, tree_name)
Ejemplo n.º 31
0
def create(evaluator, obj, parent_context=None, *args):
    tree_name = find_syntax_node_name(evaluator, obj)

    compiled_object = compiled.create(
        evaluator, obj, parent_context=parent_context.compiled_object)
    if tree_name is None:
        return compiled_object
    return MixedObject(evaluator, parent_context, compiled_object, tree_name)
Ejemplo n.º 32
0
def test_fake_loading():
    e = _evaluator()
    assert isinstance(compiled.create(e, next), Function)

    builtin = compiled.get_special_object(e, 'BUILTINS')
    string = builtin.get_subscope_by_name('str')
    from_name = compiled._create_from_name(e, builtin, string, '__init__')
    assert isinstance(from_name, Function)
Ejemplo n.º 33
0
def test_fake_loading():
    e = _evaluator()
    assert isinstance(compiled.create(e, next), FunctionContext)

    builtin = compiled.get_special_object(e, 'BUILTINS')
    string, = builtin.py__getattribute__('str')
    from_name = compiled._create_from_name(e, builtin, string, '__init__')
    assert isinstance(from_name, FunctionContext)
Ejemplo n.º 34
0
 def py__getitem__(self, index):
     try:
         method = self.get_subscope_by_name('__getitem__')
     except KeyError:
         debug.warning('No __getitem__, cannot access the array.')
         return set()
     else:
         index_obj = compiled.create(self._evaluator, index)
         return self._evaluator.execute_evaluated(method, index_obj)
Ejemplo n.º 35
0
 def py__getitem__(self, index):
     try:
         names = self.get_function_slot_names('__getitem__')
     except KeyError:
         debug.warning('No __getitem__, cannot access the array.')
         return NO_CONTEXTS
     else:
         index_obj = compiled.create(self.evaluator, index)
         return self.execute_function_slots(names, index_obj)
 def py__getitem__(self, index):
     try:
         method = self.get_subscope_by_name('__getitem__')
     except KeyError:
         debug.warning('No __getitem__, cannot access the array.')
         return set()
     else:
         index_obj = compiled.create(self._evaluator, index)
         return self._evaluator.execute_evaluated(method, index_obj)
Ejemplo n.º 37
0
 def py__getitem__(self, index):
     try:
         names = self.get_function_slot_names('__getitem__')
     except KeyError:
         debug.warning('No __getitem__, cannot access the array.')
         return set()
     else:
         index_obj = compiled.create(self.evaluator, index)
         return self.execute_function_slots(names, index_obj)
Ejemplo n.º 38
0
    def _eval_atom(self, atom):
        """
        Basically to process ``atom`` nodes. The parser sometimes doesn't
        generate the node (because it has just one child). In that case an atom
        might be a name or a literal as well.
        """
        if isinstance(atom, tree.Name):
            # This is the first global lookup.
            stmt = atom.get_definition()
            scope = stmt.get_parent_until(tree.IsScope, include_current=True)
            if isinstance(scope, (tree.Function, er.FunctionExecution)):
                # Adjust scope: If the name is not in the suite, it's a param
                # default or annotation and will be resolved as part of the
                # parent scope.
                colon = scope.children.index(':')
                if atom.start_pos < scope.children[colon + 1].start_pos:
                    scope = scope.get_parent_scope()
            if isinstance(stmt, tree.CompFor):
                stmt = stmt.get_parent_until((tree.ClassOrFunc, tree.ExprStmt))
            if stmt.type != 'expr_stmt':
                # We only need to adjust the start_pos for statements, because
                # there the name cannot be used.
                stmt = atom
            return self.find_types(scope, atom, stmt.start_pos, search_global=True)
        elif isinstance(atom, tree.Literal):
            return set([compiled.create(self, atom.eval())])
        else:
            c = atom.children
            if c[0].type == 'string':
                # Will be one string.
                types = self._eval_atom(c[0])
                for string in c[1:]:
                    right = self._eval_atom(string)
                    types = precedence.calculate(self, types, '+', right)
                return types
            # Parentheses without commas are not tuples.
            elif c[0] == '(' and not len(c) == 2 \
                    and not(tree.is_node(c[1], 'testlist_comp')
                            and len(c[1].children) > 1):
                return self.eval_element(c[1])

            try:
                comp_for = c[1].children[1]
            except (IndexError, AttributeError):
                pass
            else:
                if comp_for == ':':
                    # Dict comprehensions have a colon at the 3rd index.
                    try:
                        comp_for = c[1].children[3]
                    except IndexError:
                        pass

                if comp_for.type == 'comp_for':
                    return set([iterable.Comprehension.from_atom(self, atom)])
            return set([iterable.Array(self, atom)])
 def get_descriptor_returns(self, obj):
     """ Throws a KeyError if there's no method. """
     # Arguments in __get__ descriptors are obj, class.
     # `method` is the new parent of the array, don't know if that's good.
     none_obj = compiled.create(self._evaluator, None)
     args = [obj, obj.base] if isinstance(obj, Instance) else [none_obj, obj]
     try:
         return self.execute_subscope_by_name('__get__', *args)
     except KeyError:
         return set([self])
Ejemplo n.º 40
0
def test_fake_loading():
    assert isinstance(compiled.create(Evaluator(load_grammar()), next), Function)

    string = compiled.builtin.get_subscope_by_name('str')
    from_name = compiled._create_from_name(
        compiled.builtin,
        string,
        '__init__'
    )
    assert isinstance(from_name, Function)
Ejemplo n.º 41
0
def _factor_calculate(evaluator, operator, right):
    if _is_number(right):
        if operator == '-':
            return create(evaluator, -right.obj)
    if operator == 'not':
        value = right.py__bool__()
        if value is None:  # Uncertainty.
            return None
        return keyword_from_value(not value)
    return right
Ejemplo n.º 42
0
 def get_descriptor_returns(self, obj):
     """ Throws a KeyError if there's no method. """
     # Arguments in __get__ descriptors are obj, class.
     # `method` is the new parent of the array, don't know if that's good.
     none_obj = compiled.create(self._evaluator, None)
     args = [obj, obj.base] if isinstance(obj,
                                          Instance) else [none_obj, obj]
     try:
         return self.execute_subscope_by_name('__get__', *args)
     except KeyError:
         return set([self])
Ejemplo n.º 43
0
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
Ejemplo n.º 44
0
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(context.evaluator.latest_grammar),
        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
Ejemplo n.º 45
0
def _element_calculate(left, operator, right):
    def is_string(obj):
        return isinstance(obj, CompiledObject) \
            and isinstance(obj.obj, (str, unicode))

    def is_number(obj):
        return isinstance(obj, CompiledObject) \
            and isinstance(obj.obj, (int, float))

    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
    elif operator == '+':
        if is_number(left) and is_number(right) or is_string(left) and is_string(right):
            return [create(left.obj + right.obj)]
    elif operator == '-':
        if is_number(left) and is_number(right):
            return [create(left.obj - right.obj)]
    return [left, right]
Ejemplo n.º 46
0
    def parent(self):
        obj = self._value
        parser_path = []
        if inspect.ismodule(obj):
            module = obj
        else:
            class FakeParent(pr.Base):
                parent = None  # To avoid having no parent for NamePart.
                path = None

            names = []
            try:
                o = obj.__objclass__
                names.append(obj.__name__)
                obj = o
            except AttributeError:
                pass

            try:
                module_name = obj.__module__
                names.insert(0, obj.__name__)
            except AttributeError:
                # Unfortunately in some cases like `int` there's no __module__
                module = builtins
            else:
                module = __import__(module_name)
            fake_name = helpers.FakeName(names, FakeParent())
            parser_path = fake_name.names
        raw_module = get_module(self._value)

        try:
            path = module.__file__
        except AttributeError:
            pass
        else:
            path = re.sub('c$', '', path)
            if path.endswith('.py'):
                # cut the `c` from `.pyc`
                with open(path) as f:
                    source = source_to_unicode(f.read())
                mod = FastParser(source, path[:-1]).module
                if not parser_path:
                    return mod
                found = self._evaluator.eval_call_path(iter(parser_path), mod, None)
                if found:
                    return found[0]
                debug.warning('Interpreter lookup for Python code failed %s',
                              mod)

        module = compiled.CompiledObject(raw_module)
        if raw_module == builtins:
            # The builtins module is special and always cached.
            module = compiled.builtin
        return compiled.create(self._evaluator, self._value, module, module)
Ejemplo n.º 47
0
def _element_calculate(left, operator, right):
    def is_string(obj):
        return isinstance(obj, CompiledObject) \
            and isinstance(obj.obj, (str, unicode))

    def is_number(obj):
        return isinstance(obj, CompiledObject) \
            and isinstance(obj.obj, (int, float))

    if operator == '*':
        # for iterables, ignore * operations
        if isinstance(left, iterable.Array) or is_string(left):
            return [left]
    elif operator == '+':
        if is_number(left) and is_number(right) or is_string(
                left) and is_string(right):
            return [create(left.obj + right.obj)]
    elif operator == '-':
        if is_number(left) and is_number(right):
            return [create(left.obj - right.obj)]
    return [left, right]
Ejemplo n.º 48
0
    def get_filters(self, *args, **kwargs):
        for filter in self._module_context.get_filters(*args, **kwargs):
            yield filter

        for namespace_obj in self._namespace_objects:
            compiled_object = compiled.create(self.evaluator, namespace_obj)
            mixed_object = mixed.MixedObject(self.evaluator,
                                             parent_context=self,
                                             compiled_object=compiled_object,
                                             tree_context=self._module_context)
            for filter in mixed_object.get_filters(*args, **kwargs):
                yield filter
Ejemplo n.º 49
0
 def py__get__(self, obj):
     # Arguments in __get__ descriptors are obj, class.
     # `method` is the new parent of the array, don't know if that's good.
     names = self.get_function_slot_names('__get__')
     if names:
         if isinstance(obj, AbstractInstanceContext):
             return self.execute_function_slots(names, obj, obj.class_context)
         else:
             none_obj = compiled.create(self.evaluator, None)
             return self.execute_function_slots(names, none_obj, obj)
     else:
         return set([self])
Ejemplo n.º 50
0
 def py__get__(self, obj):
     # Arguments in __get__ descriptors are obj, class.
     # `method` is the new parent of the array, don't know if that's good.
     names = self.get_function_slot_names('__get__')
     if names:
         if isinstance(obj, AbstractInstanceContext):
             return self.execute_function_slots(names, obj, obj.class_context)
         else:
             none_obj = compiled.create(self.evaluator, None)
             return self.execute_function_slots(names, none_obj, obj)
     else:
         return ContextSet(self)
Ejemplo n.º 51
0
 def _eval_element_not_cached(self, element):
     debug.dbg('eval_element %s@%s', element, element.start_pos)
     types = set()
     if isinstance(element, (tree.Name, tree.Literal)) or tree.is_node(element, 'atom'):
         types = self._eval_atom(element)
     elif isinstance(element, tree.Keyword):
         # For False/True/None
         if element.value in ('False', 'True', 'None'):
             types.add(compiled.builtin_from_name(self, element.value))
         # else: print e.g. could be evaluated like this in Python 2.7
     elif element.isinstance(tree.Lambda):
         types = set([er.LambdaWrapper(self, element)])
     elif element.isinstance(er.LambdaWrapper):
         types = set([element])  # TODO this is no real evaluation.
     elif element.type == 'expr_stmt':
         types = self.eval_statement(element)
     elif element.type in ('power', 'atom_expr'):
         types = self._eval_atom(element.children[0])
         for trailer in element.children[1:]:
             if trailer == '**':  # has a power operation.
                 right = self.eval_element(element.children[2])
                 types = set(precedence.calculate(self, types, trailer, right))
                 break
             types = self.eval_trailer(types, trailer)
     elif element.type in ('testlist_star_expr', 'testlist',):
         # The implicit tuple in statements.
         types = set([iterable.ImplicitTuple(self, element)])
     elif element.type in ('not_test', 'factor'):
         types = self.eval_element(element.children[-1])
         for operator in element.children[:-1]:
             types = set(precedence.factor_calculate(self, types, operator))
     elif element.type == 'test':
         # `x if foo else y` case.
         types = (self.eval_element(element.children[0]) |
                  self.eval_element(element.children[-1]))
     elif element.type == 'operator':
         # Must be an ellipsis, other operators are not evaluated.
         assert element.value == '...'
         types = set([compiled.create(self, Ellipsis)])
     elif element.type == 'dotted_name':
         types = self._eval_atom(element.children[0])
         for next_name in element.children[2::2]:
             types = set(chain.from_iterable(self.find_types(typ, next_name)
                                             for typ in types))
         types = types
     elif element.type == 'eval_input':
         types = self._eval_element_not_cached(element.children[0])
     elif element.type == 'annassign':
         types = self.eval_element(element.children[1])
     else:
         types = precedence.calculate_children(self, element.children)
     debug.dbg('eval_element result %s', types)
     return types
Ejemplo n.º 52
0
    def _eval_yield(self, yield_expr):
        if yield_expr.type == 'keyword':
            # `yield` just yields None.
            yield context.LazyKnownContext(compiled.create(self.evaluator, None))
            return

        node = yield_expr.children[1]
        if node.type == 'yield_arg':  # It must be a yield from.
            cn = ContextualizedNode(self, node.children[1])
            for lazy_context in iterable.py__iter__(self.evaluator, cn.infer(), cn):
                yield lazy_context
        else:
            yield context.LazyTreeContext(self, node)
Ejemplo n.º 53
0
    def _eval_yield(self, yield_expr):
        if yield_expr.type == 'keyword':
            # `yield` just yields None.
            yield LazyKnownContext(compiled.create(self.evaluator, None))
            return

        node = yield_expr.children[1]
        if node.type == 'yield_arg':  # It must be a yield from.
            cn = ContextualizedNode(self, node.children[1])
            for lazy_context in cn.infer().iterate(cn):
                yield lazy_context
        else:
            yield LazyTreeContext(self, node)
Ejemplo n.º 54
0
    def _check_getattr(self, inst):
        """Checks for both __getattr__ and __getattribute__ methods"""
        # str is important, because it shouldn't be `Name`!
        name = compiled.create(self._evaluator, self._string_name)

        # This is a little bit special. `__getattribute__` is in Python
        # executed before `__getattr__`. But: I know no use case, where
        # this could be practical and where Jedi would return wrong types.
        # If you ever find something, let me know!
        # We are inversing this, because a hand-crafted `__getattribute__`
        # could still call another hand-crafted `__getattr__`, but not the
        # other way around.
        names = (inst.get_function_slot_names('__getattr__')
                 or inst.get_function_slot_names('__getattribute__'))
        return inst.execute_function_slots(names, name)
Ejemplo n.º 55
0
 def _check_getattr(self, inst):
     """Checks for both __getattr__ and __getattribute__ methods"""
     result = []
     # str is important, because it shouldn't be `Name`!
     name = compiled.create(self._evaluator, str(self.name_str))
     with common.ignored(KeyError):
         result = inst.execute_subscope_by_name('__getattr__', name)
     if not result:
         # this is a little bit special. `__getattribute__` is executed
         # before anything else. But: I know no use case, where this
         # could be practical and the jedi would return wrong types. If
         # you ever have something, let me know!
         with common.ignored(KeyError):
             result = inst.execute_subscope_by_name('__getattribute__', name)
     return result