Reputation: 5486
The return type of the below function depends on the argument passed to path
: if it is None
the function returns a string, if it is a string the function returns None
, and in all other possible cases, the function does not return at all. However, mypy
reports
error: Missing return statement
What am I missing here?
import json
from typing import Optional
def to_json(data: dict, path: Optional[str] = None) -> Optional[str]:
if path is None:
return json.dumps(data)
elif isinstance(path, str):
with open(path, 'w') as file:
json.dump(data, file)
else:
raise TypeError('Unsupported type for ``path``.')
Upvotes: 1
Views: 8519
Reputation: 66171
mypy
warns on missing return types by default, so you can turn it off explicitly:
$ mypy --no-warn-no-return spam.py
or turn off the particular check for the particular line only:
def to_json(data: Dict, path: Optional[str] = None) -> Optional[str]: # type: ignore[return]
...
However, your function has different return types depending on the input. I would add an overloaded signature to handle these:
from typing import Dict, Optional, overload
# when path is provided, the function returns
@overload
def to_json(data: Dict, path: str) -> str: ...
# when path is not provided, the function returns None
@overload
def to_json(data: Dict) -> None: ...
# your actual impl
def to_json(data, path=None):
if path is None:
...
Upvotes: 4
Reputation: 6246
First things first, your code is valid python. I believe mypy seems to be configured according to PEP8 recommendations for returns but is more strict about it since it has to enforce typechecks. The relevant section:
Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).
Yes:
def foo(x):
if x >= 0:
return math.sqrt(x)
else:
return None
No:
def foo(x):
if x >= 0:
return math.sqrt(x)
So, for your code, just be explicit about return None
in all branches where you do not return anything else.
Upvotes: 1
Reputation: 140148
not explicitly returning something from all branches makes the static analysis fail: it's seen as an omission (and considered as bad practice).
Just make the return None
explicit in the else
part (no need where you're rasing an exception)
elif isinstance(path, str):
with open(path, 'w') as file:
json.dump(data, file)
return None
Upvotes: 2
Reputation: 2076
Just add return None
to the code or return -1
or any such kind of return at the end of code.
Upvotes: 0