Skip to content

Commit 7cc47ef

Browse files
committed
attach classes to their parent; fix bugs uncovered by this
1. some '__doc__' fields of standard library symbols (e.g. WrapperDescriptorType.__doc__) don't return a string, they return a 'getset_descriptor'. Thus, an attempt to print "as string" fails. The solution is to check that __doc__ is an instance of str. 2. A "temporary_class" was attached to a function node, when it shouldn't have been. The solution is to reattach it to the adhoc module.
1 parent e33b04a commit 7cc47ef

File tree

3 files changed

+27
-16
lines changed

3 files changed

+27
-16
lines changed

astroid/nodes/node_classes.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
"""Module for some node classes. More nodes in scoped_nodes.py"""
66

7+
# isort: off
8+
79
from __future__ import annotations
810

911
import abc
@@ -2061,7 +2063,14 @@ def __init__(
20612063
:param end_col_offset: The end column this node appears on in the
20622064
source code. Note: This is after the last symbol.
20632065
"""
2064-
self.value: Any = value
2066+
if getattr(value, "__name__", None) == "__doc__":
2067+
raise AssertionError( # pragma: no cover
2068+
"You have most likely called a __doc__ field of some object "
2069+
"and it didn't return a string. "
2070+
"That happens to some symbols from the standard library. "
2071+
"Check for isinstance(<X>.__doc__, str)."
2072+
)
2073+
self.value = value
20652074
"""The value that the constant represents."""
20662075

20672076
self.kind: str | None = kind # can be None

astroid/nodes/scoped_nodes/scoped_nodes.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ def function_to_method(n, klass):
179179
return n
180180

181181

182+
def attach_to_parent(node: NodeNG, name: str, parent: NodeNG):
183+
frame = parent.frame()
184+
frame.set_local(name, node)
185+
if frame is parent:
186+
frame._append_node(node)
187+
188+
182189
class Module(LocalsDictNodeNG):
183190
"""Class representing an :class:`ast.Module` node.
184191
@@ -1168,10 +1175,7 @@ def __init__(
11681175
parent=parent,
11691176
)
11701177
if parent:
1171-
frame = parent.frame()
1172-
frame.set_local(name, self)
1173-
if frame is parent:
1174-
frame._append_node(self)
1178+
attach_to_parent(self, name, parent)
11751179

11761180
def postinit(
11771181
self,
@@ -1627,7 +1631,7 @@ def infer_call_result(
16271631
col_offset=0,
16281632
end_lineno=0,
16291633
end_col_offset=0,
1630-
parent=self,
1634+
parent=AstroidManager().adhoc_module,
16311635
)
16321636
new_class.hide = True
16331637
new_class.postinit(
@@ -1939,7 +1943,7 @@ def __init__(
19391943
parent=parent,
19401944
)
19411945
if parent:
1942-
parent.frame().set_local(name, self)
1946+
attach_to_parent(self, name, parent)
19431947

19441948
for local_name, node in self.implicit_locals():
19451949
self.add_local_node(node, local_name)

astroid/raw_building.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ def _add_dunder_class(func, parent: nodes.NodeNG, member) -> None:
5656
if not cls_name:
5757
return
5858
cls_bases = [ancestor.__name__ for ancestor in python_cls.__bases__]
59-
ast_klass = build_class(cls_name, parent, cls_bases, python_cls.__doc__)
59+
doc = python_cls.__doc__ if isinstance(python_cls.__doc__, str) else None
60+
ast_klass = build_class(cls_name, parent, cls_bases, doc)
6061
func.instance_attrs["__class__"] = [ast_klass]
6162

6263

@@ -321,7 +322,7 @@ def object_build_function(
321322
args,
322323
posonlyargs,
323324
defaults,
324-
member.__doc__,
325+
member.__doc__ if isinstance(member.__doc__, str) else None,
325326
kwonlyargs=kwonlyargs,
326327
kwonlydefaults=kwonly_defaults,
327328
)
@@ -359,12 +360,8 @@ def _base_class_object_build(
359360
"""
360361
class_name = name or getattr(member, "__name__", None) or localname
361362
assert isinstance(class_name, str)
362-
klass = build_class(
363-
class_name,
364-
node,
365-
basenames,
366-
member.__doc__,
367-
)
363+
doc = member.__doc__ if isinstance(member.__doc__, str) else None
364+
klass = build_class(class_name, node, basenames, doc)
368365
klass._newstyle = isinstance(member, type)
369366
try:
370367
# limit the instantiation trick since it's too dangerous
@@ -713,11 +710,12 @@ def _astroid_bootstrapping() -> None:
713710
end_col_offset=0,
714711
parent=astroid_builtin,
715712
)
713+
doc = _type.__doc__ if isinstance(_type.__doc__, str) else None
716714
klass.postinit(
717715
bases=[],
718716
body=[],
719717
decorators=None,
720-
doc_node=nodes.Const(value=_type.__doc__) if _type.__doc__ else None,
718+
doc_node=nodes.Const(doc) if doc else None,
721719
)
722720
builder.object_build(klass, _type)
723721
astroid_builtin[_type.__name__] = klass

0 commit comments

Comments
 (0)