Skip to content

unittest style asserts don't have same type narrowing behaviour as normal asserts #2181

Closed as duplicate

Description

@joe-pierce

Summary

unittest-style self.assert... is not narrowing types as I'd expect.

I have just seen this diagnostic:

error[non-subscriptable]: Cannot subscript object of type `None` with no `__getitem__` method
   --> tests\test_builder.py:304:27
    |
302 |         # Assert
303 |         self.assertIsNotNone(publisher.message)
304 |         self.assertIsNone(publisher.message["ElapsedTimeMs"])
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
info: rule `non-subscriptable` is enabled by default

I would expect the self.assertIsNotNone to make line 304 valid. If I change the first like to assert publisher.message is not None then no error is flagged.

target python version: 3.12
ty version: ty 0.0.5 (d37b7db 2025-12-20)

Thanks!

Version

ty 0.0.5 (d37b7db 2025-12-20)

Activity

  1. AlexWaygood commented on Dec 23, 2025

    @AlexWaygood
    Member

    Thanks for the report!

    You haven't provided us with a minimal repro here, but I'm guessing your code looks something like this?

    import unittest
    
    def string_or_int() -> int | None:
        return 42
    
    class Foo(unittest.TestCase):
        def test_foo(self) -> None:
            x = string_or_int()
            self.assertIsNotNone(x)
            reveal_type(x)  # revealed: int | None

    If so, this is not a form of narrowing supported by any other type checker right now. I think the real solution to this is python/typing#930, which would allow typeshed to annotate the return type of methods like assertIsNotNone in such a way that all type checkers would understand their narrowing behaviour.

  2. joe-pierce commented on Dec 23, 2025

    @joe-pierce
    Author

    Yes that code snippet reflects my raised issue - sounds like a resolution to this sits outside this project so feel free to close, unless you think there may be some improvements to the returned diagnostic in the terminal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    narrowingrelated to flow-sensitive type narrowing

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions