Skip to content

Consider allowing assertIsNotNone() to constitute a None check #2007

Closed

Description

@jparise

Is your feature request related to a problem? Please describe.

It's common for unit tests (based on unittest) to assert that an object is non-None and then verify some of its attributes.

def test_object(self):
    obj = load_object_by_name('name')  # type: Optional[Object]
    self.assertIsNotNone(obj)
    self.assertEqual('name', obj.name)

Pyright will flag that last line for reportOptionalMemberAccess, even though we've performed an (implied) "is not None" check via assertIsNotNone.

There are three workarounds:

Somewhat redundant

def test_object(self):
    obj = load_object_by_name('name')  # type: Optional[Object]
    self.assertIsNotNone(obj)
    if obj is not None:
        self.assertEqual('name', obj.name)

Very redundant

def test_object(self):
    obj = load_object_by_name('name')  # type: Optional[Object]
    self.assertIsNotNone(obj)
    assert is not None
    self.assertEqual('name', obj.name)

Tricky but concise

def test_object(self):
    obj = load_object_by_name('name')  # type: Optional[Object]
    self.assertIsNotNone(obj)
    self.assertEqual('name', obj and obj.name)

Describe the solution you'd like

Because unittest is part of the standard library, it would be convenient if calling assertIsNotNone (and assertIsNone) would be constitute a None check from the type checker's perspective.

Additional context

It might be too magical to apply special treatment to these methods. Perhaps there should (eventually) be a generalized typing facility that assertIsNone/assertIsNotNone could adopt, a la TypeGuard.

Activity

  1. erictraut commented on Jun 18, 2021

    @erictraut
    Collaborator

    We generally don't hard code any knowledge of specific functions or methods. It's just not a scalable approach to type checking. Type information should come from the type stubs, even for stdlib methods.

    In my code, I've worked around this by switching from assertIsNotNone to assert is not None. Another option is to disable the reportOptionalMemberAccess diagnostic check in your test files using a # pyright: reportOptionalMemberAccess=false comment at the top of the file.

    We have made exceptions to the above principle in very rare cases but only after we received significant signal from pyright/pylance users. I'm going to close this issue for now, but we can consider reopening it in the future if it receives a bunch of upvotes or additional requests.

  2. 1kastner commented on Aug 23, 2022

    @1kastner

    Well, this issue arises at different corners of GitHub, see also python/typeshed#8583 and the issues mentioned therein. People are still in need of this feature :)

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions