Example #1
0
def infer_isinstance(callnode, context=None):
    """Infer isinstance calls

    :param nodes.Call callnode: an isinstance call
    :param InferenceContext: context for call
        (currently unused but is a common interface for inference)
    :rtype nodes.Const: Boolean Const value of isinstance call

    :raises UseInferenceDefault: If the node cannot be inferred
    """
    call = arguments.CallSite.from_call(callnode)
    if call.keyword_arguments:
        # isinstance doesn't support keyword arguments
        raise UseInferenceDefault(
            "TypeError: isinstance() takes no keyword arguments")
    if len(call.positional_arguments) != 2:
        raise UseInferenceDefault("Expected two arguments, got {count}".format(
            count=len(call.positional_arguments)))
    # The left hand argument is the obj to be checked
    obj_node, class_or_tuple_node = call.positional_arguments
    # The right hand argument is the class(es) that the given
    # obj is to be check is an instance of
    try:
        class_container = _class_or_tuple_to_container(class_or_tuple_node,
                                                       context=context)
    except InferenceError:
        raise UseInferenceDefault
    try:
        isinstance_bool = helpers.object_isinstance(obj_node, class_container,
                                                    context)
    except AstroidTypeError as exc:
        raise UseInferenceDefault("TypeError: " + str(exc))
    except MroError as exc:
        raise UseInferenceDefault from exc
    if isinstance_bool is util.Uninferable:
        raise UseInferenceDefault
    return nodes.Const(isinstance_bool)
Example #2
0
    def infer_objects_get_as_a(call_node, context=None):
        if getattr(call_node.func, "attrname") != 'get':
            raise UseInferenceDefault()

        code = """\
class A(object):
    class objects(object):
        @staticmethod
        def get():
            pass
    def save():
        pass"""
        m = astroid.parse(code, 'infer.this')
        class_node = m.body[0]

        return iter((class_node.instantiate_class(),))
Example #3
0
def _find_func_form_arguments(node, context):
    args = node.args
    keywords = node.keywords

    if args and len(args) == 2:
        name = _infer_first(node.args[0], context).value
        names = _infer_first(node.args[1], context)

        return name, names
    elif keywords:
        found_keywords = {keyword.arg: keyword.value for keyword in keywords}
        if {'field_names', 'typename'}.issubset(found_keywords.keys()):
            name = _infer_first(found_keywords['typename'], context).value
            names = _infer_first(found_keywords['field_names'], context)
            return name, names
    raise UseInferenceDefault()
def infer_dict(node, context=None):
    """Try to infer a dict call to a Dict node.

    The function treats the following cases:

        * dict()
        * dict(mapping)
        * dict(iterable)
        * dict(iterable, **kwargs)
        * dict(mapping, **kwargs)
        * dict(**kwargs)

    If a case can't be inferred, we'll fallback to default inference.
    """
    call = arguments.CallSite.from_call(node, context=context)
    if call.has_invalid_arguments() or call.has_invalid_keywords():
        raise UseInferenceDefault

    args = call.positional_arguments
    kwargs = list(call.keyword_arguments.items())

    if not args and not kwargs:
        # dict()
        return nodes.Dict()
    elif kwargs and not args:
        # dict(a=1, b=2, c=4)
        items = [(nodes.Const(key), value) for key, value in kwargs]
    elif len(args) == 1 and kwargs:
        # dict(some_iterable, b=2, c=4)
        elts = _get_elts(args[0], context)
        keys = [(nodes.Const(key), value) for key, value in kwargs]
        items = elts + keys
    elif len(args) == 1:
        items = _get_elts(args[0], context)
    else:
        raise UseInferenceDefault()

    value = nodes.Dict(col_offset=node.col_offset,
                       lineno=node.lineno,
                       parent=node.parent)
    value.postinit(items)
    return value
Example #5
0
def _find_func_form_arguments(node, context):
    def _extract_namedtuple_arg_or_keyword(position, key_name=None):

        if len(args) > position:
            return _infer_first(args[position], context)
        if key_name and key_name in found_keywords:
            return _infer_first(found_keywords[key_name], context)

    args = node.args
    keywords = node.keywords
    found_keywords = ({keyword.arg: keyword.value
                       for keyword in keywords} if keywords else {})

    name = _extract_namedtuple_arg_or_keyword(position=0, key_name="typename")
    names = _extract_namedtuple_arg_or_keyword(position=1,
                                               key_name="field_names")
    if name and names:
        return name.value, names

    raise UseInferenceDefault()
def _container_generic_inference(node, context, node_type, transform):
    args = node.args
    if not args:
        return node_type()
    if len(node.args) > 1:
        raise UseInferenceDefault()

    (arg, ) = args
    transformed = transform(arg)
    if not transformed:
        try:
            inferred = next(arg.infer(context=context))
        except (InferenceError, StopIteration) as exc:
            raise UseInferenceDefault from exc
        if inferred is util.Uninferable:
            raise UseInferenceDefault
        transformed = transform(inferred)
    if not transformed or transformed is util.Uninferable:
        raise UseInferenceDefault
    return transformed
Example #7
0
def infer_type_sub(node, context=None):
    """
    Infer a type[...] subscript

    :param node: node to infer
    :type node: astroid.node_classes.NodeNG
    :param context: inference context
    :type context: astroid.context.InferenceContext
    :return: the inferred node
    :rtype: nodes.NodeNG
    """
    node_scope, _ = node.scope().lookup("type")
    if node_scope.qname() != "builtins":
        raise UseInferenceDefault()
    class_src = """
    class type:
        def __class_getitem__(cls, key):
            return cls
     """
    node = extract_node(class_src)
    return node.infer(context=context)
Example #8
0
def _container_generic_transform(arg, klass, iterables, build_elts):
    if isinstance(arg, klass):
        return arg
    elif isinstance(arg, iterables):
        if all(isinstance(elt, nodes.Const) for elt in arg.elts):
            elts = [elt.value for elt in arg.elts]
        else:
            # TODO: Does not handle deduplication for sets.
            elts = filter(None, map(helpers.safe_infer, arg.elts))
    elif isinstance(arg, nodes.Dict):
        # Dicts need to have consts as strings already.
        if not all(isinstance(elt[0], nodes.Const) for elt in arg.items):
            raise UseInferenceDefault()
        elts = [item[0].value for item in arg.items]
    elif isinstance(arg, nodes.Const) and isinstance(
        arg.value, (six.string_types, six.binary_type)
    ):
        elts = arg.value
    else:
        return
    return klass.from_elements(elts=build_elts(elts))
Example #9
0
def infer_func_form(node, base_type, context=None, enum=False):
    """Specific inference function for namedtuple or Python 3 enum. """
    # node is a Call node, class name as first argument and generated class
    # attributes as second argument

    # namedtuple or enums list of attributes can be a list of strings or a
    # whitespace-separate string
    try:
        name, names = _find_func_form_arguments(node, context)
        try:
            attributes = names.value.replace(",", " ").split()
        except AttributeError:
            if not enum:
                attributes = [
                    _infer_first(const, context).value for const in names.elts
                ]
            else:
                # Enums supports either iterator of (name, value) pairs
                # or mappings.
                if hasattr(names, "items") and isinstance(names.items, list):
                    attributes = [
                        _infer_first(const[0], context).value
                        for const in names.items
                        if isinstance(const[0], nodes.Const)
                    ]
                elif hasattr(names, "elts"):
                    # Enums can support either ["a", "b", "c"]
                    # or [("a", 1), ("b", 2), ...], but they can't
                    # be mixed.
                    if all(
                            isinstance(const, nodes.Tuple)
                            for const in names.elts):
                        attributes = [
                            _infer_first(const.elts[0], context).value
                            for const in names.elts
                            if isinstance(const, nodes.Tuple)
                        ]
                    else:
                        attributes = [
                            _infer_first(const, context).value
                            for const in names.elts
                        ]
                else:
                    raise AttributeError
                if not attributes:
                    raise AttributeError
    except (AttributeError, exceptions.InferenceError):
        raise UseInferenceDefault()

    attributes = [attr for attr in attributes if " " not in attr]

    # If we can't infer the name of the class, don't crash, up to this point
    # we know it is a namedtuple anyway.
    name = name or "Uninferable"
    # we want to return a Class node instance with proper attributes set
    class_node = nodes.ClassDef(name, "docstring")
    class_node.parent = node.parent
    # set base class=tuple
    class_node.bases.append(base_type)
    # XXX add __init__(*attributes) method
    for attr in attributes:
        fake_node = nodes.EmptyNode()
        fake_node.parent = class_node
        fake_node.attrname = attr
        class_node.instance_attrs[attr] = [fake_node]
    return class_node, name, attributes
def infer_dict_fromkeys(node, context=None):
    """Infer dict.fromkeys

    :param nodes.Call node: dict.fromkeys() call to infer
    :param context.InferenceContext: node context
    :rtype nodes.Dict:
        a Dictionary containing the values that astroid was able to infer.
        In case the inference failed for any reason, an empty dictionary
        will be inferred instead.
    """
    def _build_dict_with_elements(elements):
        new_node = nodes.Dict(col_offset=node.col_offset,
                              lineno=node.lineno,
                              parent=node.parent)
        new_node.postinit(elements)
        return new_node

    call = arguments.CallSite.from_call(node, context=context)
    if call.keyword_arguments:
        raise UseInferenceDefault(
            "TypeError: int() must take no keyword arguments")
    if len(call.positional_arguments) not in {1, 2}:
        raise UseInferenceDefault(
            "TypeError: Needs between 1 and 2 positional arguments")

    default = nodes.Const(None)
    values = call.positional_arguments[0]
    try:
        inferred_values = next(values.infer(context=context))
    except InferenceError:
        return _build_dict_with_elements([])
    if inferred_values is util.Uninferable:
        return _build_dict_with_elements([])

    # Limit to a couple of potential values, as this can become pretty complicated
    accepted_iterable_elements = (nodes.Const, )
    if isinstance(inferred_values, (nodes.List, nodes.Set, nodes.Tuple)):
        elements = inferred_values.elts
        for element in elements:
            if not isinstance(element, accepted_iterable_elements):
                # Fallback to an empty dict
                return _build_dict_with_elements([])

        elements_with_value = [(element, default) for element in elements]
        return _build_dict_with_elements(elements_with_value)

    elif isinstance(inferred_values, nodes.Const) and isinstance(
            inferred_values.value, (str, bytes)):
        elements = [(nodes.Const(element), default)
                    for element in inferred_values.value]
        return _build_dict_with_elements(elements)
    elif isinstance(inferred_values, nodes.Dict):
        keys = inferred_values.itered()
        for key in keys:
            if not isinstance(key, accepted_iterable_elements):
                # Fallback to an empty dict
                return _build_dict_with_elements([])

        elements_with_value = [(element, default) for element in keys]
        return _build_dict_with_elements(elements_with_value)

    # Fallback to an empty dictionary
    return _build_dict_with_elements([])
Example #11
0
def infer_func_form(node, base_type, context=None, enum=False):
    """Specific inference function for namedtuple or Python 3 enum. """
    def infer_first(node):
        if node is util.Uninferable:
            raise UseInferenceDefault
        try:
            value = next(node.infer(context=context))
            if value is util.Uninferable:
                raise UseInferenceDefault()
            else:
                return value
        except StopIteration:
            raise InferenceError()

    # node is a Call node, class name as first argument and generated class
    # attributes as second argument
    if len(node.args) != 2:
        # something weird here, go back to class implementation
        raise UseInferenceDefault()
    # namedtuple or enums list of attributes can be a list of strings or a
    # whitespace-separate string
    try:
        name = infer_first(node.args[0]).value
        names = infer_first(node.args[1])
        try:
            attributes = names.value.replace(',', ' ').split()
        except AttributeError:
            if not enum:
                attributes = [infer_first(const).value for const in names.elts]
            else:
                # Enums supports either iterator of (name, value) pairs
                # or mappings.
                # TODO: support only list, tuples and mappings.
                if hasattr(names, 'items') and isinstance(names.items, list):
                    attributes = [
                        infer_first(const[0]).value for const in names.items
                        if isinstance(const[0], nodes.Const)
                    ]
                elif hasattr(names, 'elts'):
                    # Enums can support either ["a", "b", "c"]
                    # or [("a", 1), ("b", 2), ...], but they can't
                    # be mixed.
                    if all(
                            isinstance(const, nodes.Tuple)
                            for const in names.elts):
                        attributes = [
                            infer_first(const.elts[0]).value
                            for const in names.elts
                            if isinstance(const, nodes.Tuple)
                        ]
                    else:
                        attributes = [
                            infer_first(const).value for const in names.elts
                        ]
                else:
                    raise AttributeError
                if not attributes:
                    raise AttributeError
    except (AttributeError, exceptions.InferenceError):
        raise UseInferenceDefault()
    # we want to return a Class node instance with proper attributes set
    class_node = nodes.ClassDef(name, 'docstring')
    class_node.parent = node.parent
    # set base class=tuple
    class_node.bases.append(base_type)
    # XXX add __init__(*attributes) method
    for attr in attributes:
        fake_node = nodes.EmptyNode()
        fake_node.parent = class_node
        fake_node.attrname = attr
        class_node.instance_attrs[attr] = [fake_node]
    return class_node, name, attributes