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

Fully annotate ExifRead #9403

Merged
merged 11 commits into from
Dec 27, 2022
Merged

Fully annotate ExifRead #9403

merged 11 commits into from
Dec 27, 2022

Conversation

srittau
Copy link
Collaborator

@srittau srittau commented Dec 23, 2022

No description provided.

@github-actions

This comment has been minimized.

@srittau
Copy link
Collaborator Author

srittau commented Dec 23, 2022

For reference, there are potential type problems, which I reported here: ianare/exif-py#172.

stubs/ExifRead/exifread/__init__.pyi Show resolved Hide resolved
stubs/ExifRead/exifread/classes.pyi Outdated Show resolved Hide resolved
stubs/ExifRead/exifread/classes.pyi Outdated Show resolved Hide resolved
stubs/ExifRead/exifread/_types.pyi Outdated Show resolved Hide resolved
def find_jpeg_exif(fh, data, fake_exif) -> tuple[Incomplete, Incomplete, Incomplete]: ...
logger: Logger

def find_jpeg_exif(fh: Reader, data: bytes, fake_exif: bool) -> tuple[int, bytes, bool]: ...
Copy link
Member

Choose a reason for hiding this comment

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

Looks like fake_exif can sometimes be an int: https://github.com/ianare/exif-py/blob/3575cc6d0df9e356edc1cd3d49516d066d1ad465/exifread/jpeg.py#L24

Suggested change
def find_jpeg_exif(fh: Reader, data: bytes, fake_exif: bool) -> tuple[int, bytes, bool]: ...
def find_jpeg_exif(fh: Reader, data: bytes, fake_exif: int) -> tuple[int, bytes, int]: ...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I believe that this is just a leftover from before there was a bool type in Python. We had similar cases in the stdlib.

Copy link
Member

Choose a reason for hiding this comment

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

I think that's the reason why this is the case, but at least the return type should be int, as I don't think bool is ever returned. It looks like _get_initial_base always returns an int as the second item in the tuple, which means find_jpeg_exif always returns int as the third item in the tuple, even if a bool was passed in.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The problem with using bool in the return type is that code like the following would cause a type error, although it's working fine at runtime, and is (arguably) correctly annotated:

def foo(b: bool) -> ...:
    if b:
        ...
foo(find_jpeg_exif(...)[2])

We've found in the past that just using bool in cases like this works best. The only instance where is fails is if isinstance (or similar) is used at runtime.

def ord_(dta: str) -> int: ... # type: ignore[misc]
@overload
def ord_(dta: _T) -> _T: ...
def make_string(seq: str | list[int]) -> str: ...
Copy link
Member

Choose a reason for hiding this comment

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

I guess this is another one of the str/bytes problems you identified in ianare/exif-py#172.

The code looks like it'll crash if seq isn't a sequence of ints, which implies that the annotation should be bytes | list[int]: https://github.com/ianare/exif-py/blob/3575cc6d0df9e356edc1cd3d49516d066d1ad465/exifread/utils.py#L23.

But in make_string_uc(), it's passed an argument that must be a str: https://github.com/ianare/exif-py/blob/3575cc6d0df9e356edc1cd3d49516d066d1ad465/exifread/utils.py#L47-L53

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Indeed. Therefore, I don't think it particularly matters what we annotate it as at the moment. (Maybe -> NoReturn?) I'm fine with any annotation.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah. It's a weird one, happy to go with whatever :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let's leave it like it is for lazyness reasons?

Copy link
Member

@AlexWaygood AlexWaygood left a comment

Choose a reason for hiding this comment

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

LGTM

@github-actions
Copy link
Contributor

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

@AlexWaygood AlexWaygood merged commit 0cf685c into python:main Dec 27, 2022
@srittau srittau deleted the exifread2 branch December 27, 2022 18:05
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