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

Typecheking code inside try...except TypeError #2420

Closed
davire opened this issue Nov 8, 2016 · 3 comments
Closed

Typecheking code inside try...except TypeError #2420

davire opened this issue Nov 8, 2016 · 3 comments

Comments

@davire
Copy link

davire commented Nov 8, 2016

here's an example:

from typing import Union,List

def fn(val: Union[str,List[int]]) -> int:
    try:
        res = int(val)
    except (ValueError,TypeError):
        res = 0
    return res

print(fn("123"),fn([]))

val could be either a str or a List[int], but if it's a list it'll be caught by except TypeError

for this code, mypy returns:

david@pcdavid:~/code/mypy-exemples$ mypy ex1.py 
ex1.py: note: In function "fn":
ex1.py:5: error: Argument 1 to "int" has incompatible type "Union[str, List[int]]"; expected "Union[SupportsInt, str, bytes]"
david@pcdavid:~/code/mypy-exemples$ mypy --version
mypy 0.4.5

There are workarounds using isinstance or cast, but it might be useful that mypy be able to typecheck this code.

@JukkaL
Copy link
Collaborator

JukkaL commented Nov 8, 2016

As @ilevkivskyi mentioned on Gitter, this can be dangerous. Mypy can't easily tell from where the ValueError or TypeError may come from. It seems to me that the only easy way to implement this right now would be to disable all or at least a lot of error reporting in some try blocks, and this could result in false negatives.

This could be more effective if mypy would classify errors using error ids (similar to some linters). For example, we could have one id for all errors that are likely to result in TypeError at runtime and another id for errors likely to result in AttributeError. An except TypeError: would only silence errors that would cause a TypeError, etc.

However, mypy wouldn't know exactly which exceptions a particular function or method can raise -- one might raise ValueError when given an invalid argument, another could raise AttributeError. Typeshed doesn't have exception annotations, and there's no way to annotate this for user code (and inferring raised exceptions would be impractical). Even with annotations, it may be impossible to predict which exact exception is raised in a particular context, in case a function can raise multiple exception types.

As this is a relatively complex issue, and there are easy workarounds (such as a cast or # type: ignore), this is not going to be a priority for us. However, as this issue comes up every now and then, it might be worthwhile to discuss the workarounds in the mypy documentation or the mypy wiki.

@gvanrossum
Copy link
Member

IMO this should not become a feature. Catching an exception is expensive (and even if you don't catch it you pay for the try/except setup and teardown). More importantly, an exception handler would basically end up disabling all type checking in the try/block. We also have no syntax for annotating which functions raise which exceptions.

The proper approach should use isinstance(), not cast(), because the latter just shuts up the checker completely while a series of isinstance() checks (in an if..elif... structure) is completely type-checked.

@cosinusalpha
Copy link

Is it worth considering reopening this issue? The try..except construct has become zero-cost in recent implementations. As a result, it seems that utilizing try..except for type-checking could potentially be more efficient than using isinstance() (?).

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

No branches or pull requests

4 participants