Union-attr method chaining #1118
-
I am trying to use mypy strict whilst chaining calls to class attributes/methods, each of which is returning a union type, e.g. div: bs4.Tag #some beautifulsoup div
if element := div.find(text='sometext'): # has type Tag
# mypy fails due to union-attr
text = element.parent.next_sibling.text
# mypy passes, only works in this case because all are Optional. Other Unions wouldn't work
if parent := element.parent:
if parent_sibing := parent.next_sibling:
text = parent_sibling.text
# mypy passes, works regardless of the Union return
text = cast(bs4.Tag, cast(bs4.Tag, element.parent).next_sibling).text mypy will complain here as the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
In our codebase we have this helper function: from typing import TypeVar, Optional
T = TypeVar("T")
def not_none(obj: Optional[T], *, message: Optional[str] = None) -> T:
"""Check that obj is not None. Raises TypeError if it is.
This is meant to help get code to type check that uses Optional types.
"""
if obj is None:
if message is not None:
raise TypeError(message)
raise TypeError("object is unexpectedly None")
return obj In your code, you'd write |
Beta Was this translation helpful? Give feedback.
In our codebase we have this helper function:
In your code, you'd write
text = not_none(not_none(element).parent).next_sibling.text
. This satisfies the type checker and also allows you to give a nice error message if the object happens to be None at runtime.