Ejemplo n.º 1
0
def test_subscript_negative(build_node, namespace):
    node = build_node("foo[-1]")
    type_def = Int128Definition()

    namespace["foo"] = ArrayDefinition(type_def, 3)
    with pytest.raises(ArrayIndexException):
        get_possible_types_from_node(node)
Ejemplo n.º 2
0
def get_type_from_abi(
    abi_type: Dict,
    location: DataLocation = DataLocation.UNSET,
    is_constant: bool = False,
    is_public: bool = False,
) -> BaseTypeDefinition:
    """
    Return a type object from an ABI type definition.

    Arguments
    ---------
    abi_type : Dict
       A type definition taken from the `input` or `output` field of an ABI.

    Returns
    -------
    BaseTypeDefinition
        Type definition object.
    """
    type_string = abi_type["type"]
    if type_string == "fixed168x10":
        type_string = "decimal"
    if type_string in ("string", "bytes"):
        type_string = type_string.capitalize()

    namespace = get_namespace()

    if "[" in type_string:
        value_type_string, length_str = type_string.rsplit("[", maxsplit=1)
        try:
            length = int(length_str.rstrip("]"))
        except ValueError:
            raise UnknownType(
                f"ABI type has an invalid length: {type_string}") from None
        try:
            value_type = get_type_from_abi({"type": value_type_string},
                                           location=location,
                                           is_constant=is_constant)
        except UnknownType:
            raise UnknownType(
                f"ABI contains unknown type: {type_string}") from None
        try:
            return ArrayDefinition(value_type,
                                   length,
                                   location=location,
                                   is_constant=is_constant,
                                   is_public=is_public)
        except InvalidType:
            raise UnknownType(
                f"ABI contains unknown type: {type_string}") from None

    else:
        try:
            return namespace[type_string]._type(location=location,
                                                is_constant=is_constant,
                                                is_public=is_public)
        except KeyError:
            raise UnknownType(
                f"ABI contains unknown type: {type_string}") from None
Ejemplo n.º 3
0
def get_type_from_annotation(
    node: vy_ast.VyperNode,
    location: DataLocation,
    is_constant: bool = False,
    is_public: bool = False,
    is_immutable: bool = False,
) -> BaseTypeDefinition:
    """
    Return a type object for the given AST node.

    Arguments
    ---------
    node : VyperNode
        Vyper ast node from the `annotation` member of a `VariableDef` or `AnnAssign` node.

    Returns
    -------
    BaseTypeDefinition
        Type definition object.
    """
    namespace = get_namespace()

    if isinstance(node, vy_ast.Tuple):
        values = node.elements
        types = tuple(
            get_type_from_annotation(v, DataLocation.UNSET) for v in values)
        return TupleDefinition(types)

    try:
        # get id of leftmost `Name` node from the annotation
        type_name = next(
            i.id for i in node.get_descendants(vy_ast.Name, include_self=True))
    except StopIteration:
        raise StructureException("Invalid syntax for type declaration", node)
    try:
        type_obj = namespace[type_name]
    except UndeclaredDefinition:
        suggestions_str = get_levenshtein_error_suggestions(
            type_name, namespace, 0.3)
        raise UnknownType(
            f"No builtin or user-defined type named '{type_name}'. {suggestions_str}",
            node) from None

    if (getattr(type_obj, "_as_array", False)
            and isinstance(node, vy_ast.Subscript)
            and node.value.get("id") != "DynArray"):
        # TODO: handle `is_immutable` for arrays
        # if type can be an array and node is a subscript, create an `ArrayDefinition`
        length = get_index_value(node.slice)
        value_type = get_type_from_annotation(node.value, location,
                                              is_constant, False, is_immutable)
        return ArrayDefinition(value_type, length, location, is_constant,
                               is_public, is_immutable)

    try:
        return type_obj.from_annotation(node, location, is_constant, is_public,
                                        is_immutable)
    except AttributeError:
        raise InvalidType(f"'{type_name}' is not a valid type", node) from None
Ejemplo n.º 4
0
    def types_from_List(self, node):
        # literal array
        if not node.elements:
            raise InvalidLiteral("Cannot have an empty array", node)

        types_list = get_common_types(*node.elements)
        if types_list:
            return [ArrayDefinition(i, len(node.elements)) for i in types_list]

        raise InvalidLiteral("Array contains multiple, incompatible types",
                             node)
Ejemplo n.º 5
0
def get_type_from_annotation(
    node: vy_ast.VyperNode,
    location: DataLocation,
    is_immutable: bool = False,
    is_public: bool = False,
) -> BaseTypeDefinition:
    """
    Return a type object for the given AST node.

    Arguments
    ---------
    node : VyperNode
        Vyper ast node from the `annotation` member of an `AnnAssign` node.

    Returns
    -------
    BaseTypeDefinition
        Type definition object.
    """
    namespace = get_namespace()
    try:
        # get id of leftmost `Name` node from the annotation
        type_name = next(
            i.id for i in node.get_descendants(vy_ast.Name, include_self=True))
    except StopIteration:
        raise StructureException("Invalid syntax for type declaration", node)
    try:
        type_obj = namespace[type_name]
    except UndeclaredDefinition:
        raise UnknownType(
            f"No builtin or user-defined type named '{type_name}'",
            node) from None

    if getattr(type_obj, "_as_array", False) and isinstance(
            node, vy_ast.Subscript):
        # if type can be an array and node is a subscript, create an `ArrayDefinition`
        length = get_index_value(node.slice)
        value_type = get_type_from_annotation(node.value, location,
                                              is_immutable, False)
        return ArrayDefinition(value_type, length, location, is_immutable,
                               is_public)

    try:
        return type_obj.from_annotation(node, location, is_immutable,
                                        is_public)
    except AttributeError:
        raise InvalidType(f"'{type_name}' is not a valid type", node) from None
Ejemplo n.º 6
0
    def types_from_List(self, node):
        # literal array

        if not node.elements:
            # empty list literal `[]`
            # subtype can be anything
            types_list = types.get_types()
            # 1 is minimum possible length for dynarray, assignable to anything
            ret = [DynamicArrayDefinition(t, 1) for t in types_list]
            return ret

        types_list = get_common_types(*node.elements)

        if len(types_list) > 0:
            count = len(node.elements)
            ret = []
            ret.extend([ArrayDefinition(t, count) for t in types_list])
            ret.extend([DynamicArrayDefinition(t, count) for t in types_list])
            return ret

        raise InvalidLiteral("Array contains multiple, incompatible types",
                             node)
Ejemplo n.º 7
0
def test_subscript(build_node, namespace):
    node = build_node("foo[1]")
    type_def = Int128Definition()

    namespace["foo"] = ArrayDefinition(type_def, 3)
    assert get_possible_types_from_node(node) == [type_def]