Skip to content
Commits on Source (3)
Metadata-Version: 2.1
Name: mypy
Version: 0.580
Version: 0.590
Summary: Optional static typing for Python
Home-page: http://www.mypy-lang.org/
Author: Jukka Lehtosalo
......
mypy (0.580-3) UNRELEASED; urgency=medium
mypy (0.590-1) unstable; urgency=medium
* Add basic autopkgtest and enable autopkgtest-pkg-python
* Latest upstream.
* Bump standards-version and update VCS fields to salsa
-- Michael R. Crusoe <michael.crusoe@gmail.com> Wed, 04 Apr 2018 04:31:28 -0700
-- Michael R. Crusoe <michael.crusoe@gmail.com> Wed, 18 Apr 2018 03:57:17 -0700
mypy (0.580-2) unstable; urgency=medium
......
......@@ -4,7 +4,7 @@ Uploaders: Michael R. Crusoe <michael.crusoe@gmail.com>
Section: utils
Testsuite: autopkgtest-pkg-python
Priority: optional
Build-Depends: debhelper (>= 11~),
Build-Depends: debhelper (>= 11),
dh-python,
flake8,
help2man,
......@@ -17,9 +17,9 @@ Build-Depends: debhelper (>= 11~),
python3-sphinx-rtd-theme,
python3-typed-ast (>= 1.1.0),
python3-psutil (>= 5.4.0)
Standards-Version: 4.1.3
Vcs-Browser: https://anonscm.debian.org/cgit/debian-med/mypy.git
Vcs-Git: https://anonscm.debian.org/git/debian-med/mypy.git
Standards-Version: 4.1.4
Vcs-Browser: https://salsa.debian.org/med-team/mypy
Vcs-Git: https://salsa.debian.org/med-team/mypy.git
Homepage: http://www.mypy-lang.org/
X-Python3-Version: >= 3.2
......
......@@ -105,6 +105,45 @@ Python 3 introduces an annotation syntax for function declarations in `PEP 3107
...
Coroutines and asyncio
**********************
See :ref:`async-and-await` for the full detail on typing coroutines and asynchronous code.
.. code-block:: python
import asyncio
from typing import Generator, Any
# A generator-based coroutine created with @asyncio.coroutine should have a
# return type of Generator[Any, None, T], where T is the type it returns.
@asyncio.coroutine
def countdown34(tag: str, count: int) -> Generator[Any, None, str]:
while count > 0:
print('T-minus {} ({})'.format(count, tag))
yield from asyncio.sleep(0.1)
count -= 1
return "Blastoff!"
# mypy currently does not support converting functions into generator-based
# coroutines in Python 3.4, so you need to add a 'yield' to make it
# typecheck.
@asyncio.coroutine
def async1(obj: object) -> Generator[None, None, str]:
if False:
yield
return "placeholder"
# A Python 3.5+ coroutine is typed like a normal function.
async def countdown35(tag: str, count: int) -> str:
while count > 0:
print('T-minus {} ({})'.format(count, tag))
await asyncio.sleep(0.1)
count -= 1
return "Blastoff!"
async def async2(obj: object) -> str:
return "placeholder"
When you're puzzled or when things are complicated
**************************************************
......
......@@ -309,10 +309,13 @@ This is a type for objects that support ``bytes(x)``.
def __bytes__(self) -> bytes
.. _supports-int-etc:
``SupportsComplex``
-------------------
This is a type for objects that support ``complex(x)``.
This is a type for objects that support ``complex(x)``. Note that no arithmetic operations
are supported.
.. code-block:: python
......@@ -321,7 +324,8 @@ This is a type for objects that support ``complex(x)``.
``SupportsFloat``
-----------------
This is a type for objects that support ``float(x)``.
This is a type for objects that support ``float(x)``. Note that no arithmetic operations
are supported.
.. code-block:: python
......@@ -330,7 +334,8 @@ This is a type for objects that support ``float(x)``.
``SupportsInt``
---------------
This is a type for objects that support ``int(x)``.
This is a type for objects that support ``int(x)``. Note that no arithmetic operations
are supported.
.. code-block:: python
......
......@@ -19,21 +19,21 @@ flag (or its long form ``--help``)::
[--warn-incomplete-stub] [--disallow-untyped-decorators]
[--warn-redundant-casts] [--no-warn-no-return] [--warn-return-any]
[--warn-unused-ignores] [--warn-unused-configs]
[--show-error-context] [--no-implicit-optional] [-i]
[--show-error-context] [--no-implicit-optional] [--no-incremental]
[--quick-and-dirty] [--cache-dir DIR] [--cache-fine-grained]
[--skip-version-check] [--strict-optional]
[--strict-optional-whitelist [GLOB [GLOB ...]]]
[--junit-xml JUNIT_XML] [--pdb] [--show-traceback] [--stats]
[--inferstats] [--custom-typing MODULE]
[--custom-typeshed-dir DIR] [--scripts-are-modules]
[--config-file CONFIG_FILE] [--show-column-numbers]
[--find-occurrences CLASS.MEMBER] [--strict]
[--shadow-file SOURCE_FILE SHADOW_FILE] [--any-exprs-report DIR]
[--cobertura-xml-report DIR] [--html-report DIR]
[--linecount-report DIR] [--linecoverage-report DIR]
[--memory-xml-report DIR] [--txt-report DIR] [--xml-report DIR]
[--xslt-html-report DIR] [--xslt-txt-report DIR] [-m MODULE]
[-c PROGRAM_TEXT] [-p PACKAGE]
[--always-true NAME] [--always-false NAME] [--junit-xml JUNIT_XML]
[--pdb] [--show-traceback] [--stats] [--inferstats]
[--custom-typing MODULE] [--custom-typeshed-dir DIR]
[--scripts-are-modules] [--config-file CONFIG_FILE]
[--show-column-numbers] [--find-occurrences CLASS.MEMBER]
[--strict] [--shadow-file SOURCE_FILE SHADOW_FILE]
[--any-exprs-report DIR] [--cobertura-xml-report DIR]
[--html-report DIR] [--linecount-report DIR]
[--linecoverage-report DIR] [--memory-xml-report DIR]
[--txt-report DIR] [--xml-report DIR] [--xslt-html-report DIR]
[--xslt-txt-report DIR] [-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT]
[files [files ...]]
(etc., too long to show everything here)
......@@ -337,12 +337,15 @@ Here are some more useful flags:
.. _incremental:
- ``--incremental`` enables a module cache, using results from
- Incremental mode enables a module cache, using results from
previous runs to speed up type checking. Incremental mode can help
when most parts of your program haven't changed since the previous
mypy run.
- ``--cache-dir DIR`` is a companion flag to ``-incremental``, which
Incremental mode is the default and may be disabled with
``--no-incremental``.
- ``--cache-dir DIR`` is a companion flag to incremental mode, which
specifies where the cache files are written. By default this is
``.mypy_cache`` in the current directory. While the cache is only
read in incremental mode, it is written even in non-incremental
......@@ -363,17 +366,41 @@ Here are some more useful flags:
updates the cache, but regular incremental mode ignores cache files
written by quick mode.
- ``--python-executable EXECUTABLE`` will have mypy collect type information
from `PEP 561`_ compliant packages installed for the Python executable
``EXECUTABLE``. If not provided, mypy will use PEP 561 compliant packages
installed for the Python executable running mypy. See
:ref:`installed-packages` for more on making PEP 561 compliant packages.
This flag will attempt to set ``--python-version`` if not already set.
- ``--python-version X.Y`` will make mypy typecheck your code as if it were
run under Python version X.Y. Without this option, mypy will default to using
whatever version of Python is running mypy. Note that the ``-2`` and
``--py2`` flags are aliases for ``--python-version 2.7``. See
:ref:`version_and_platform_checks` for more about this feature.
:ref:`version_and_platform_checks` for more about this feature. This flag
will attempt to find a Python executable of the corresponding version to
search for `PEP 561`_ compliant packages. If you'd like to disable this,
see ``--no-site-packages`` below.
- ``--no-site-packages`` will disable searching for `PEP 561`_ compliant
packages. This will also disable searching for a usable Python executable.
Use this flag if mypy cannot find a Python executable for the version of
Python being checked, and you don't need to use PEP 561 typed packages.
Otherwise, use ``--python-executable``.
- ``--platform PLATFORM`` will make mypy typecheck your code as if it were
run under the the given operating system. Without this option, mypy will
default to using whatever operating system you are currently using. See
:ref:`version_and_platform_checks` for more about this feature.
.. _always-true:
- ``--always-true NAME`` will treat all variables named ``NAME`` as
compile-time constants that are always true. May be repeated.
- ``--always-false NAME`` will treat all variables named ``NAME`` as
compile-time constants that are always false. May be repeated.
- ``--show-column-numbers`` will add column offsets to error messages,
for example, the following indicates an error in line 12, column 9
(note that column offsets are 0-based):
......@@ -450,6 +477,8 @@ For the remaining flags you can read the full ``mypy -h`` output.
Command line flags are liable to change between releases.
.. _PEP 561: https://www.python.org/dev/peps/pep-0561/
.. _integrating-mypy:
Integrating mypy into another Python application
......
......@@ -85,6 +85,18 @@ flagged as an error.
clarity about the latter use ``--follow-imports=error``. You can
read up about these and other useful flags in :ref:`command-line`.
- **A function annotated as returning a non-optional type returns ``None``
and mypy doesn't complain**.
.. code-block:: python
def foo() -> str:
return None # No error!
By default, the ``None`` value is considered compatible with everything. See
:ref:`optional` for details on strict optional checking, which allows mypy to
check ``None`` values precisely, and will soon become default.
.. _silencing_checker:
Spurious errors and locally silencing the checker
......
......@@ -55,6 +55,14 @@ The following global flags may only be set in the global section
Windows, respectively). The default is the current platform as
revealed by Python's ``sys.platform`` variable.
- ``always_true`` (comma-separated list of strings) gives variable
names that will be treated as compile-time constants that are always
true.
- ``always_false`` (comma-separated list of strings) gives variable
names that will be treated as compile-time constants that are always
false.
- ``custom_typing_module`` (string) specifies the name of an
alternative module which is to be considered equivalent to the
``typing`` module.
......@@ -99,7 +107,7 @@ The following global flags may only be set in the global section
- ``dump_inference_stats`` (Boolean, default False) dumps stats about
type inference.
- ``incremental`` (Boolean, default False) enables :ref:`incremental
- ``incremental`` (Boolean, default True) enables :ref:`incremental
mode <incremental>`.
- ``cache_dir`` (string, default ``.mypy_cache``) stores module cache
......@@ -142,6 +150,15 @@ overridden by the pattern sections matching the module name.
of the *imported* module, not the module containing the import
statement.
- ``follow_imports_for_stubs`` (Boolean, default false) determines
whether to respect the ``follow_imports`` setting even for stub
(``.pyi``) files.
Used in conjunction with ``follow_imports=skip``, this can be used
to suppress the import of a module from ``typeshed``, replacing it
with `Any`.
Used in conjuncation with ``follow_imports=error``, this can be used
to make any use of a particular ``typeshed`` module an error.
- ``ignore_missing_imports`` (Boolean, default False) suppress error
messages about imports that cannot be resolved. Note that if
pattern matching is used, the pattern should match the name of the
......
......@@ -30,6 +30,7 @@ Mypy is a static type checker for Python.
command_line
config_file
python36
installed_packages
faq
cheat_sheet
cheat_sheet_py3
......
.. _installed-packages:
Using Installed Packages
========================
`PEP 561 <https://www.python.org/dev/peps/pep-0561/>`_ specifies how to mark
a package as supporting type checking. Below is a summary of how to create
PEP 561 compatible packages and have mypy use them in type checking.
Using PEP 561 compatible packages with mypy
*******************************************
Generally, you do not need to do anything to use installed packages that
support typing for the Python executable used to run mypy. Note that most
packages do not support typing. Packages that do support typing should be
automatically picked up by mypy and used for type checking.
By default, mypy searches for packages installed for the Python executable
running mypy. It is highly unlikely you want this situation if you have
installed typed packages in another Python's package directory.
Generally, you can use the ``--python-version`` flag and mypy will try to find
the correct package directory. If that fails, you can use the
``--python-executable`` flag to point to the exact executable, and mypy will
find packages installed for that Python executable.
Note that mypy does not support some more advanced import features, such as zip
imports, namespace packages, and custom import hooks.
If you do not want to use typed packages, use the ``--no-site-packages`` flag
to disable searching.
Making PEP 561 compatible packages
**********************************
PEP 561 notes three main ways to distribute type information. The first is a
package that has only inline type annotations in the code itself. The second is
a package that ships stub files with type information alongside the runtime
code. The third method, also known as a "stub only package" is a package that
ships type information for a package separately as stub files.
If you would like to publish a library package to a package repository (e.g.
PyPI) for either internal or external use in type checking, packages that
supply type information via type comments or annotations in the code should put
a ``py.typed`` in their package directory. For example, with a directory
structure as follows:
.. code-block:: text
setup.py
package_a/
__init__.py
lib.py
py.typed
the setup.py might look like:
.. code-block:: python
from distutils.core import setup
setup(
name="SuperPackageA",
author="Me",
version="0.1",
package_data={"package_a": ["py.typed"]},
packages=["package_a"]
)
Some packages have a mix of stub files and runtime files. These packages also
require a ``py.typed`` file. An example can be seen below:
.. code-block:: text
setup.py
package_b/
__init__.py
lib.py
lib.pyi
py.typed
the setup.py might look like:
.. code-block:: python
from distutils.core import setup
setup(
name="SuperPackageB",
author="Me",
version="0.1",
package_data={"package_b": ["py.typed", "lib.pyi"]},
packages=["package_b"]
)
In this example, both ``lib.py`` and ``lib.pyi`` exist. At runtime, the Python
interpeter will use ``lib.py``, but mypy will use ``lib.pyi`` instead.
If the package is stub-only (not imported at runtime), the package should have
a prefix of the runtime package name and a suffix of ``-stubs``.
A ``py.typed`` file is not needed for stub-only packages. For example, if we
had stubs for ``package_c``, we might do the following:
.. code-block:: text
setup.py
package_c-stubs/
__init__.pyi
lib.pyi
the setup.py might look like:
.. code-block:: python
from distutils.core import setup
setup(
name="SuperPackageC",
author="Me",
version="0.1",
package_data={"package_c-stubs": ["__init__.pyi", "lib.pyi"]},
packages=["package_c-stubs"]
)
......@@ -3,13 +3,28 @@ Revision history
List of major changes:
- April 2018
* Publish ``mypy`` version 0.590 on PyPI.
* Document :ref:`PEP 561 support <installed-packages>`.
* Made :ref:`incremental mode <incremental>` the default.
* Document ``--always-true`` and ``--always-false`` (:ref:`docs <always-true>`).
* Document ``follow_imports_for_stubs`` (:ref:`docs<per-module-flags>`).
* Add coroutines to :ref:`Python 3 cheat sheet <cheat-sheet-py3>`.
* Add ``None`` return/strict-optional to :ref:`common issues <annotations_needed>`.
* Clarify that ``SupportsInt`` etc. don't support arithmetic operations (see :ref:`docs <supports-int-etc>`).
- March 2018
* Publish ``mypy`` version 0.580 on PyPI.
* Allow specifying multiple packages on the command line with ``-p`` and ``-m`` flags.
* Clarify that ``SupportsInt`` etc. don't support arithmetic operations.
* Publish ``mypy`` version 0.570 on PyPI.
* Add support for :ref:`attrs_package`.
......
Metadata-Version: 2.1
Name: mypy
Version: 0.580
Version: 0.590
Summary: Optional static typing for Python
Home-page: http://www.mypy-lang.org/
Author: Jukka Lehtosalo
......
......@@ -27,6 +27,7 @@ docs/source/function_overloading.rst
docs/source/generics.rst
docs/source/getting_started.rst
docs/source/index.rst
docs/source/installed_packages.rst
docs/source/introduction.rst
docs/source/kinds_of_types.rst
docs/source/python2.rst
......@@ -62,6 +63,7 @@ mypy/experiments.py
mypy/exprtotype.py
mypy/fastparse.py
mypy/fastparse2.py
mypy/find_sources.py
mypy/fixup.py
mypy/fscache.py
mypy/fswatcher.py
......@@ -84,10 +86,15 @@ mypy/report.py
mypy/sametypes.py
mypy/scope.py
mypy/semanal.py
mypy/semanal_enum.py
mypy/semanal_namedtuple.py
mypy/semanal_newtype.py
mypy/semanal_pass1.py
mypy/semanal_pass3.py
mypy/semanal_shared.py
mypy/semanal_typeddict.py
mypy/sharedparse.py
mypy/sitepkgs.py
mypy/solve.py
mypy/stats.py
mypy/strconv.py
......@@ -143,6 +150,7 @@ mypy/test/testinfer.py
mypy/test/testmerge.py
mypy/test/testmoduleinfo.py
mypy/test/testparse.py
mypy/test/testpep561.py
mypy/test/testpythoneval.py
mypy/test/testreports.py
mypy/test/testsemanal.py
......@@ -163,6 +171,13 @@ scripts/myunit
scripts/stubgen
scripts/stubtest.py
test-data/.flake8
test-data/packages/typedpkg/setup.py
test-data/packages/typedpkg-stubs/setup.py
test-data/packages/typedpkg-stubs/typedpkg-stubs/__init__.pyi
test-data/packages/typedpkg-stubs/typedpkg-stubs/sample.pyi
test-data/packages/typedpkg/typedpkg/__init__.py
test-data/packages/typedpkg/typedpkg/py.typed
test-data/packages/typedpkg/typedpkg/sample.py
test-data/samples/bottles.py
test-data/samples/class.py
test-data/samples/cmdline.py
......@@ -413,6 +428,7 @@ typeshed/stdlib/2/commands.pyi
typeshed/stdlib/2/compileall.pyi
typeshed/stdlib/2/cookielib.pyi
typeshed/stdlib/2/decimal.pyi
typeshed/stdlib/2/dircache.pyi
typeshed/stdlib/2/dummy_thread.pyi
typeshed/stdlib/2/exceptions.pyi
typeshed/stdlib/2/fcntl.pyi
......@@ -522,8 +538,6 @@ typeshed/stdlib/2/multiprocessing/process.pyi
typeshed/stdlib/2/multiprocessing/util.pyi
typeshed/stdlib/2/os/__init__.pyi
typeshed/stdlib/2/os/path.pyi
typeshed/stdlib/2/sqlite3/__init__.pyi
typeshed/stdlib/2/sqlite3/dbapi2.pyi
typeshed/stdlib/2/wsgiref/__init__.pyi
typeshed/stdlib/2/wsgiref/types.pyi
typeshed/stdlib/2/wsgiref/validate.pyi
......@@ -633,6 +647,9 @@ typeshed/stdlib/2and3/xdrlib.pyi
typeshed/stdlib/2and3/zipfile.pyi
typeshed/stdlib/2and3/zipimport.pyi
typeshed/stdlib/2and3/zlib.pyi
typeshed/stdlib/2and3/ctypes/__init__.pyi
typeshed/stdlib/2and3/ctypes/util.pyi
typeshed/stdlib/2and3/ctypes/wintypes.pyi
typeshed/stdlib/2and3/distutils/__init__.pyi
typeshed/stdlib/2and3/distutils/archive_util.pyi
typeshed/stdlib/2and3/distutils/bcppcompiler.pyi
......@@ -693,6 +710,8 @@ typeshed/stdlib/2and3/lib2to3/pgen2/tokenize.pyi
typeshed/stdlib/2and3/logging/__init__.pyi
typeshed/stdlib/2and3/logging/config.pyi
typeshed/stdlib/2and3/logging/handlers.pyi
typeshed/stdlib/2and3/sqlite3/__init__.pyi
typeshed/stdlib/2and3/sqlite3/dbapi2.pyi
typeshed/stdlib/2and3/xml/__init__.pyi
typeshed/stdlib/2and3/xml/etree/ElementInclude.pyi
typeshed/stdlib/2and3/xml/etree/ElementPath.pyi
......@@ -796,6 +815,8 @@ typeshed/stdlib/3.4/asyncio/tasks.pyi
typeshed/stdlib/3.4/asyncio/transports.pyi
typeshed/stdlib/3.5/zipapp.pyi
typeshed/stdlib/3.6/secrets.pyi
typeshed/stdlib/3.7/contextvars.pyi
typeshed/stdlib/3.7/importlib/resources.pyi
typeshed/stdlib/3/collections/__init__.pyi
typeshed/stdlib/3/collections/abc.pyi
typeshed/stdlib/3/concurrent/__init__.pyi
......@@ -857,8 +878,6 @@ typeshed/stdlib/3/multiprocessing/queues.pyi
typeshed/stdlib/3/multiprocessing/synchronize.pyi
typeshed/stdlib/3/os/__init__.pyi
typeshed/stdlib/3/os/path.pyi
typeshed/stdlib/3/sqlite3/__init__.pyi
typeshed/stdlib/3/sqlite3/dbapi2.pyi
typeshed/stdlib/3/tkinter/__init__.pyi
typeshed/stdlib/3/tkinter/constants.pyi
typeshed/stdlib/3/tkinter/ttk.pyi
......@@ -904,9 +923,11 @@ typeshed/third_party/2/google/protobuf/message_factory.pyi
typeshed/third_party/2/google/protobuf/reflection.pyi
typeshed/third_party/2/google/protobuf/symbol_database.pyi
typeshed/third_party/2/google/protobuf/internal/__init__.pyi
typeshed/third_party/2/google/protobuf/internal/containers.pyi
typeshed/third_party/2/google/protobuf/internal/decoder.pyi
typeshed/third_party/2/google/protobuf/internal/encoder.pyi
typeshed/third_party/2/google/protobuf/internal/enum_type_wrapper.pyi
typeshed/third_party/2/google/protobuf/internal/message_listener.pyi
typeshed/third_party/2/google/protobuf/internal/wire_format.pyi
typeshed/third_party/2/kazoo/__init__.pyi
typeshed/third_party/2/kazoo/client.pyi
......@@ -997,6 +1018,7 @@ typeshed/third_party/2and3/croniter.pyi
typeshed/third_party/2and3/emoji.pyi
typeshed/third_party/2and3/mypy_extensions.pyi
typeshed/third_party/2and3/singledispatch.pyi
typeshed/third_party/2and3/termcolor.pyi
typeshed/third_party/2and3/typing_extensions.pyi
typeshed/third_party/2and3/ujson.pyi
typeshed/third_party/2and3/Crypto/__init__.pyi
......@@ -1095,6 +1117,7 @@ typeshed/third_party/2and3/boto/s3/user.pyi
typeshed/third_party/2and3/boto/s3/website.pyi
typeshed/third_party/2and3/characteristic/__init__.pyi
typeshed/third_party/2and3/click/__init__.pyi
typeshed/third_party/2and3/click/_termui_impl.pyi
typeshed/third_party/2and3/click/core.pyi
typeshed/third_party/2and3/click/decorators.pyi
typeshed/third_party/2and3/click/exceptions.pyi
......
"""This module makes it possible to use mypy as part of a Python application.
Since mypy still changes, the API was kept utterly simple and non-intrusive.
It just mimics command line activation without starting a new interpreter.
So the normal docs about the mypy command line apply.
Changes in the command line version of mypy will be immediately useable.
Just import this module and then call the 'run' function with a parameter of
type List[str], containing what normally would have been the command line
arguments to mypy.
Function 'run' returns a Tuple[str, str, int], namely
(<normal_report>, <error_report>, <exit_status>),
in which <normal_report> is what mypy normally writes to sys.stdout,
<error_report> is what mypy normally writes to sys.stderr and exit_status is
the exit status mypy normally returns to the operating system.
Any pretty formatting is left to the caller.
Trivial example of code using this module:
import sys
from mypy import api
result = api.run(sys.argv[1:])
if result[0]:
print('\nType checking report:\n')
print(result[0]) # stdout
if result[1]:
print('\nError report:\n')
print(result[1]) # stderr
print ('\nExit status:', result[2])
"""
import sys
from io import StringIO
from typing import List, Tuple
from mypy.main import main
def run(args: List[str]) -> Tuple[str, str, int]:
old_stdout = sys.stdout
new_stdout = StringIO()
sys.stdout = new_stdout
old_stderr = sys.stderr
new_stderr = StringIO()
sys.stderr = new_stderr
try:
main(None, args=args)
exit_status = 0
except SystemExit as system_exit:
exit_status = system_exit.code
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
return new_stdout.getvalue(), new_stderr.getvalue(), exit_status
"""This module makes it possible to use mypy as part of a Python application.
Since mypy still changes, the API was kept utterly simple and non-intrusive.
It just mimics command line activation without starting a new interpreter.
So the normal docs about the mypy command line apply.
Changes in the command line version of mypy will be immediately useable.
Just import this module and then call the 'run' function with a parameter of
type List[str], containing what normally would have been the command line
arguments to mypy.
Function 'run' returns a Tuple[str, str, int], namely
(<normal_report>, <error_report>, <exit_status>),
in which <normal_report> is what mypy normally writes to sys.stdout,
<error_report> is what mypy normally writes to sys.stderr and exit_status is
the exit status mypy normally returns to the operating system.
Any pretty formatting is left to the caller.
Trivial example of code using this module:
import sys
from mypy import api
result = api.run(sys.argv[1:])
if result[0]:
print('\nType checking report:\n')
print(result[0]) # stdout
if result[1]:
print('\nError report:\n')
print(result[1]) # stderr
print ('\nExit status:', result[2])
"""
import sys
from io import StringIO
from typing import List, Tuple
from mypy.main import main
def run(args: List[str]) -> Tuple[str, str, int]:
old_stdout = sys.stdout
new_stdout = StringIO()
sys.stdout = new_stdout
old_stderr = sys.stderr
new_stderr = StringIO()
sys.stderr = new_stderr
try:
main(None, args=args)
exit_status = 0
except SystemExit as system_exit:
exit_status = system_exit.code
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
return new_stdout.getvalue(), new_stderr.getvalue(), exit_status
This diff is collapsed.
......@@ -610,7 +610,9 @@ class TypeChecker(NodeVisitor[None], CheckerPluginInterface):
"""Type check a function definition."""
self.check_func_item(defn, name=defn.name())
if defn.info:
if not defn.is_dynamic():
if not defn.is_dynamic() and not defn.is_overload:
# If the definition is the implementation for an overload, the legality
# of the override has already been typechecked.
self.check_method_override(defn)
self.check_inplace_operator_method(defn)
if defn.original_def:
......
......@@ -161,6 +161,11 @@ class ExpressionChecker(ExpressionVisitor[Type]):
elif isinstance(node, TypeInfo):
# Reference to a type object.
result = type_object_type(node, self.named_type)
if isinstance(result, CallableType) and isinstance(result.ret_type, Instance):
# We need to set correct line and column
# TODO: always do this in type_object_type by passing the original context
result.ret_type.line = e.line
result.ret_type.column = e.column
if isinstance(self.type_context[-1], TypeType):
# This is the type in a Type[] expression, so substitute type
# variables with Any.
......@@ -2424,7 +2429,8 @@ class ExpressionChecker(ExpressionVisitor[Type]):
def has_member(self, typ: Type, member: str) -> bool:
"""Does type have member with the given name?"""
# TODO TupleType => also consider tuple attributes
# TODO: refactor this to use checkmember.analyze_member_access, otherwise
# these two should be carefully kept in sync.
if isinstance(typ, Instance):
return typ.type.has_readable_member(member)
if isinstance(typ, CallableType) and typ.is_type_obj():
......@@ -2436,6 +2442,14 @@ class ExpressionChecker(ExpressionVisitor[Type]):
return result
elif isinstance(typ, TupleType):
return self.has_member(typ.fallback, member)
elif isinstance(typ, TypeType):
# Type[Union[X, ...]] is always normalized to Union[Type[X], ...],
# so we don't need to care about unions here.
if isinstance(typ.item, Instance) and typ.item.type.metaclass_type is not None:
return self.has_member(typ.item.type.metaclass_type, member)
if isinstance(typ.item, AnyType):
return True
return False
else:
return False
......
......@@ -311,7 +311,7 @@ def analyze_var(name: str, var: Var, itype: Instance, info: TypeInfo, node: Cont
t = expand_type_by_instance(typ, itype)
if is_lvalue and var.is_property and not var.is_settable_property:
# TODO allow setting attributes in subclass (although it is probably an error)
msg.read_only_property(name, info, node)
msg.read_only_property(name, itype.type, node)
if is_lvalue and var.is_classvar:
msg.cant_assign_to_classvar(name, node)
result = t
......@@ -319,7 +319,7 @@ def analyze_var(name: str, var: Var, itype: Instance, info: TypeInfo, node: Cont
if is_lvalue:
if var.is_property:
if not var.is_settable_property:
msg.read_only_property(name, info, node)
msg.read_only_property(name, itype.type, node)
else:
msg.cant_assign_to_method(node)
......
......@@ -19,7 +19,7 @@ from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Tuple
import mypy.build
import mypy.errors
import mypy.main
from mypy.find_sources import create_source_list, InvalidSourceList
from mypy.server.update import FineGrainedBuildManager
from mypy.dmypy_util import STATUS_FILE, receive
from mypy.gclogger import GcLogger
......@@ -95,8 +95,6 @@ def process_start_options(flags: List[str]) -> Options:
sys.exit("dmypy: start/restart should not disable incremental mode")
if options.quick_and_dirty:
sys.exit("dmypy: start/restart should not specify quick_and_dirty mode")
if options.use_fine_grained_cache and not options.fine_grained_incremental:
sys.exit("dmypy: fine-grained cache can only be used in experimental mode")
# Our file change tracking can't yet handle changes to files that aren't
# specified in the sources list.
if options.follow_imports not in ('skip', 'error'):
......@@ -121,6 +119,8 @@ class Server:
if os.path.isfile(STATUS_FILE):
os.unlink(STATUS_FILE)
self.fscache = FileSystemCache(self.options.python_version)
options.incremental = True
options.fine_grained_incremental = True
options.show_traceback = True
......@@ -162,7 +162,14 @@ class Server:
resp = {'error': "Command is not a string"}
else:
command = data.pop('command')
resp = self.run_command(command, data)
try:
resp = self.run_command(command, data)
except Exception:
# If we are crashing, report the crash to the client
tb = traceback.format_exception(*sys.exc_info()) # type: ignore
resp = {'error': "Daemon crashed!\n" + "".join(tb)}
conn.sendall(json.dumps(resp).encode('utf8'))
raise
try:
conn.sendall(json.dumps(resp).encode('utf8'))
except OSError as err:
......@@ -214,19 +221,10 @@ class Server:
def cmd_check(self, files: Sequence[str]) -> Dict[str, object]:
"""Check a list of files."""
# TODO: Move this into check(), in case one of the args is a directory.
# Capture stdout/stderr and catch SystemExit while processing the source list.
save_stdout = sys.stdout
save_stderr = sys.stderr
try:
sys.stdout = stdout = io.StringIO()
sys.stderr = stderr = io.StringIO()
self.last_sources = mypy.main.create_source_list(files, self.options)
except SystemExit as err:
return {'out': stdout.getvalue(), 'err': stderr.getvalue(), 'status': err.code}
finally:
sys.stdout = save_stdout
sys.stderr = save_stderr
self.last_sources = create_source_list(files, self.options, self.fscache)
except InvalidSourceList as err:
return {'out': '', 'err': str(err), 'status': 2}
return self.check(self.last_sources)
def cmd_recheck(self) -> Dict[str, object]:
......@@ -238,21 +236,19 @@ class Server:
def check(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
"""Check using fine-grained incremental mode."""
if not self.fine_grained_manager:
return self.initialize_fine_grained(sources)
res = self.initialize_fine_grained(sources)
else:
return self.fine_grained_increment(sources)
res = self.fine_grained_increment(sources)
self.fscache.flush()
return res
def initialize_fine_grained(self, sources: List[mypy.build.BuildSource]) -> Dict[str, Any]:
# The file system cache we create gets passed off to
# BuildManager, and thence to FineGrainedBuildManager, which
# assumes responsibility for clearing it after updates.
fscache = FileSystemCache(self.options.python_version)
self.fswatcher = FileSystemWatcher(fscache)
self.fswatcher = FileSystemWatcher(self.fscache)
self.update_sources(sources)
try:
result = mypy.build.build(sources=sources,
options=self.options,
fscache=fscache,
fscache=self.fscache,
alt_lib_path=self.alt_lib_path)
except mypy.errors.CompileError as e:
output = ''.join(s + '\n' for s in e.messages)
......@@ -293,7 +289,6 @@ class Server:
# Stores the initial state of sources as a side effect.
self.fswatcher.find_changed()
fscache.flush()
status = 1 if messages else 0
return {'out': ''.join(s + '\n' for s in messages), 'err': '', 'status': status}
......@@ -320,9 +315,12 @@ class Server:
def find_changed(self, sources: List[mypy.build.BuildSource]) -> Tuple[List[Tuple[str, str]],
List[Tuple[str, str]]]:
changed_paths = self.fswatcher.find_changed()
# Find anything that has been added or modified
changed = [(source.module, source.path)
for source in sources
if source.path in changed_paths]
# Now find anything that has been removed from the build
modules = {source.module for source in sources}
omitted = [source for source in self.previous_sources if source.module not in modules]
removed = []
......@@ -330,6 +328,16 @@ class Server:
path = source.path
assert path
removed.append((source.module, path))
# Find anything that has had its module path change because of added or removed __init__s
last = {s.path: s.module for s in self.previous_sources}
for s in sources:
assert s.path
if s.path in last and last[s.path] != s.module:
# Mark it as removed from its old name and changed at its new name
removed.append((last[s.path], s.path))
changed.append((s.module, s.path))
return changed, removed
def cmd_hang(self) -> Dict[str, object]:
......
......@@ -294,7 +294,7 @@ class Errors:
def generate_unused_ignore_notes(self, file: str) -> None:
ignored_lines = self.ignored_lines[file]
if not self.is_typeshed_file(file):
if not self.is_typeshed_file(file) and file not in self.ignored_files:
for line in ignored_lines - self.used_ignored_lines[file]:
# Don't use report since add_error_info will ignore the error!
info = ErrorInfo(self.import_context(), file, self.current_module(), None,
......