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)
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
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
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)
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
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)
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]