Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use better return types #440

Merged
merged 1 commit into from
Sep 29, 2022
Merged

Use better return types #440

merged 1 commit into from
Sep 29, 2022

Conversation

cdce8p
Copy link
Contributor

@cdce8p cdce8p commented Sep 29, 2022

Small improvement. Change return types from Iterable to list. Usually it's recommend that the return type be as specific as possible since that helps with downstream typing.

Came across this issue while testing a new mypy feature with Home Assistant.

@allenporter
Copy link
Owner

Thanks. So my impression is that it if something takes an input then its still better to accept an iterable input of possible rather than a list, but for a return value being more specific/accurate is better (e.g. so you can use properties of the list)? I think i get it, thanks.

Copy link
Owner

@allenporter allenporter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As is, this reserves the right to return a more efficient return value in the future (e.g. an iterator that streams the results back, for example, rather than a list). Can you help me reason about why this is better? Did this actually fail a mypy check or do you have another specific goal in mind? Also happy if you have something to point me at with guidance on this.

@cdce8p
Copy link
Contributor Author

cdce8p commented Sep 29, 2022

So my impression is that it if something takes an input then its still better to accept an iterable input of possible rather than a list, but for a return value being more specific/accurate is better (e.g. so you can use properties of the list)?

Exactly. Input as broad as possible. I.e. Iterable allows the caller to pass any of list, tuple, set, ... . Same but in reverse for the return value -> as specific as possible. If the return type is list, it can be passed around to any function that accepts an Iterable or any abstract subclass (Collection, Sequence, ...). However an Iterable return value can only be passed to functions which also accept Iterable even though a list might be returned.

As is, this reserves the right to return a more efficient return value in the future (e.g. an iterator that streams the results back, for example, rather than a list).

Not exactly. I'd still consider changing the actual return value to be a breaking change (even if the typing would have allowed it). Typing is still optional after all. My general suggestion regarding typing is to type what you have and not what could be. The later would make it much more difficult for downstream consumers to deal with a library.

Can you help me reason about why this is better? Did this actually fail a mypy check or do you have another specific goal in mind? Also happy if you have something to point me at with guidance on this.

At the moment Home Assistant implicitly relies on the fact that no generator is returned. Especially with empty generators, the following checks would fail.

async def _async_get_recent_event_id(
    device_id: MediaId, device: Device
) -> MediaId | None:
    """Return thumbnail for most recent device event."""
    if CameraClipPreviewTrait.NAME in device.traits:
        clips = await device.event_media_manager.async_clip_preview_sessions()
        if not clips:  # <-- always false with Generator
            return None
        return MediaId(device_id.device_id, next(iter(clips)).event_token)
    images = await device.event_media_manager.async_image_sessions()
    if not images:  # <-- always false with Generator
        return None
    return MediaId(device_id.device_id, next(iter(images)).event_token)

https://github.com/home-assistant/core/blob/2022.10.0b0/homeassistant/components/nest/media_source.py#L462-L468

At the moment, I'm working on a mypy check to help detect these cases, of Iterables which can always be true, better. That's how I came across it initially. python/mypy#13762

@allenporter
Copy link
Owner

Thank you for the explanation! Very helpful.

@allenporter allenporter merged commit 73cdf82 into allenporter:main Sep 29, 2022
@allenporter
Copy link
Owner

Let me know if there is any time frame you want this in HA and I can facilitate.

@cdce8p cdce8p deleted the cdce8p-patch-1 branch September 29, 2022 15:38
@cdce8p
Copy link
Contributor Author

cdce8p commented Sep 29, 2022

Let me know if there is any time frame you want this in HA and I can facilitate.

There isn't any rush. The check hasn't been accepted into mypy yet and the next release is at least one month out. No need to do an extra release just for it.

@cdce8p
Copy link
Contributor Author

cdce8p commented Nov 13, 2022

@allenporter Sorry do bug you. The mypy PR was merged today and will be included in the next release. Just wanted to ask if you have an idea when you want to do the release. It would be awesome if it would be fixed by the time I prepare the next mypy update for Home Assistant.

@allenporter
Copy link
Owner

Thanks for the reminder: home-assistant/core#82066

@cdce8p
Copy link
Contributor Author

cdce8p commented Nov 14, 2022

Thanks for the reminder: home-assistant/core#82066

Awesome! Thank you 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants