Skip to content

Commit 2cfc46c

Browse files
committed
Improve the Common Issues page (#14581)
Linking #13681
1 parent 7cf1391 commit 2cfc46c

File tree

2 files changed

+80
-77
lines changed

2 files changed

+80
-77
lines changed

docs/source/common_issues.rst

+72-77
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ doesn't work as expected. Statically typed code is often identical to
99
normal Python code (except for type annotations), but sometimes you need
1010
to do things slightly differently.
1111

12-
Can't install mypy using pip
13-
----------------------------
14-
15-
If installation fails, you've probably hit one of these issues:
16-
17-
* Mypy needs Python 3.6 or later to run.
18-
* You may have to run pip like this:
19-
``python3 -m pip install mypy``.
20-
2112
.. _annotations_needed:
2213

2314
No errors reported for obviously wrong code
@@ -26,7 +17,9 @@ No errors reported for obviously wrong code
2617
There are several common reasons why obviously wrong code is not
2718
flagged as an error.
2819

29-
**The function containing the error is not annotated.** Functions that
20+
**The function containing the error is not annotated.**
21+
22+
Functions that
3023
do not have any annotations (neither for any argument nor for the
3124
return type) are not type-checked, and even the most blatant type
3225
errors (e.g. ``2 + 'a'``) pass silently. The solution is to add
@@ -52,7 +45,9 @@ once you add annotations:
5245
5346
If you don't know what types to add, you can use ``Any``, but beware:
5447

55-
**One of the values involved has type 'Any'.** Extending the above
48+
**One of the values involved has type 'Any'.**
49+
50+
Extending the above
5651
example, if we were to leave out the annotation for ``a``, we'd get
5752
no error:
5853

@@ -68,49 +63,52 @@ The reason is that if the type of ``a`` is unknown, the type of
6863
If you're having trouble debugging such situations,
6964
:ref:`reveal_type() <reveal-type>` might come in handy.
7065

71-
Note that sometimes library stubs have imprecise type information,
72-
e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285
73-
<https://github.com/python/typeshed/issues/285>`_ for the reason).
66+
Note that sometimes library stubs with imprecise type information
67+
can be a source of ``Any`` values.
7468

7569
:py:meth:`__init__ <object.__init__>` **method has no annotated
76-
arguments or return type annotation.** :py:meth:`__init__ <object.__init__>`
77-
is considered fully-annotated **if at least one argument is annotated**,
78-
while mypy will infer the return type as ``None``.
79-
The implication is that, for a :py:meth:`__init__ <object.__init__>` method
80-
that has no argument, you'll have to explicitly annotate the return type
81-
as ``None`` to type-check this :py:meth:`__init__ <object.__init__>` method:
70+
arguments and no return type annotation.**
71+
72+
This is basically a combination of the two cases above, in that ``__init__``
73+
without annotations can cause ``Any`` types leak into instance variables:
8274

8375
.. code-block:: python
8476
85-
def foo(s: str) -> str:
86-
return s
77+
class Bad:
78+
def __init__(self):
79+
self.value = "asdf"
80+
1 + "asdf" # No error!
81+
82+
bad = Bad()
83+
bad.value + 1 # No error!
84+
reveal_type(bad) # Revealed type is "__main__.Bad"
85+
reveal_type(bad.value) # Revealed type is "Any"
8786
88-
class A():
89-
def __init__(self, value: str): # Return type inferred as None, considered as typed method
87+
class Good:
88+
def __init__(self) -> None: # Explicitly return None
9089
self.value = value
91-
foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
92-
93-
class B():
94-
def __init__(self): # No argument is annotated, considered as untyped method
95-
foo(1) # No error!
96-
97-
class C():
98-
def __init__(self) -> None: # Must specify return type to type-check
99-
foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
100-
101-
**Some imports may be silently ignored**. Another source of
102-
unexpected ``Any`` values are the :option:`--ignore-missing-imports
103-
<mypy --ignore-missing-imports>` and :option:`--follow-imports=skip
104-
<mypy --follow-imports>` flags. When you use :option:`--ignore-missing-imports <mypy --ignore-missing-imports>`,
105-
any imported module that cannot be found is silently replaced with
106-
``Any``. When using :option:`--follow-imports=skip <mypy --follow-imports>` the same is true for
107-
modules for which a ``.py`` file is found but that are not specified
108-
on the command line. (If a ``.pyi`` stub is found it is always
109-
processed normally, regardless of the value of
110-
:option:`--follow-imports <mypy --follow-imports>`.) To help debug the former situation (no
111-
module found at all) leave out :option:`--ignore-missing-imports <mypy --ignore-missing-imports>`; to get
112-
clarity about the latter use :option:`--follow-imports=error <mypy --follow-imports>`. You can
113-
read up about these and other useful flags in :ref:`command-line`.
90+
91+
92+
**Some imports may be silently ignored**.
93+
94+
A common source of unexpected ``Any`` values is the
95+
:option:`--ignore-missing-imports <mypy --ignore-missing-imports>` flag.
96+
97+
When you use :option:`--ignore-missing-imports <mypy --ignore-missing-imports>`,
98+
any imported module that cannot be found is silently replaced with ``Any``.
99+
100+
To help debug this, simply leave out
101+
:option:`--ignore-missing-imports <mypy --ignore-missing-imports>`.
102+
As mentioned in :ref:`fix-missing-imports`, setting ``ignore_missing_imports=True``
103+
on a per-module basis will make bad surprises less likely and is highly encouraged.
104+
105+
Use of the :option:`--follow-imports=skip <mypy --follow-imports>` flags can also
106+
cause problems. Use of these flags is strongly discouraged and only required in
107+
relatively niche situations. See :ref:`follow-imports` for more information.
108+
109+
**mypy considers some of your code unreachable**.
110+
111+
See :ref:`unreachable` for more information.
114112

115113
**A function annotated as returning a non-optional type returns 'None'
116114
and mypy doesn't complain**.
@@ -186,25 +184,17 @@ over ``.py`` files.
186184
Ignoring a whole file
187185
---------------------
188186

189-
A ``# type: ignore`` comment at the top of a module (before any statements,
187+
* To only ignore errors, use a top-level ``# mypy: ignore-errors`` comment instead.
188+
* To only ignore errors with a specific error code, use a top-level
189+
``# mypy: disable-error-code=...`` comment.
190+
* To replace the contents of a module with ``Any``, use a per-module ``follow_imports = skip``.
191+
See :ref:`Following imports <follow-imports>` for details.
192+
193+
Note that a ``# type: ignore`` comment at the top of a module (before any statements,
190194
including imports or docstrings) has the effect of ignoring the entire contents of the module.
191195
This behaviour can be surprising and result in
192196
"Module ... has no attribute ... [attr-defined]" errors.
193197

194-
To only ignore errors, use a top-level ``# mypy: ignore-errors`` comment instead.
195-
To only ignore errors with a specific error code, use a top-level
196-
``# mypy: disable-error-code=...`` comment.
197-
To replace the contents of the module with ``Any``, use a per-module ``follow_imports = skip``.
198-
See :ref:`Following imports <follow-imports>` for details.
199-
200-
.. code-block:: python
201-
202-
# type: ignore
203-
204-
import foo
205-
206-
foo.bar()
207-
208198
Issues with code at runtime
209199
---------------------------
210200

@@ -262,20 +252,20 @@ Redefinitions with incompatible types
262252

263253
Each name within a function only has a single 'declared' type. You can
264254
reuse for loop indices etc., but if you want to use a variable with
265-
multiple types within a single function, you may need to declare it
266-
with the ``Any`` type.
255+
multiple types within a single function, you may need to instead use
256+
multiple variables (or maybe declare the variable with an ``Any`` type).
267257

268258
.. code-block:: python
269259
270260
def f() -> None:
271261
n = 1
272262
...
273-
n = 'x' # Type error: n has type int
263+
n = 'x' # error: Incompatible types in assignment (expression has type "str", variable has type "int")
274264
275265
.. note::
276266

277-
This limitation could be lifted in a future mypy
278-
release.
267+
Using the :option:`--allow-redefinition <mypy --allow-redefinition>`
268+
flag can suppress this error in several cases.
279269

280270
Note that you can redefine a variable with a more *precise* or a more
281271
concrete type. For example, you can redefine a sequence (which does
@@ -289,6 +279,8 @@ not support ``sort()``) as a list and sort it in-place:
289279
# Type of x is List[int] here.
290280
x.sort() # Okay!
291281
282+
See :ref:`type-narrowing` for more information.
283+
292284
.. _variance:
293285

294286
Invariance vs covariance
@@ -340,24 +332,24 @@ Declaring a supertype as variable type
340332

341333
Sometimes the inferred type is a subtype (subclass) of the desired
342334
type. The type inference uses the first assignment to infer the type
343-
of a name (assume here that ``Shape`` is the base class of both
344-
``Circle`` and ``Triangle``):
335+
of a name:
345336

346337
.. code-block:: python
347338
348-
shape = Circle() # Infer shape to be Circle
349-
...
350-
shape = Triangle() # Type error: Triangle is not a Circle
339+
class Shape: ...
340+
class Circle(Shape): ...
341+
class Triangle(Shape): ...
342+
343+
shape = Circle() # mypy infers the type of shape to be Circle
344+
shape = Triangle() # error: Incompatible types in assignment (expression has type "Triangle", variable has type "Circle")
351345
352346
You can just give an explicit type for the variable in cases such the
353347
above example:
354348

355349
.. code-block:: python
356350
357-
shape = Circle() # type: Shape # The variable s can be any Shape,
358-
# not just Circle
359-
...
360-
shape = Triangle() # OK
351+
shape: Shape = Circle() # The variable s can be any Shape, not just Circle
352+
shape = Triangle() # OK
361353
362354
Complex type tests
363355
------------------
@@ -622,7 +614,10 @@ You can install the latest development version of mypy from source. Clone the
622614
623615
git clone https://github.com/python/mypy.git
624616
cd mypy
625-
sudo python3 -m pip install --upgrade .
617+
python3 -m pip install --upgrade .
618+
619+
To install a development version of mypy that is mypyc-compiled, see the
620+
instructions at the `mypyc wheels repo <https://github.com/mypyc/mypy_mypyc-wheels>`_.
626621

627622
Variables vs type aliases
628623
-------------------------

docs/source/running_mypy.rst

+8
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ other than the one mypy is running in, you can use :option:`--python-executable
357357
<mypy --python-executable>` flag to point to the Python executable for that
358358
environment, and mypy will find packages installed for that Python executable.
359359

360+
If you've installed the relevant stub packages and are still getting this error,
361+
see the :ref:`section below <missing-type-hints-for-third-party-library>`.
362+
360363
.. _missing-type-hints-for-third-party-library:
361364

362365
Cannot find implementation or library stub
@@ -379,6 +382,11 @@ this error, try:
379382
line flag to point the Python interpreter containing your installed
380383
third party packages.
381384

385+
You can confirm that you are running mypy from the environment you expect
386+
by running it like ``python -m mypy ...``. You can confirm that you are
387+
installing into the environment you expect by running pip like
388+
``python -m pip ...``.
389+
382390
2. Reading the :ref:`finding-imports` section below to make sure you
383391
understand how exactly mypy searches for and finds modules and modify
384392
how you're invoking mypy accordingly.

0 commit comments

Comments
 (0)