Skip to content

Commit 203f7e4

Browse files
author
hauntsaninja
committed
Document new source finding behaviour
This should cover the current state on master, as implemented across python#9742, python#9683, python#9632, python#9616, python#9614, etc. This will need to be changed if we can make `--namespace-packages` the default (python#9636).
1 parent 734e4ad commit 203f7e4

File tree

2 files changed

+73
-46
lines changed

2 files changed

+73
-46
lines changed

docs/source/command_line.rst

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,17 @@ imports.
110110
passed on the command line, the ``MYPYPATH`` environment variable,
111111
and the :confval:`mypy_path` config option.
112112

113-
Note that this only affects import discovery -- for modules and
114-
packages explicitly passed on the command line, mypy still
115-
searches for ``__init__.py[i]`` files in order to determine the
116-
fully-qualified module/package name.
113+
This flag also affects how mypy determines fully qualified module names for
114+
files, modules and packages explicitly passed on the command line. See
115+
:ref:`Mapping file paths to modules <mapping-paths-to-modules>` for details.
116+
117+
.. option:: --explicit-package-bases
118+
119+
This flag tells mypy to that the current directory, the ``MYPYPATH``
120+
environment variable, and the :confval:`mypy_path` config option as the
121+
directories in which top-level packages are located. This option is only
122+
useful in conjunction with :option:`--namespace-packages`. See :ref:`Mapping
123+
file paths to modules <mapping-paths-to-modules>` for details.
117124

118125
.. option:: --ignore-missing-imports
119126

docs/source/running_mypy.rst

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ actual way mypy type checks your code, see our
2424
Specifying code to be checked
2525
*****************************
2626

27-
Mypy lets you specify what files it should type check in several
28-
different ways.
27+
Mypy lets you specify what files it should type check in several different ways.
28+
29+
Note that if you use namespace packages (in particular, packages without
30+
``__init__.py``), you'll need to specify :option:`--namespace-packages <mypy
31+
--namespace-packages>`.
2932

3033
1. First, you can pass in paths to Python files and directories you
3134
want to type check. For example::
@@ -342,52 +345,69 @@ hard-to-debug errors.
342345
Mapping file paths to modules
343346
*****************************
344347

345-
One of the main ways you can tell mypy what files to type check
346-
is by providing mypy the paths to those files. For example::
348+
One of the main ways you can tell mypy what to type check
349+
is by providing mypy a list of paths. For example::
347350

348351
$ mypy file_1.py foo/file_2.py file_3.pyi some/directory
349352

350353
This section describes how exactly mypy maps the provided paths
351354
to modules to type check.
352355

353-
- Files ending in ``.py`` (and stub files ending in ``.pyi``) are
354-
checked as Python modules.
355-
356-
- Files not ending in ``.py`` or ``.pyi`` are assumed to be Python
357-
scripts and checked as such.
358-
359-
- Directories representing Python packages (i.e. containing a
360-
``__init__.py[i]`` file) are checked as Python packages; all
361-
submodules and subpackages will be checked (subpackages must
362-
themselves have a ``__init__.py[i]`` file).
363-
364-
- Directories that don't represent Python packages (i.e. not directly
365-
containing an ``__init__.py[i]`` file) are checked as follows:
366-
367-
- All ``*.py[i]`` files contained directly therein are checked as
368-
toplevel Python modules;
369-
370-
- All packages contained directly therein (i.e. immediate
371-
subdirectories with an ``__init__.py[i]`` file) are checked as
372-
toplevel Python packages.
373-
374-
One more thing about checking modules and packages: if the directory
375-
*containing* a module or package specified on the command line has an
376-
``__init__.py[i]`` file, mypy assigns these an absolute module name by
377-
crawling up the path until no ``__init__.py[i]`` file is found.
378-
379-
For example, suppose we run the command ``mypy foo/bar/baz.py`` where
380-
``foo/bar/__init__.py`` exists but ``foo/__init__.py`` does not. Then
381-
the module name assumed is ``bar.baz`` and the directory ``foo`` is
382-
added to mypy's module search path.
383-
384-
On the other hand, if ``foo/bar/__init__.py`` did not exist, ``foo/bar``
385-
would be added to the module search path instead, and the module name
386-
assumed is just ``baz``.
387-
388-
If a script (a file not ending in ``.py[i]``) is processed, the module
389-
name assumed is ``__main__`` (matching the behavior of the
390-
Python interpreter), unless :option:`--scripts-are-modules <mypy --scripts-are-modules>` is passed.
356+
- mypy will check all paths provided that correspond to files.
357+
358+
- mypy will recursively discover all Python files ending in ``.py`` (and stub
359+
files ending in ``.pyi``) in all directory paths provided.
360+
361+
- For each file to be checked, mypy will attempt to associate the file (e.g.
362+
``project/foo/bar/baz.py``) with a fully qualified module name (e.g.
363+
``foo.bar.baz``). The directory the package is in (``project``) is then
364+
add to mypy's module search paths.
365+
366+
How mypy determines fully qualified module names depends on if the options
367+
:option:`--namespace-packages <mypy --namespace-packages>` and
368+
:option:`--explicit-package-bases <mypy --explicit-package-bases>` are set.
369+
370+
First, if :option:`--namespace-packages <mypy --namespace-packages>` is off,
371+
mypy will rely solely upon the presence of ``__init__.py[i]`` files to determine
372+
the fully qualified module name. That is, mypy will crawl up the directory tree
373+
for as long as it continues to find ``__init__.py`` (or ``__init__.pyi``) files.
374+
375+
Second, if :option:`--namespace-packages <mypy --namespace-packages>` is on, but
376+
:option:`--explicit-package-bases <mypy --explicit-package-bases>` is off, mypy
377+
will allow for the possibility that directories without ``__init__.py[i]`` are
378+
packages. Specifically, mypy will look at all parent directories of the file and
379+
use the location of the highest ``__init__.py[i]`` in the directory tree to
380+
determine the top-level package.
381+
382+
For example, say your directory tree consists solely of ``pkg/__init__.py`` and
383+
``pkg/a/b/c/d/mod.py``. When determining ``mod.py``'s fully qualified module
384+
name, mypy will look at ``pkg/__init__.py`` and conclude that the associated
385+
module name is ``pkg.a.b.c.d.mod``.
386+
387+
You'll notice that that method still relies on ``__init__.py``. If you can't put
388+
an ``__init__.py`` in your top-level package, but still wish to pass paths (as
389+
opposed to packages or modules using the ``-p`` or ``-m`` flags),
390+
:option:`--explicit-package-bases <mypy --explicit-package-bases>` provides a
391+
solution.
392+
393+
Third, with :option:`--explicit-package-bases <mypy --explicit-package-bases>`,
394+
mypy will locate the nearest parent directory that is a member of the
395+
``MYPYPATH`` environment variable, the :confval:`mypy_path` config or is the
396+
current working directory. mypy will then use the relative path to determine the
397+
fully qualified module name.
398+
399+
For example, say your directory tree consists solely of
400+
``src/namespace_pkg/mod.py``. If you run the command following command, mypy
401+
will correctly associate ``mod.py`` with ``namespace_pkg.mod``::
402+
403+
$ MYPYPATH=src mypy --namespace-packages --explicit-package-bases .
404+
405+
If you pass a file not ending in ``.py[i]``, the module name assumed is
406+
``__main__`` (matching the behavior of the Python interpreter), unless
407+
:option:`--scripts-are-modules <mypy --scripts-are-modules>` is passed.
408+
409+
Passing :option:`-v <mypy -v>` will show you the files and associated module
410+
names that mypy will check.
391411

392412

393413
.. _finding-imports:

0 commit comments

Comments
 (0)