diff --git a/tests/functional/syntax/test_structs.py b/tests/functional/syntax/test_structs.py index c2cc11324f..d34a4a6c58 100644 --- a/tests/functional/syntax/test_structs.py +++ b/tests/functional/syntax/test_structs.py @@ -594,4 +594,4 @@ def foo(): expected += "Use kwargs instead e.g. Foo(a=1, b=2)" assert len(w) == 1 - assert str(w[0].message) == expected + assert str(w[0].message).startswith(expected) diff --git a/vyper/ast/parse.py b/vyper/ast/parse.py index 4f162ac18f..99ebafd0ff 100644 --- a/vyper/ast/parse.py +++ b/vyper/ast/parse.py @@ -1,6 +1,5 @@ import ast as python_ast import tokenize -import warnings from decimal import Decimal from typing import Any, Dict, List, Optional, Union, cast @@ -11,6 +10,7 @@ from vyper.compiler.settings import Settings from vyper.exceptions import CompilerPanic, ParserException, SyntaxException from vyper.typing import ModificationOffsets +from vyper.utils import vyper_warn def parse_to_ast(*args: Any, **kwargs: Any) -> vy_ast.Module: @@ -348,7 +348,10 @@ def visit_Call(self, node): msg = "Instantiating a struct using a dictionary is deprecated " msg += "as of v0.4.0 and will be disallowed in a future release. " msg += "Use kwargs instead e.g. Foo(a=1, b=2)" - warnings.warn(msg, stacklevel=2) + + # add full_source_code so that str(VyperException(msg, node)) works + node.full_source_code = self._source_code + vyper_warn(msg, node) dict_ = node.args[0] kw_list = [] diff --git a/vyper/builtins/functions.py b/vyper/builtins/functions.py index de0158aba4..b11b9174e6 100644 --- a/vyper/builtins/functions.py +++ b/vyper/builtins/functions.py @@ -1234,7 +1234,9 @@ class SelfDestruct(BuiltinFunctionT): @process_inputs def build_IR(self, expr, args, kwargs, context): if not self._warned: - vyper_warn("`selfdestruct` is deprecated! The opcode is no longer recommended for use.") + vyper_warn( + "`selfdestruct` is deprecated! The opcode is no longer recommended for use.", expr + ) self._warned = True context.check_is_not_constant("selfdestruct", expr) @@ -1337,7 +1339,7 @@ class BitwiseAnd(BuiltinFunctionT): def _try_fold(self, node): if not self.__class__._warned: - vyper_warn("`bitwise_and()` is deprecated! Please use the & operator instead.") + vyper_warn("`bitwise_and()` is deprecated! Please use the & operator instead.", node) self.__class__._warned = True validate_call_args(node, 2) @@ -1362,7 +1364,7 @@ class BitwiseOr(BuiltinFunctionT): def _try_fold(self, node): if not self.__class__._warned: - vyper_warn("`bitwise_or()` is deprecated! Please use the | operator instead.") + vyper_warn("`bitwise_or()` is deprecated! Please use the | operator instead.", node) self.__class__._warned = True validate_call_args(node, 2) @@ -1387,7 +1389,7 @@ class BitwiseXor(BuiltinFunctionT): def _try_fold(self, node): if not self.__class__._warned: - vyper_warn("`bitwise_xor()` is deprecated! Please use the ^ operator instead.") + vyper_warn("`bitwise_xor()` is deprecated! Please use the ^ operator instead.", node) self.__class__._warned = True validate_call_args(node, 2) @@ -1412,7 +1414,7 @@ class BitwiseNot(BuiltinFunctionT): def _try_fold(self, node): if not self.__class__._warned: - vyper_warn("`bitwise_not()` is deprecated! Please use the ~ operator instead.") + vyper_warn("`bitwise_not()` is deprecated! Please use the ~ operator instead.", node) self.__class__._warned = True validate_call_args(node, 1) @@ -1438,7 +1440,7 @@ class Shift(BuiltinFunctionT): def _try_fold(self, node): if not self.__class__._warned: - vyper_warn("`shift()` is deprecated! Please use the << or >> operator instead.") + vyper_warn("`shift()` is deprecated! Please use the << or >> operator instead.", node) self.__class__._warned = True validate_call_args(node, 2) @@ -1764,7 +1766,9 @@ class CreateForwarderTo(CreateMinimalProxyTo): def build_IR(self, expr, context): if not self._warned: - vyper_warn("`create_forwarder_to` is a deprecated alias of `create_minimal_proxy_to`!") + vyper_warn( + "`create_forwarder_to` is a deprecated alias of `create_minimal_proxy_to`!", expr + ) self._warned = True return super().build_IR(expr, context) @@ -2265,7 +2269,7 @@ class Breakpoint(BuiltinFunctionT): def fetch_call_return(self, node): if not self._warned: - vyper_warn("`breakpoint` should only be used for debugging!\n" + node._annotated_source) + vyper_warn("`breakpoint` should only be used for debugging!", node) self._warned = True return None @@ -2285,7 +2289,7 @@ class Print(BuiltinFunctionT): def fetch_call_return(self, node): if not self._warned: - vyper_warn("`print` should only be used for debugging!\n" + node._annotated_source) + vyper_warn("`print` should only be used for debugging!", node) self._warned = True return None diff --git a/vyper/codegen/expr.py b/vyper/codegen/expr.py index fc8dc9393c..9da5b24469 100644 --- a/vyper/codegen/expr.py +++ b/vyper/codegen/expr.py @@ -34,7 +34,6 @@ TypeCheckFailure, TypeMismatch, UnimplementedException, - VyperException, tag_exceptions, ) from vyper.semantics.types import ( @@ -280,21 +279,15 @@ def parse_Attribute(self): return IRnode.from_list(["gas"], typ=UINT256_T) elif key == "block.prevrandao": if not version_check(begin="paris"): - warning = VyperException( - "tried to use block.prevrandao in pre-Paris " - "environment! Suggest using block.difficulty instead.", - self.expr, - ) - vyper_warn(str(warning)) + warning = "tried to use block.prevrandao in pre-Paris " + warning += "environment! Suggest using block.difficulty instead." + vyper_warn(warning, self.expr) return IRnode.from_list(["prevrandao"], typ=UINT256_T) elif key == "block.difficulty": if version_check(begin="paris"): - warning = VyperException( - "tried to use block.difficulty in post-Paris " - "environment! Suggest using block.prevrandao instead.", - self.expr, - ) - vyper_warn(str(warning)) + warning = "tried to use block.difficulty in post-Paris " + warning += "environment! Suggest using block.prevrandao instead." + vyper_warn(warning, self.expr) return IRnode.from_list(["difficulty"], typ=UINT256_T) elif key == "block.timestamp": return IRnode.from_list(["timestamp"], typ=UINT256_T) diff --git a/vyper/utils.py b/vyper/utils.py index 26869a6def..a7ca1bd441 100644 --- a/vyper/utils.py +++ b/vyper/utils.py @@ -9,7 +9,7 @@ import warnings from typing import Generic, List, TypeVar, Union -from vyper.exceptions import CompilerPanic, DecimalOverrideException, InvalidLiteral +from vyper.exceptions import CompilerPanic, DecimalOverrideException, InvalidLiteral, VyperException _T = TypeVar("_T") @@ -208,8 +208,11 @@ def trace(n=5, out=sys.stderr): # print a warning -def vyper_warn(msg, prefix="Warning: ", file_=sys.stderr): - print(f"{prefix}{msg}", file=file_) +def vyper_warn(msg, node=None): + if node is not None: + # use VyperException for its formatting abilities + msg = str(VyperException(msg, node)) + warnings.warn(msg, stacklevel=2) # converts a signature like Func(bool,uint256,address) to its 4 byte method ID