From 35dba66b7739b8fc0b25e409ca07da9a62d9ee34 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Fri, 9 Feb 2024 12:25:24 +0100 Subject: [PATCH] Include modname in AST warnings (#2380) --- ChangeLog | 3 +++ astroid/_ast.py | 6 +++++- astroid/builder.py | 10 +++++++--- tests/test_builder.py | 12 ++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 807b2da72f..d06026c5e1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,9 @@ Release date: TBA to the ``PartialFunction`` and ``Property`` constructors have been removed (call ``postinit(doc_node=...)`` instead.) +* Include modname in AST warnings. Useful for ``invalid escape sequence`` warnings + with Python 3.12. + What's New in astroid 3.0.3? diff --git a/astroid/_ast.py b/astroid/_ast.py index c134ae70e7..44800e3829 100644 --- a/astroid/_ast.py +++ b/astroid/_ast.py @@ -22,7 +22,11 @@ class ParserModule(NamedTuple): bin_op_classes: dict[type[ast.operator], str] context_classes: dict[type[ast.expr_context], Context] - def parse(self, string: str, type_comments: bool = True) -> ast.Module: + def parse( + self, string: str, type_comments: bool = True, filename: str | None = None + ) -> ast.Module: + if filename: + return ast.parse(string, filename=filename, type_comments=type_comments) return ast.parse(string, type_comments=type_comments) diff --git a/astroid/builder.py b/astroid/builder.py index 09a787aad4..1a4c10ecfe 100644 --- a/astroid/builder.py +++ b/astroid/builder.py @@ -173,7 +173,9 @@ def _data_build( ) -> tuple[nodes.Module, rebuilder.TreeRebuilder]: """Build tree node from data and add some informations.""" try: - node, parser_module = _parse_string(data, type_comments=True) + node, parser_module = _parse_string( + data, type_comments=True, modname=modname + ) except (TypeError, ValueError, SyntaxError) as exc: raise AstroidSyntaxError( "Parsing Python code failed:\n{error}", @@ -466,11 +468,13 @@ def _extract_single_node(code: str, module_name: str = "") -> nodes.NodeNG: def _parse_string( - data: str, type_comments: bool = True + data: str, type_comments: bool = True, modname: str | None = None ) -> tuple[ast.Module, ParserModule]: parser_module = get_parser_module(type_comments=type_comments) try: - parsed = parser_module.parse(data + "\n", type_comments=type_comments) + parsed = parser_module.parse( + data + "\n", type_comments=type_comments, filename=modname + ) except SyntaxError as exc: # If the type annotations are misplaced for some reason, we do not want # to fail the entire parsing of the file, so we need to retry the parsing without diff --git a/tests/test_builder.py b/tests/test_builder.py index c025afa8a2..84ac65e099 100644 --- a/tests/test_builder.py +++ b/tests/test_builder.py @@ -416,6 +416,18 @@ def test_data_build_invalid_x_escape(self) -> None: with self.assertRaises(AstroidSyntaxError): self.builder.string_build('"\\x1"') + def test_data_build_error_filename(self) -> None: + """Check that error filename is set to modname if given.""" + with pytest.raises(AstroidSyntaxError, match="invalid escape sequence") as ctx: + self.builder.string_build("'\\d+\\.\\d+'") + assert isinstance(ctx.value.error, SyntaxError) + assert ctx.value.error.filename == "" + + with pytest.raises(AstroidSyntaxError, match="invalid escape sequence") as ctx: + self.builder.string_build("'\\d+\\.\\d+'", modname="mymodule") + assert isinstance(ctx.value.error, SyntaxError) + assert ctx.value.error.filename == "mymodule" + def test_missing_newline(self) -> None: """Check that a file with no trailing new line is parseable.""" resources.build_file("data/noendingnewline.py")