Skip to content

Commit c1ecb1a

Browse files
committed
Extract return types for property decorator
1 parent da0d3fc commit c1ecb1a

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

pylint/pyreverse/inspector.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from pylint import constants
2323
from pylint.pyreverse import utils
24+
from pylint.pyreverse.utils import get_annotation_label
2425

2526
_WrapperFuncT = Callable[
2627
[Callable[[str], nodes.Module], str, bool], Optional[nodes.Module]
@@ -174,6 +175,51 @@ def visit_classdef(self, node: nodes.ClassDef) -> None:
174175
if not isinstance(assignattr, nodes.Unknown):
175176
self.associations_handler.handle(assignattr, node)
176177
self.handle_assignattr_type(assignattr, node)
178+
# resolve class properties
179+
properties = []
180+
for name, member_list in node.locals.items():
181+
for member in member_list:
182+
if isinstance(member, nodes.FunctionDef):
183+
# Check if this function is decorated with @property
184+
if any(
185+
isinstance(decorator, nodes.Name)
186+
and decorator.name == "property"
187+
for decorator in (
188+
member.decorators.nodes if member.decorators else []
189+
)
190+
):
191+
properties.append(member)
192+
193+
# Extract return type directly from the function definition
194+
if member.returns:
195+
# Use get_annotation_label to extract the type name
196+
annotation_label = get_annotation_label(member.returns)
197+
inferred_type = annotation_label
198+
199+
# Special handling for enum types ==> name property is always a string
200+
elif (
201+
any(base.name == "Enum" for base in node.ancestors())
202+
and name == "name"
203+
):
204+
inferred_type = "str"
205+
206+
# Fallback to inference (which may not always be perfect)
207+
else:
208+
inferred_nodes = utils.infer_node(member)
209+
inferred_type = (
210+
", ".join(str(inf) for inf in inferred_nodes if inf)
211+
if inferred_nodes
212+
else "Unknown"
213+
)
214+
215+
# Assign to instance attributes with the inferred or annotated type
216+
node.instance_attrs_type[name] = [inferred_type]
217+
print(
218+
f"Property {name} in class {node.name} has type {inferred_type}"
219+
)
220+
221+
# Add the detected properties to a new attribute for the class definition
222+
node.properties = properties
177223

178224
def visit_functiondef(self, node: nodes.FunctionDef) -> None:
179225
"""Visit an astroid.Function node.

0 commit comments

Comments
 (0)