ScreenPyHQ / screenpy

Screenplay pattern base for Python automated UI test suites.
MIT License
27 stars 3 forks source link

mypy doesn't like passing objects into `represent_prop` #137

Closed bandophahita closed 5 months ago

bandophahita commented 5 months ago

While building a new resolution I noticed mypy did not like the arguments type in vs returned type.

class StringContainsInOrder:
    substrings: tuple[str, ...]
    @property
    def text_to_log(self) -> str:
        return represent_prop(self.substrings)

mypy will error on this - Incompatible return value type (got "tuple[str, ...]", expected "str") [return-value]

I see the problem with the annotation, but I am at a loss for how to "fix" this nicely.

As far as I know, mypy simply doesn't like the type of pattern represent_prop has. This will mean any call to it may need to wrap cast around it to satisfy mypy.

    @property
    def text_to_log(self) -> str:
        return cast(str, represent_prop(self.substrings))
bandophahita commented 5 months ago

I found a solution. We only return mock objects as they are, so I made the code more explicit about doing so and mypy understands that.

@overload
def represent_prop(item: mock.Mock) -> mock.Mock: ...

@overload
def represent_prop(item: str | T) -> str: ...

def represent_prop(item: str | T | mock.Mock) -> str | mock.Mock:
    """Represent items in a manner suitable for the audience (logging)."""
    if isinstance(item, mock.Mock):
        return item
    if hasmethod(item, "describe_to"):
        return f"{item}"
    if isinstance(item, str):
        return repr(item)

    return f"<{item}>"