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

Return type for PIL.Image.load #9466

Merged
merged 13 commits into from
Apr 26, 2023
Merged

Return type for PIL.Image.load #9466

merged 13 commits into from
Apr 26, 2023

Conversation

DMRobertson
Copy link
Contributor

@DMRobertson DMRobertson commented Jan 6, 2023

A first step towards #9126.

Points I wasn't sure about:

  • is this well-typed enough to be useful?
  • does the Union PixelAccess | PyAccess return value actually get us anything? E.g. perhaps a Protocol describing the common parts of these two would be more useful

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@DMRobertson DMRobertson marked this pull request as ready for review January 6, 2023 18:55
@DMRobertson DMRobertson changed the title WIP: return type for Pillow.load Return type for PIL.Image.load Jan 6, 2023
@Avasam
Copy link
Collaborator

Avasam commented Jan 6, 2023

(I am not a maintainer, I just contribute a lot here)

  1. Incomplete types are always better than flat-out wrong ones. Typeshed also generally prefers false-negatives over false-positive. So even def load(self): ... or def load(self) -> Incomplete: ... would be better than a wrong type.

  2. We tend to avoid unions in return types (see https://github.com/python/typeshed/blob/main/CONTRIBUTING.md#conventions and Document why having a union return type is often a problem mypy#1693).
    In your case you can't use an overload and you can't typeguard based on an ImportError. I think a protocol may still have variance issue (trying to assign AccessProtocol to a PyAccess for instance).
    There's a proposal that aims at solving this kind of problem: AnyOf - Union for return types typing#566

@Avasam
Copy link
Collaborator

Avasam commented Jan 14, 2023

If a solution is found for the return type. Do you think you could do all the other def load as well? Since they seem to also return the result of ImageFile.ImageFile.load or Image.Image.load?

@github-actions

This comment has been minimized.

@JelleZijlstra
Copy link
Member

@DMRobertson could you respond to Avasam's feedback?

@DMRobertson
Copy link
Contributor Author

Apologies all for the delay in responding. I have some spare time now; let me see if I can fix this up.

@DMRobertson
Copy link
Contributor Author

DMRobertson commented Apr 8, 2023

Taking a look at this with fresher eyes, I think(?) the history here is:

So I think these really are meant to be implementations of the same interface. For that reason, I think returning a protocol rather than ImplA | ImplB best captures the intent of the library.

2. I think a protocol may still have variance issue (trying to assign AccessProtocol to a PyAccess for instance).

Similarly, I think the PIL authors don't really intend for any downstream user to care about the distinction between PixelAccess and PyAccess, so I don't think what you describe is likely to be a problem in practice. (Though let's see what the primer says.)

If a solution is found for the return type. Do you think you could do all the other def load as well? Since they seem to also return the result of ImageFile.ImageFile.load or Image.Image.load?

Sure, I can add that.

@Akuli
Copy link
Collaborator

Akuli commented Apr 8, 2023

I think returning ImplA | ImplB is probably the best solution. If we add a protocol, it becomes difficult for users to use it in type annotations, but PixelAccess | PyAccess isn't too bad although it isn't great either.

A protocol can be closer to what PIL authors intended, but typeshed generally types things with a "practicality beats purity" mindset, and IMO adding a fictional protocol wouldn't be very practical.

@github-actions
Copy link
Contributor

github-actions bot commented Apr 8, 2023

According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉

Copy link
Collaborator

@Akuli Akuli left a comment

Choose a reason for hiding this comment

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

While I don't like the fictional protocol, this is a big improvement over -> None and can be improved in future PRs.

@Akuli Akuli merged commit f7443a7 into python:main Apr 26, 2023
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.

5 participants