5

have been using the following code

import yaml
try:
    filterwarnings(yaml.YAMLLoadWarning)
except AttributeError:
    pass

But when I tried to run mypy today I got "module has no attribute YAMLLoadWarning". Which is true on some versions of python. Is there a better way to write this?

EDIT:

To be a little clearer, I know how to ignore the error (and catch the exception related to the python 3.6 version of pyyaml not including that exception). My question is more about working with the parser. Consider these examples-

I know that if you have a function that returns a more specific type

def bad(a: Optional[int]) -> int:
    return a  # Incompatible return value type (got "Optional[int]", expected "int")

You can use a branch to force only the correct type to be returned, and the parser notices

def good(a: Optional[int]) -> int:
    if a:
        return a
    return 0

So in situations where you handle error situations using a try/catch statement, is there a way to construct this so that the parser realizes that the attribute error is handled?

def exception_branch(a: Optional[str])-> list:
    try:
        return a.split()  # Item "None" of "Optional[str]" has no attribute "split"
    except:
        return []
Paul Becotte
  • 9,767
  • 3
  • 34
  • 42
  • Possible duplicate of [How can mypy ignore a single line in a source file?](https://stackoverflow.com/questions/49220022/how-can-mypy-ignore-a-single-line-in-a-source-file) – Georgy Jun 19 '19 at 14:15

2 Answers2

1

So in situations where you handle error situations using a try/catch statement, is there a way to construct this so that the parser realizes that the attribute error is handled?

No, there is not, I'm afraid. The problem is that catch AttributeError does not indicate where from the exception comes. So if you had

try:
    print(foo.barr)
    return a.split()
except AttributeError:
    return []

The typechecker can ignore the fact that a can be None, but it would have to ignore also the fact that you misspelled bar and there is no barr attribute in the object foo. See also here.

volferine
  • 372
  • 1
  • 9
  • I'm not quite following how that is an issue for the type checker. Ignoring *all* possible ``AttributeError``s is exactly what the code means. "misspelled" and "missing" are the same as far as types are concerned. – MisterMiyagi Mar 21 '22 at 14:05
  • @MisterMiyagi It's an issue for the OP, as I understand the question. It would be nice if mypy was able to deduce something like "`a` is `Optional` so `a.split` is troublesome, but the code is catching `AttributeError` because the author is aware of the problem, so all is ok". But mypy is not and ignoring `AttributeError` for `a.split` means ignoring it also for `foo.barr`, which is not desirable and against type checker principles. – volferine Mar 22 '22 at 17:13
0

I'm assuming you're using PyYAML?

In that case, the best long-term fix is probably for you to submit a pull request to Typeshed including type hints for this class. (Typeshed is the repository of type hints for standard library modules and select third party modules. The stubs for PyYAML happen to be included within typeshed here.)

It seems PyYAML defines YAMLLoadWarning within the module's __init__.py file so you should probably add type hints for that class within the corresponding __init__.pyi file in Typeshed.

Then you wait for the next release of mypy -- it bakes in the latest available version of Typeshed the time of release.

I believe mypy is actually scheduled to release later today, so the timing might be a bit tight if you end up submitting a PR. But worst case scenario, you'll just need to wait for another month or two for the subsequent mypy release.

In the meantime, you can just add a # type: ignore comment to that line, as suggested by Georgy in the comments.

If you do this, I also recommend running mypy with the --warn-unused-ignores command line flag. This will help you find # type: ignore comments you no longer need as mypy releases/improves over time.

Azat Ibrakov
  • 9,998
  • 9
  • 38
  • 50
Michael0x2a
  • 58,192
  • 30
  • 175
  • 224
  • 1
    No, this wasn't a PyYaml thing. This was pretty much the question verbatim- had an `Optional` parameter that I was using an attribute on and catching the attribute error, and was wondering if there was a way to explain to mypy that there was no way for that error to get thrown. I understand now why it works differently than the If- the error DOES get thrown after all, just caught. So, just used an ignore. – Paul Becotte Nov 08 '19 at 02:33