mypy icon indicating copy to clipboard operation
mypy copied to clipboard

Turn off implicit-optional by default

Open JukkaL opened this issue 4 years ago • 6 comments

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.

JukkaL avatar Jul 03 '20 15:07 JukkaL

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.

hukkin avatar Nov 03 '20 18:11 hukkin

@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

JukkaL avatar Nov 04 '20 16:11 JukkaL

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)

lazytype avatar Aug 17 '21 04:08 lazytype

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).

erictraut avatar Aug 17 '21 04:08 erictraut

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.

tzaffi avatar May 09 '22 12:05 tzaffi

If you're stumbling upon this, here is a codemod to help you automatically fix your code: https://github.com/hauntsaninja/no_implicit_optional

hauntsaninja avatar Sep 08 '22 03:09 hauntsaninja