Skip to content

Support deeper-nested attribute type narrowing #2134

@pasky

Description

@pasky

Summary

Common unittest.mock patterns used in (at least my) test suite(s) produce false positives in ty, while pyright handles them correctly. This makes it difficult to type-check test files with ty.

See the full reproducer at https://play.ty.dev/d95a7a51-6af0-486d-8ebb-a3b0ca0d0ea6

1. possibly-missing-attribute after mock assignment

When a typed attribute is replaced with AsyncMock() or MagicMock(), ty still tracks the union of possible types (Unknown | OriginalType). When accessing mock-specific attributes like .assert_called(), .call_args, or .call_count on child attributes of the mock, ty reports possibly-missing-attribute because it sees the original method signature in the union.

    agent.irc_monitor.varlink_sender = AsyncMock()
    await agent.irc_monitor.varlink_sender.send_message("#test", "hello", "server")
    agent.irc_monitor.varlink_sender.send_message.assert_called()  # ty: possibly-missing-attribute

produces

warning[possibly-missing-attribute]: Attribute `assert_called` may be missing on object of type `Unknown | (bound method VarlinkSender.send_message(target: str, message: str, server: str) -> CoroutineType[Any, Any, bool])`

2. invalid-assignment for lambda stubs

Monkeypatching a method with a lambda that has a compatible but not identical signature (e.g., lambda: False vs def check_limit(self) -> bool) triggers invalid-assignment. This is a common pattern for quickly stubbing out methods in tests.

class RateLimiter:
    def check_limit(self) -> bool:
        return True
agent.irc_monitor.rate_limiter.check_limit = lambda: False  # ty: invalid-assignment

produces

error[invalid-assignment]: Object of type `() -> Unknown` is not assignable to attribute `check_limit` on type `Unknown | RateLimiter

Both of these cases work just fine with pyright (1.1.407) and I think having to exclude them manually seems unreasonable. I tried to look for some best practices around ty and tests, but didn't really find much so far...

Version

0.0.4

Metadata

Metadata

Assignees

Labels

attribute accessInstance attributes, class attributes, etc.narrowingrelated to flow-sensitive type narrowing

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions