Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion mypy/checkmember.py
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,18 @@ def analyze_var(
):
# Unwrap nonmember similar to class-level access
result = p_result.args[0]
if result and not (implicit or var.info.is_protocol and is_instance_var(var)):
dataclass_metadata = var.info.metadata.get("dataclass", {})
is_dataclass_field = any(
attribute.get("name") == name for attribute in dataclass_metadata.get("attributes", [])
)
# A read-only property has already applied descriptor access to its getter
# result. Dataclass fields are represented as synthetic properties, but
# their descriptor access still needs to happen on instance reads.
if (
result
and not (var.is_property and not var.is_settable_property and not is_dataclass_field)
and not (implicit or var.info.is_protocol and is_instance_var(var))
):
result = analyze_descriptor_access(result, mx)
if hook:
result = hook(
Expand Down
29 changes: 29 additions & 0 deletions test-data/unit/check-classes.test
Original file line number Diff line number Diff line change
Expand Up @@ -9727,3 +9727,32 @@ def f() -> None:
class X:
...
undefined # E: Name "undefined" is not defined

[case testPropertyReturningFunctionType]
from types import FunctionType

class FuncWrap:
def __init__(self, func: object) -> None:
if not isinstance(func, FunctionType):
raise TypeError()
self._func = func

@property
def __func__(self) -> FunctionType:
return self._func

def good() -> int:
return 1

wrapped = FuncWrap(good)
assert isinstance(wrapped.__func__, FunctionType)
[builtins fixtures/property-function.pyi]
[file types.pyi]
from typing import final

@final
class FunctionType:
def __get__(self, instance: object, owner: type | None = ...) -> MethodType: ...

@final
class MethodType: ...
22 changes: 22 additions & 0 deletions test-data/unit/fixtures/property-function.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Any

class object:
def __init__(self) -> None: ...

class type:
def __init__(self, x: Any) -> None: ...

class property:
def __init__(self, fget: Any = ...) -> None: ...

class BaseException: ...
class Exception(BaseException): ...
class TypeError(Exception): ...

class int: ...
class str: ...
class dict: ...
class tuple: ...
class ellipsis: ...

def isinstance(x: object, t: Any) -> bool: ...
Loading