Exemplo n.º 1
0
 def get_key_values(self):
     filtered_values = itertools.chain.from_iterable(
         (f.values()
          for f in self._definition_class.get_filters(is_instance=True)))
     return ValueSet({
         create_simple_object(self.inference_state, v.string_name)
         for v in filtered_values
     })
Exemplo n.º 2
0
 def infer(self):
     if self._string_value is not None:
         s = self._string_value
         if self.parent_context.inference_state.environment.version_info.major == 2 \
                 and not isinstance(s, bytes):
             s = s.encode('utf-8')
         return ValueSet([
             create_simple_object(self.parent_context.inference_state, s)
         ])
     return compiled.get_string_value_set(self.parent_context.inference_state)
Exemplo n.º 3
0
def infer_factor(value_set, operator):
    """
    Calculates `+`, `-`, `~` and `not` prefixes.
    """
    for value in value_set:
        if operator == '-':
            if is_number(value):
                yield value.negate()
        elif operator == 'not':
            b = value.py__bool__()
            if b is None:  # Uncertainty.
                return
            yield compiled.create_simple_object(value.inference_state, not b)
        else:
            yield value
Exemplo n.º 4
0
    def get_key_values(self):
        values = NO_VALUES
        if self.array_type == 'dict':
            for i, (key, instance) in enumerate(self._arguments.unpack()):
                if key is None and i == 0:
                    values |= ValueSet.from_sets(v.get_key_values()
                                                 for v in instance.infer()
                                                 if v.array_type == 'dict')
                if key:
                    values |= ValueSet([
                        compiled.create_simple_object(
                            self.inference_state,
                            key,
                        )
                    ])

        return values
Exemplo n.º 5
0
    def py__getattribute__alternatives(self, string_name):
        '''
        Since nothing was inferred, now check the __getattr__ and
        __getattribute__ methods. Stubs don't need to be checked, because
        they don't contain any logic.
        '''
        if self.is_stub():
            return NO_VALUES

        name = compiled.create_simple_object(self.inference_state, 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 Medi 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.
        if is_big_annoying_library(self.parent_context):
            return NO_VALUES
        names = (self.get_function_slot_names(u'__getattr__')
                 or self.get_function_slot_names(u'__getattribute__'))
        return self.execute_function_slots(names, name)
Exemplo n.º 6
0
def infer_atom(context, 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.
    """
    state = context.inference_state
    if atom.type == 'name':
        if atom.value in ('True', 'False', 'None'):
            # Python 2...
            return ValueSet([compiled.builtin_from_name(state, atom.value)])

        # This is the first global lookup.
        stmt = tree.search_ancestor(
            atom, 'expr_stmt', 'lambdef'
        ) or atom
        if stmt.type == 'lambdef':
            stmt = atom
        position = stmt.start_pos
        if _is_annotation_name(atom):
            # Since Python 3.7 (with from __future__ import annotations),
            # annotations are essentially strings and can reference objects
            # that are defined further down in code. Therefore just set the
            # position to None, so the finder will not try to stop at a certain
            # position in the module.
            position = None
        return context.py__getattribute__(atom, position=position)
    elif atom.type == 'keyword':
        # For False/True/None
        if atom.value in ('False', 'True', 'None'):
            return ValueSet([compiled.builtin_from_name(state, atom.value)])
        elif atom.value == 'print':
            # print e.g. could be inferred like this in Python 2.7
            return NO_VALUES
        elif atom.value == 'yield':
            # Contrary to yield from, yield can just appear alone to return a
            # value when used with `.send()`.
            return NO_VALUES
        assert False, 'Cannot infer the keyword %s' % atom

    elif isinstance(atom, tree.Literal):
        string = state.compiled_subprocess.safe_literal_eval(atom.value)
        return ValueSet([compiled.create_simple_object(state, string)])
    elif atom.type == 'strings':
        # Will be multiple string.
        value_set = infer_atom(context, atom.children[0])
        for string in atom.children[1:]:
            right = infer_atom(context, string)
            value_set = _infer_comparison(context, value_set, u'+', right)
        return value_set
    elif atom.type == 'fstring':
        return compiled.get_string_value_set(state)
    else:
        c = atom.children
        # Parentheses without commas are not tuples.
        if c[0] == '(' and not len(c) == 2 \
                and not(c[1].type == 'testlist_comp'
                        and len(c[1].children) > 1):
            return context.infer_node(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 in ('comp_for', 'sync_comp_for'):
                return ValueSet([iterable.comprehension_from_atom(
                    state, context, atom
                )])

        # It's a dict/list/tuple literal.
        array_node = c[1]
        try:
            array_node_c = array_node.children
        except AttributeError:
            array_node_c = []
        if c[0] == '{' and (array_node == '}' or ':' in array_node_c
                            or '**' in array_node_c):
            new_value = iterable.DictLiteralValue(state, context, atom)
        else:
            new_value = iterable.SequenceLiteralValue(state, context, atom)
        return ValueSet([new_value])