Skip to content

Commit 17387a5

Browse files
DanielNoordcdce8p
andauthored
Pass doc_node to postinit of all PartialFunction constructors (#1437)
Co-authored-by: Marc Mueller <[email protected]>
1 parent 40e1a64 commit 17387a5

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

astroid/brain/brain_functools.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
"""Astroid hooks for understanding functools library module."""
88
from functools import partial
99
from itertools import chain
10+
from typing import Iterator, Optional
1011

11-
from astroid import BoundMethod, arguments, extract_node, helpers, objects
12+
from astroid import BoundMethod, arguments, extract_node, helpers, nodes, objects
13+
from astroid.context import InferenceContext
1214
from astroid.exceptions import InferenceError, UseInferenceDefault
1315
from astroid.inference_tip import inference_tip
1416
from astroid.interpreter import objectmodel
@@ -62,7 +64,9 @@ def _transform_lru_cache(node, context=None) -> None:
6264
node.special_attributes = LruWrappedModel()(node)
6365

6466

65-
def _functools_partial_inference(node, context=None):
67+
def _functools_partial_inference(
68+
node: nodes.Call, context: Optional[InferenceContext] = None
69+
) -> Iterator[objects.PartialFunction]:
6670
call = arguments.CallSite.from_call(node, context=context)
6771
number_of_positional = len(call.positional_arguments)
6872
if number_of_positional < 1:
@@ -101,7 +105,6 @@ def _functools_partial_inference(node, context=None):
101105
partial_function = objects.PartialFunction(
102106
call,
103107
name=inferred_wrapped_function.name,
104-
doc=inferred_wrapped_function.doc,
105108
lineno=inferred_wrapped_function.lineno,
106109
col_offset=inferred_wrapped_function.col_offset,
107110
parent=node.parent,
@@ -113,6 +116,7 @@ def _functools_partial_inference(node, context=None):
113116
returns=inferred_wrapped_function.returns,
114117
type_comment_returns=inferred_wrapped_function.type_comment_returns,
115118
type_comment_args=inferred_wrapped_function.type_comment_args,
119+
doc_node=inferred_wrapped_function.doc_node,
116120
)
117121
return iter((partial_function,))
118122

astroid/objects.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ class PartialFunction(scoped_nodes.FunctionDef):
269269
def __init__(
270270
self, call, name=None, doc=None, lineno=None, col_offset=None, parent=None
271271
):
272+
# TODO: Pass end_lineno and end_col_offset as well
272273
super().__init__(name, doc, lineno, col_offset, parent=None)
273274
# A typical FunctionDef automatically adds its name to the parent scope,
274275
# but a partial should not, so defer setting parent until after init

tests/unittest_brain.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,30 @@ def test_infer_dict_from_keys() -> None:
29942994

29952995

29962996
class TestFunctoolsPartial:
2997+
@staticmethod
2998+
def test_infer_partial() -> None:
2999+
ast_node = astroid.extract_node(
3000+
"""
3001+
from functools import partial
3002+
def test(a, b):
3003+
'''Docstring'''
3004+
return a + b
3005+
partial(test, 1)(3) #@
3006+
"""
3007+
)
3008+
assert isinstance(ast_node.func, nodes.Call)
3009+
inferred = ast_node.func.inferred()
3010+
assert len(inferred) == 1
3011+
partial = inferred[0]
3012+
assert isinstance(partial, objects.PartialFunction)
3013+
assert isinstance(partial.doc_node, nodes.Const)
3014+
assert partial.doc_node.value == "Docstring"
3015+
with pytest.warns(DeprecationWarning) as records:
3016+
assert partial.doc == "Docstring"
3017+
assert len(records) == 1
3018+
assert partial.lineno == 3
3019+
assert partial.col_offset == 0
3020+
29973021
def test_invalid_functools_partial_calls(self) -> None:
29983022
ast_nodes = astroid.extract_node(
29993023
"""

0 commit comments

Comments
 (0)