diff --git a/astroid/nodes/node_ng.py b/astroid/nodes/node_ng.py index 977469df90..af2d270e1b 100644 --- a/astroid/nodes/node_ng.py +++ b/astroid/nodes/node_ng.py @@ -210,7 +210,7 @@ def __str__(self) -> str: alignment = len(cname) + 1 result = [] for field in self._other_fields + self._astroid_fields: - value = getattr(self, field) + value = getattr(self, field, "Unknown") width = 80 - len(field) - alignment lines = pprint.pformat(value, indent=2, width=width).splitlines(True) @@ -227,6 +227,11 @@ def __str__(self) -> str: def __repr__(self) -> str: rname = self.repr_name() + # The dependencies used to calculate fromlineno (if not cached) may not exist at the time + try: + lineno = self.fromlineno + except AttributeError: + lineno = 0 if rname: string = "<%(cname)s.%(rname)s l.%(lineno)s at 0x%(id)x>" else: @@ -234,7 +239,7 @@ def __repr__(self) -> str: return string % { "cname": type(self).__name__, "rname": rname, - "lineno": self.fromlineno, + "lineno": lineno, "id": id(self), } diff --git a/tests/test_nodes.py b/tests/test_nodes.py index 6303bbef28..d5c017dfc4 100644 --- a/tests/test_nodes.py +++ b/tests/test_nodes.py @@ -7,7 +7,9 @@ from __future__ import annotations import copy +import inspect import os +import random import sys import textwrap import unittest @@ -1880,3 +1882,35 @@ def return_from_match(x): inferred = node.inferred() assert len(inferred) == 2 assert [inf.value for inf in inferred] == [10, -1] + + +@pytest.mark.parametrize( + "node", + [ + node + for node in astroid.nodes.ALL_NODE_CLASSES + if node.__name__ + not in ["_BaseContainer", "BaseContainer", "NodeNG", "const_factory"] + ], +) +@pytest.mark.filterwarnings("error") +def test_str_repr_no_warnings(node): + parameters = inspect.signature(node.__init__).parameters + + args = {} + for name, param_type in parameters.items(): + if name == "self": + continue + + if "int" in param_type.annotation: + args[name] = random.randint(0, 50) + elif "NodeNG" in param_type.annotation: + args[name] = nodes.Unknown() + elif "str" in param_type.annotation: + args[name] = "" + else: + args[name] = None + + test_node = node(**args) + str(test_node) + repr(test_node)