mypy
mypy copied to clipboard
Turn off implicit-optional by default
We'd require an explicit optional argument type in cases like this:
def f(x: int = None) -> None:
...
Currently this is accepted by mypy, unless --no-implicit-optional
is used. The idea would be to make --no-implicit-optional
the default, and --implicit-optional
can be used to get back to the current default behavior.
It might be a good idea to flip the switch sooner rather than later. If I understand things correctly, annotations relying on "implicit optional" are no longer PEP 484 compliant after https://github.com/python/peps/pull/689 and the number of these non-compliant annotations will keep on increasing as long as mypy allows them.
@hukkinj1 A good point. We could try to get this included in the next public release as a breaking change, perhaps, if there no good arguments against this.
cc @ilevkivskyi
I was wondering if we could change the behavior to mean, "the argument is optional, but explicit None
is not allowed". Here's a simple, contrived use-case:
class Point:
...
@overload
def update(self, other_point: Point) -> None: ...
@overload
def update(self, *, x: int = None, y: int = None) -> None: ... # Keyword-only arguments that can't explicitly be `None`
def update(self, *args: Any, **kwargs: Any) -> None:
if args:
self.x = args[0].x
self.y = args[0].y
else:
self.x = kwargs.get("x", self.x) # Can't be `None` because explicit `.update(x=None)` is not allowed
self.y = kwargs.get("y", self.y)
PEP 484 is clear that the subexpression x: int = None
should be flagged as an error going forward.
An ellipsis is already the standard way to indicate this behavior within an overload signature: x: int = ...
. Or you can use the actual default value (x: int = 0
).
What is the status of this almost 2 years in? Clearly foo(x: int = None)
is more concise than foo(x: Optional[int] = None)
. While the latter may seem more correct than the former, the intent of the former is transparent for anyone understanding type hints. There are other situation in which brevity has been chosen over "correctness". For example None
is allowed to be used instead of NoneType
in unions.
If you're stumbling upon this, here is a codemod to help you automatically fix your code: https://github.com/hauntsaninja/no_implicit_optional