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

Document how evil --no-strict-optional is #16731

Merged
merged 1 commit into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions docs/source/command_line.rst
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,6 @@ None and Optional handling
**************************

The following flags adjust how mypy handles values of type ``None``.
For more details, see :ref:`no_strict_optional`.

.. _implicit-optional:

Expand All @@ -435,16 +434,19 @@ For more details, see :ref:`no_strict_optional`.

**Note:** This was disabled by default starting in mypy 0.980.

.. _no_strict_optional:

.. option:: --no-strict-optional

This flag disables strict checking of :py:data:`~typing.Optional`
This flag effectively disables checking of :py:data:`~typing.Optional`
types and ``None`` values. With this option, mypy doesn't
generally check the use of ``None`` values -- they are valid
everywhere. See :ref:`no_strict_optional` for more about this feature.
generally check the use of ``None`` values -- it is treated
as compatible with every type.

.. warning::

**Note:** Strict optional checking was enabled by default starting in
mypy 0.600, and in previous versions it had to be explicitly enabled
using ``--strict-optional`` (which is still accepted).
``--no-strict-optional`` is evil. Avoid using it and definitely do
not use it without understanding what it does.


.. _configuring-warnings:
Expand Down
2 changes: 1 addition & 1 deletion docs/source/common_issues.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ and mypy doesn't complain**.
return None # No error!

You may have disabled strict optional checking (see
:ref:`no_strict_optional` for more).
:ref:`--no-strict-optional <no_strict_optional>` for more).

.. _silencing_checker:

Expand Down
9 changes: 7 additions & 2 deletions docs/source/config_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -580,10 +580,15 @@ section of the command line docs.
:type: boolean
:default: True

Enables or disables strict Optional checks. If False, mypy treats ``None``
Effectively disables checking of :py:data:`~typing.Optional`
types and ``None`` values. With this option, mypy doesn't
generally check the use of ``None`` values -- it is treated
as compatible with every type.

**Note:** This was False by default in mypy versions earlier than 0.600.
.. warning::

``strict_optional = false`` is evil. Avoid using it and definitely do
not use it without understanding what it does.


Configuring warnings
Expand Down
68 changes: 0 additions & 68 deletions docs/source/kinds_of_types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -429,74 +429,6 @@ the runtime with some limitations (see :ref:`runtime_troubles`).

t2: int | None # equivalent to Optional[int]

.. _no_strict_optional:

Disabling strict optional checking
**********************************

Mypy also has an option to treat ``None`` as a valid value for every
type (in case you know Java, it's useful to think of it as similar to
the Java ``null``). In this mode ``None`` is also valid for primitive
types such as ``int`` and ``float``, and :py:data:`~typing.Optional` types are
not required.

The mode is enabled through the :option:`--no-strict-optional <mypy --no-strict-optional>` command-line
option. In mypy versions before 0.600 this was the default mode. You
can enable this option explicitly for backward compatibility with
earlier mypy versions, in case you don't want to introduce optional
types to your codebase yet.

It will cause mypy to silently accept some buggy code, such as
this example -- it's not recommended if you can avoid it:

.. code-block:: python

def inc(x: int) -> int:
return x + 1

x = inc(None) # No error reported by mypy if strict optional mode disabled!

However, making code "optional clean" can take some work! You can also use
:ref:`the mypy configuration file <config-file>` to migrate your code
to strict optional checking one file at a time, since there exists
the per-module flag
:confval:`strict_optional` to control strict optional mode.

Often it's still useful to document whether a variable can be
``None``. For example, this function accepts a ``None`` argument,
but it's not obvious from its signature:

.. code-block:: python

def greeting(name: str) -> str:
if name:
return f'Hello, {name}'
else:
return 'Hello, stranger'

print(greeting('Python')) # Okay!
print(greeting(None)) # Also okay!

You can still use :py:data:`Optional[t] <typing.Optional>` to document that ``None`` is a
valid argument type, even if strict ``None`` checking is not
enabled:

.. code-block:: python

from typing import Optional

def greeting(name: Optional[str]) -> str:
if name:
return f'Hello, {name}'
else:
return 'Hello, stranger'

Mypy treats this as semantically equivalent to the previous example
if strict optional checking is disabled, since ``None`` is implicitly
valid for any type, but it's much more
useful for a programmer who is reading the code. This also makes
it easier to migrate to strict ``None`` checking in the future.

.. _type-aliases:

Type aliases
Expand Down