Skip to content
Commits on Source (6)
......@@ -4,5 +4,6 @@ recursive-include extensions *
recursive-include docs *
recursive-include mypy/typeshed *.py *.pyi
recursive-include mypy/xml *.xsd *.xslt *.css
include mypy_bootstrap.ini
include mypy_self_check.ini
include LICENSE
Metadata-Version: 2.1
Name: mypy
Version: 0.660
Version: 0.670
Summary: Optional static typing for Python
Home-page: http://www.mypy-lang.org/
Author: Jukka Lehtosalo
......@@ -25,5 +25,6 @@ Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development
Provides-Extra: dmypy
mypy (0.670-1) unstable; urgency=medium
* New upstream version
* debian/control: bump and tighten the python3-typed-ast dependency
* debian/clean: a few more directories of post build cruft
-- Michael R. Crusoe <michael.crusoe@gmail.com> Sun, 10 Feb 2019 00:19:11 -0800
mypy (0.660-5) unstable; urgency=medium
* Reporting needs python3-lxml.
......
extensions/mypy_extensions.egg-info/
.mypy_cache/
.pytest_cache/
docs/build/
mypy/__pycache__/
test-data/packages/typedpkg/build/
test-data/packages/typedpkg/dist/
test-data/packages/typedpkg/typedpkg.egg-info/
......@@ -15,7 +15,7 @@ Build-Depends: debhelper (>= 12~),
python3-setuptools,
python3-sphinx <!nodoc>,
python3-sphinx-rtd-theme <!nodoc>,
python3-typed-ast (>= 1.1.0),
python3-typed-ast (>= 1.3.1), python3-typed-ast (<< 1.4.0),
python3-psutil (>= 5.4.0),
python3-mypy-extensions,
python3-virtualenv <!nocheck>
......
......@@ -336,7 +336,7 @@ potentially problematic or redundant in some way.
a ``# type: ignore`` comment on a line that is not actually
generating an error message.
This flag, along with the ``--warn-unsued-casts`` flag, are both
This flag, along with the ``--warn-unused-casts`` flag, are both
particularly useful when you are upgrading mypy. Previously,
you may have needed to add casts or ``# type: ignore`` annotations
to work around bugs in mypy or missing stubs for 3rd party libraries.
......@@ -371,6 +371,21 @@ of the above sections.
This flag causes mypy to suppress errors caused by not being able to fully
infer the types of global and class variables.
``--allow-redefinition``
By default, mypy won't allow a variable to be redefined with an
unrelated type. This flag enables redefinion of a variable with an
arbitrary type *in some contexts*: only redefinitions within the
same block and nesting depth as the original definition are allowed.
Example where this can be useful:
.. code-block:: python
def process(items: List[str]) -> None:
# 'items' has type List[str]
items = [item.split() for item in items]
# 'items' now has type List[List[str]]
...
``--strict``
This flag mode enables all optional error checking flags. You can see the
list of flags enabled by strict mode in the full ``mypy --help`` output.
......
......@@ -5,9 +5,10 @@ The mypy configuration file
Mypy supports reading configuration settings from a file. By default
it uses the file ``mypy.ini`` with fallback to ``setup.cfg`` in the current
directory, or ``.mypy.ini`` in the user home directory if none of them are
found; the ``--config-file`` command-line flag can be used to read a different
file instead (see :ref:`--config-file <config-file-flag>`).
directory, then ``$XDG_CONFIG_HOME/mypy/config``, then
``~/.config/mypy/config``, and finally ``.mypy.ini`` in the user home directory
if none of them are found; the ``--config-file`` command-line flag can be used
to read a different file instead (see :ref:`--config-file <config-file-flag>`).
It is important to understand that there is no merging of configuration
files, as it would lead to ambiguity. The ``--config-file`` flag
......@@ -286,6 +287,12 @@ no analog available via the command line options.
``ignore_errors`` (bool, default False)
Ignores all non-fatal errors.
Miscellaneous strictness flags
------------------------------
``allow_redefinition`` (bool, default false)
Allows variables to be redefined with an arbitrary type, as long as the redefinition
is in the same block and nesting level as the original definition.
Global-only options
*******************
......@@ -424,5 +431,3 @@ Miscellaneous
``verbosity`` (integer, default 0)
Controls how much debug output will be generated. Higher numbers are more verbose.
......@@ -4,86 +4,122 @@ Getting started
===============
This chapter introduces some core concepts of mypy, including function
annotations, the ``typing`` module and library stubs. Read it carefully,
as the rest of documentation may not make much sense otherwise.
annotations, the ``typing`` module, library stubs, and more.
Installing mypy
***************
Be sure to read this chapter carefully, as the rest of the documentation
may not make much sense otherwise.
Installing and running mypy
***************************
Mypy requires Python 3.4 or later to run. Once you've
`installed Python 3 <https://www.python.org/downloads/>`_,
you can install mypy using pip:
.. code-block:: text
install mypy using pip:
python3 -m pip install mypy
.. code-block:: shell
Note that even though you need Python 3 to run ``mypy``, type checking
Python 2 code is fully supported, as discussed later in :ref:`python2`.
$ python3 -m pip install mypy
Running mypy
************
Once mypy is installed, run it by using the ``mypy`` tool:
You can type check a program by using the ``mypy`` tool, which is
basically a linter -- it checks your program for errors without actually
running it::
.. code-block:: shell
$ mypy program.py
All errors reported by mypy are essentially warnings that you are free
to ignore, if you so wish.
This command makes mypy *type check* your ``program.py`` file and print
out any errors it finds. Mypy will type check your code *statically*: this
means that it will check for errors without ever running your code, just
like a linter.
.. note::
This means that you are always free to ignore the errors mypy reports and
treat them as just warnings, if you so wish: mypy runs independently from
Python itself.
Depending on how mypy is configured, you may have to run mypy like
this::
However, if you try directly running mypy on your existing Python code, it
will most likely report little to no errors: you must add *type annotations*
to your code to take full advantage of mypy. See the section below for details.
$ python3 -m mypy program.py
.. note::
If you haven't added any type annotations to your program yet, you
should add some first, as mypy won't report many errors in unannotated
functions. Don't worry if you aren't familiar with type annotations --
we'll discuss them in detail in much of the rest of this guide.
Although you must install Python 3 to run mypy, mypy is fully capable of
type checking Python 2 code as well: just pass in the ``--py2`` flag. See
:ref:`python2` for more details.
Mypy supports many command line options that you can use to tweak how
mypy behaves. They are documented in :ref:`command-line`.
.. code-block:: shell
Function signatures
*******************
$ mypy --py2 program.py
A function without a type annotation is considered *dynamically typed* by
mypy:
Function signatures and dynamic vs static typing
************************************************
A function without type annotations is considered to be *dynamically typed* by mypy:
.. code-block:: python
def greeting(name):
return 'Hello, {}'.format(name)
return 'Hello ' + name
By default, mypy will **not** type check dynamically typed functions. This means
that with a few exceptions, mypy will not report any errors with regular unannotated Python.
You can declare the signature of a function using the Python 3
annotation syntax (Python 2 is discussed later in :ref:`python2`).
This makes the function statically typed, which causes mypy to
report type errors within the function.
This is the case even if you misuse the function: for example, mypy would currently
not report any errors if you tried running ``greeting(3)`` or ``greeting(b"Alice")``
even though those function calls would result in errors at runtime.
Here's a version of the above function that is statically typed and
will be type checked:
You can teach mypy to detect these kinds of bugs by adding *type annotations* (also
known as *type hints*). For example, you can teach mypy that ``greeting`` both accepts
and returns a string like so:
.. code-block:: python
def greeting(name: str) -> str:
return 'Hello, {}'.format(name)
return 'Hello ' + name
Now mypy will reject the following call, since the argument has an
incompatible type:
This function is now *statically typed*: mypy can use the provided type hints to detect
incorrect usages of the ``greeting`` function. For example, it will reject the following
calls since the arguments have invalid types:
.. code-block:: python
def greeting(name: str) -> str:
return 'Hello, {}'.format(name)
return 'Hello ' + name
greeting(3) # Argument 1 to "greeting" has incompatible type "int"; expected "str"
greeting(b'Alice') # Argument 1 to "greeting" has incompatible type "bytes"; expected "str"
If a function does not explicitly return a value we give the return
type as ``None``. Using a ``None`` result in a statically typed
Note that this is all still valid Python 3 code! The function annotation syntax
shown above was added to Python `as a part of Python 3.0 <pep3107_>`_.
If you are trying to type check Python 2 code, you can add type hints
using a comment-based syntax instead of the Python 3 annotation syntax.
See our section on :ref:`typing Python 2 code <python2>` for more details.
.. _pep3107: https://www.python.org/dev/peps/pep-3107/
Being able to pick whether you want a function to be dynamically or statically
typed can be very helpful. For example, if you are migrating an existing
Python codebase to use static types, it's usually easier to migrate by incrementally
adding type hints to your code rather than adding them all at once. Similarly,
when you are prototyping a new feature, it may be convenient to initially implement
the code using dynamic typing and only add type hints later once the code is more stable.
Once you are finished migrating or prototyping your code, you can make mypy warn you
if you add a dynamic function by mistake by using the ``--disallow-unchecked-defs``
flag. See :ref:`command-line` for more information on configuring mypy.
.. note::
The earlier stages of analysis performed by mypy may report errors
even for dynamically typed functions. However, you should not rely
on this, as this may change in the future.
More function signatures
************************
Here are a few more examples of adding type hints to function signatures.
If a function does not explicitly return a value, give it a return
type of ``None``. Using a ``None`` result in a statically typed
context results in a type check error:
.. code-block:: python
......@@ -93,7 +129,18 @@ context results in a type check error:
a = p() # Error: "p" does not return a value
Arguments with default values can be annotated as follows:
Make sure to remember to include ``None``: if you don't, the function
will be dynamically typed. For example:
.. code-block:: python
def f():
1 + 'x' # No static type error (dynamically typed)
def g() -> None:
1 + 'x' # Type check error (statically typed)
Arguments with default values can be annotated like so:
.. code-block:: python
......@@ -103,34 +150,53 @@ Arguments with default values can be annotated as follows:
message += '!!!'
return message
Mixing dynamic and static typing within a single file is often
useful. For example, if you are migrating existing Python code to
static typing, it may be easiest to do this incrementally, such as by
migrating a few functions at a time. Also, when prototyping a new
feature, you may decide to first implement the relevant code using
dynamic typing and only add type signatures later, when the code is
more stable.
``*args`` and ``**kwargs`` arguments can be annotated like so:
.. code-block:: python
def f():
1 + 'x' # No static type error (dynamically typed)
def stars(*args: int, **kwargs: float) -> None:
# 'args' has type 'Tuple[int, ...]' (a tuple of ints)
# 'kwargs' has type 'Dict[str, float]' (a dict of strs to floats)
for arg in args:
print(name)
for key, value in kwargs:
print(key, value)
def g() -> None:
1 + 'x' # Type check error (statically typed)
The typing module
*****************
.. note::
So far, we've added type hints that use only basic concrete types like
``str`` and ``float``. What if we want to express more complex types,
such as "a list of strings" or "an iterable of ints"?
The earlier stages of mypy, known as the semantic analysis, may
report errors even for dynamically typed functions. However, you
should not rely on this, as this may change in the future.
You can find many of these more complex static types inside of the ``typing``
module. For example, to indicate that some function can accept a list of
strings, use the ``List`` type from the ``typing`` module:
The typing module
*****************
.. code-block:: python
from typing import List
def greet_all(names: List[str]) -> None:
for name in names:
print('Hello ' + name)
names = ["Alice", "Bob", "Charlie"]
ages = [10, 20, 30]
greet_all(names) # Ok!
greet_all(ages) # Error due to incompatible types
The ``List`` type is an example of something called a *generic type*: it can
accept one or more *type parameters*. In this case, we *parameterized* ``List``
by writing ``List[str]``. This lets mypy know that ``greet_all`` accepts specifically
lists containing strings, and not lists containing ints or any other type.
In this particular case, the type signature is perhaps a little too rigid.
After all, there's no reason why this function must accept *specifically* a list --
it would run just fine if you were to pass in a tuple, a set, or any other custom iterable.
The ``typing`` module contains many definitions that are useful in
statically typed code. You typically use ``from ... import`` to import
them (we'll explain ``Iterable`` later in this document):
You can express this idea using the ``Iterable`` type instead of ``List``:
.. code-block:: python
......@@ -138,12 +204,102 @@ them (we'll explain ``Iterable`` later in this document):
def greet_all(names: Iterable[str]) -> None:
for name in names:
print('Hello, {}'.format(name))
print('Hello ' + name)
As another example, suppose you want to write a function that can accept *either*
ints or strings, but no other types. You can express this using the ``Union`` type:
.. code-block:: python
from typing import Union
def normalize_id(user_id: Union[int, str]) -> str:
if isinstance(user_id, int):
return 'user-{}'.format(100000 + user_id)
else:
return user_id
For brevity, we often omit the ``typing`` import in code examples, but
mypy will give an error if you use definitions such as ``Iterable``
Similarly, suppose that you want the function to accept only strings or None. You can
again use ``Union`` and use ``Union[str, None]`` -- or alternatively, use the type
``Optional[str]``. These two types are identical and interchangeable: ``Optional[str]``
is just a shorthand or *alias* for ``Union[str, None]``. It exists mostly as a convenience
to help function signatures look a little cleaner:
.. code-block:: python
from typing import Optional
def greeting(name: Optional[str] = None) -> str:
# Optional[str] means the same thing as Union[str, None]
if name is None:
name = 'stranger'
return 'Hello, ' + name
The ``typing`` module contains many other useful types. You can find a
quick overview by looking through the :ref:`mypy cheatsheets <overview-cheat-sheets>`
and a more detailed overview (including information on how to make your own
generic types or your own type aliases) by looking through the
:ref:`type system reference <overview-type-system-reference>`.
One final note: when adding types, the convention is to import types
using the form ``from typing import Iterable`` (as opposed to doing
just ``import typing`` or ``import typing as t`` or ``from typing import *``).
For brevity, we often omit these ``typing`` imports in code examples, but
mypy will give an error if you use types such as ``Iterable``
without first importing them.
Local type inference
********************
Once you have added type hints to a function (i.e. made it statically typed),
mypy will automatically type check that function's body. While doing so,
mypy will try and *infer* as many details as possible.
We saw an example of this in the ``normalize_id`` function above -- mypy understands
basic ``isinstance`` checks and so can infer that the ``user_id`` variable was of
type ``int`` in the if-branch and of type ``str`` in the else-branch. Similarly, mypy
was able to understand that ``name`` could not possibly be ``None`` in the ``greeting``
function above, based both on the ``name is None`` check and the variable assignment
in that if statement.
As another example, consider the following function. Mypy can type check this function
without a problem: it will use the available context and deduce that ``output`` must be
of type ``List[float]`` and that ``num`` must be of type ``float``:
.. code-block:: python
def nums_below(numbers: Iterable[float], limit: float) -> List[float]:
output = []
for num in numbers:
if num < limit:
output.append(num)
return output
Mypy will warn you if it is unable to determine the type of some variable --
for example, when assigning an empty dictionary to some global value:
.. code-block:: python
my_global_dict = {} # Error: Need type annotation for 'my_global_dict'
You can teach mypy what type ``my_global_dict`` is meant to have by giving it
a type hint. For example, if you knew this variable is supposed to be a dict
of ints to floats, you could annotate it using either variable annotations
(introduced in Python 3.6 by :ref:`PEP 526 <pep526_>`_) or using a comment-based
syntax like so:
.. code-block:: python
# If you're using Python 3.6+
my_global_dict: Dict[int, float] = {}
# If you want compatibility with older versions of Python
my_global_dict = {} # type: Dict[int, float]
.. _pep526: https://www.python.org/dev/peps/pep-0526/
.. _stubs-intro:
Library stubs and typeshed
......@@ -171,7 +327,29 @@ library module that you import. Some modules ship with stubs that mypy
can automatically find, or you can install a 3rd party module with
additional stubs (see :ref:`installed-packages` for details). You can
also :ref:`create stubs <stub-files>` easily. We discuss ways of
silencing complaints about missing stubs in :ref:`existing-code`.
silencing complaints about missing stubs in :ref:`ignore-missing-imports`.
Configuring mypy
****************
Mypy supports many command line options that you can use to tweak how
mypy behaves: see :ref:`command-line` for more details.
For example, suppose you want to make sure *all* functions within your
codebase are using static typing and make mypy report an error if you
add a dynamically-typed function by mistake. You can make mypy do this
by running mypy with the ``--disallow-untyped-defs`` flag.
Another potentially useful flag is ``--strict``, which enables many
(thought not all) of the available strictness options -- including
``--disallow-untyped-defs``.
This flag is mostly useful if you're starting a new project from scratch
and want to maintain a high degree of type safety from day one. However,
this flag will probably be too aggressive if you either plan on using
many untyped third party libraries or are trying to add static types to
a large, existing codebase. See :ref:`existing-code` for more suggestions
on how to handle the latter case.
Next steps
**********
......
......@@ -16,6 +16,8 @@ Mypy is a static type checker for Python 3 and Python 2.7.
getting_started
existing_code
.. _overview-cheat-sheets:
.. toctree::
:maxdepth: 2
:caption: Cheat sheets
......@@ -23,6 +25,8 @@ Mypy is a static type checker for Python 3 and Python 2.7.
cheat_sheet_py3
cheat_sheet
.. _overview-type-system-reference:
.. toctree::
:maxdepth: 2
:caption: Type system reference
......@@ -53,6 +57,7 @@ Mypy is a static type checker for Python 3 and Python 2.7.
mypy_daemon
installed_packages
extending_mypy
stubgen
.. toctree::
:maxdepth: 2
......
......@@ -186,7 +186,7 @@ are trying to use has done neither of these things. In that case, you can try:
:ref:`PEP 561 compliant packages <installed-packages>`.
If the module is a third party library, but you cannot find any existing
type hints nor have to time to write your own, you can *silence* the errors:
type hints nor have time to write your own, you can *silence* the errors:
1. To silence a *single* missing import error, add a `# type: ignore` at the end of the
line containing the import.
......
.. _stugen:
Automatic stub generation (stubgen)
===================================
A stub file (see `PEP 484 <https://www.python.org/dev/peps/pep-0484/#stub-files>`_)
contains only type hints for the public interface of a module, with empty
function bodies. Mypy can use a stub file instead of the real implementation
to provide type information for the module. They are useful for third-party
modules whose authors have not yet added type hints (and when no stubs are
available in typeshed) and C extension modules (which mypy can't directly
process).
Mypy includes the ``stubgen`` tool that can automatically generate
stub files (``.pyi`` files) for Python modules and C extension modules.
For example, consider this source file:
.. code-block:: python
from other_module import dynamic
BORDER_WIDTH = 15
class Window:
parent = dynamic()
def __init__(self, width, hight):
self.width = width
self.hight = hight
def create_empty() -> Window:
return Window(0, 0)
Stubgen can generate this stub file based on the above file:
.. code-block:: python
from typing import Any
BORDER_WIDTH: int = ...
class Window:
parent: Any = ...
width: Any = ...
height: Any: ...
def __init__(self, width, height) -> None: ...
def create_empty() -> Window: ...
Stubgen generates *draft* stubs. The auto-generated stub files often
require some some manual updates, and most types will default to ``Any``.
The stubs will be much more useful if you add more precise type annotations,
at least for the most commonly used functionality.
The rest of this section documents the command line interface of stubgen.
Run ``stubgen --help`` for a quick summary of options.
.. note::
The command-line flags may change between releases.
Specifying what to stub
***********************
You can give stubgen paths of the source files for which you want to
generate stubs::
$ stubgen foo.py bar.py
This generates stubs ``out/foo.pyi`` and ``out/bar.pyi``. The default
output directory ``out`` can be overridden with ``-o DIR``.
You can also pass directories, and stubgen will recursively search
them for any ``.py`` files and generate stubs for all of them::
$ stubgen my_pkg_dir
Alternatively, you can give module or package names using the
``-m`` or ``-p`` options::
$ stubgen -m foo -m bar -p my_pkg_dir
Details of the options:
``-m MODULE``, ``--module MODULE``
Generate a stub file for the given module. This flag may be repeated
multiple times.
Stubgen *will not* recursively generate stubs for any submodules of
the provided module.
``-p PACKAGE``, ``--package PACKAGE``
Generate stubs for the given package. This flag maybe repeated
multiple times.
Stubgen *will* recursively generate stubs for all submodules of
the provided package. This flag is identical to ``--module`` apart from
this behavior.
.. note::
You can't mix paths and ``-m``/``-p`` options in the same stubgen
invocation.
Specifying how to generate stubs
********************************
By default stubgen will try to import the target modules and packages.
This allows stubgen to use runtime introspection to generate stubs for C
extension modules and to improve the quality of the generated
stubs. By default, stubgen will also use mypy to perform light-weight
semantic analysis of any Python modules. Use the following flags to
alter the default behavior:
``--no-import``
Don't try to import modules. Instead use mypy's normal search mechanism to find
sources. This does not support C extension modules. This flag also disables
runtime introspection functionality, which mypy uses to find the value of
``__all__``. As result the set of exported imported names in stubs may be
incomplete. This flag is generally only useful when importing a module generates
an error for some reason.
``--parse-only``
Don't perform semantic analysis of source files. This may generate
worse stubs -- in particular, some module, class, and function aliases may
be represented as variables with the ``Any`` type. This is generally only
useful if semantic analysis causes a critical mypy error.
``--doc-dir PATH``
Try to infer better signatures by parsing .rst documentation in ``PATH``.
This may result in better stubs, but currently it only works for C extension
modules.
Additional flags
****************
``--py2``
Run stubgen in Python 2 mode (the default is Python 3 mode).
``--ignore-errors``
If an exception was raised during stub generation, continue to process any
remaining modules instead of immediately failing with an error.
``--include-private``
Include definitions that are considered private in stubs (with names such
as ``_foo`` with single leading underscore and no trailing underscores).
``--search-path PATH``
Specify module search directories, separated by colons (only used if
``--no-import`` is given).
``--python-executable PATH``
Use Python interpreter at ``PATH`` for importing modules and runtime
introspection. This has no effect with ``--no-import``, and this only works
in Python 2 mode. In Python 3 mode the Python interpreter used to run stubgen
will always be used.
``-o PATH``, ``--output PATH``
Change the output directory. By default the stubs are written in the
``./out`` directory. The output directory will be created if it doesn't
exist. Existing stubs in the output directory will be overwritten without
warning.
Metadata-Version: 2.1
Name: mypy
Version: 0.660
Version: 0.670
Summary: Optional static typing for Python
Home-page: http://www.mypy-lang.org/
Author: Jukka Lehtosalo
......@@ -25,5 +25,6 @@ Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Topic :: Software Development
Provides-Extra: dmypy
LICENSE
MANIFEST.in
README.md
mypy_bootstrap.ini
mypy_self_check.ini
setup.cfg
setup.py
......@@ -38,6 +39,7 @@ docs/source/protocols.rst
docs/source/python2.rst
docs/source/python36.rst
docs/source/running_mypy.rst
docs/source/stubgen.rst
docs/source/stubs.rst
docs/source/supported_python_features.rst
docs/source/type_inference_and_annotations.rst
......@@ -82,6 +84,7 @@ mypy/main.py
mypy/maptype.py
mypy/meet.py
mypy/memprofile.py
mypy/message_registry.py
mypy/messages.py
mypy/metastore.py
mypy/modulefinder.py
......@@ -93,6 +96,7 @@ mypy/options.py
mypy/parse.py
mypy/plugin.py
mypy/reachability.py
mypy/renaming.py
mypy/report.py
mypy/sametypes.py
mypy/scope.py
......@@ -110,6 +114,7 @@ mypy/solve.py
mypy/state.py
mypy/stats.py
mypy/strconv.py
mypy/stubdoc.py
mypy/stubgen.py
mypy/stubgenc.py
mypy/stubutil.py
......@@ -131,6 +136,17 @@ mypy.egg-info/dependency_links.txt
mypy.egg-info/entry_points.txt
mypy.egg-info/requires.txt
mypy.egg-info/top_level.txt
mypy/newsemanal/__init__.py
mypy/newsemanal/semanal.py
mypy/newsemanal/semanal_enum.py
mypy/newsemanal/semanal_main.py
mypy/newsemanal/semanal_namedtuple.py
mypy/newsemanal/semanal_newtype.py
mypy/newsemanal/semanal_pass1.py
mypy/newsemanal/semanal_pass3.py
mypy/newsemanal/semanal_shared.py
mypy/newsemanal/semanal_typeddict.py
mypy/newsemanal/typeanal.py
mypy/plugins/__init__.py
mypy/plugins/attrs.py
mypy/plugins/common.py
......@@ -160,7 +176,6 @@ mypy/test/testdaemon.py
mypy/test/testdeps.py
mypy/test/testdiff.py
mypy/test/testerrorstream.py
mypy/test/testextensions.py
mypy/test/testfinegrained.py
mypy/test/testfinegrainedcache.py
mypy/test/testgraph.py
......@@ -915,6 +930,24 @@ mypy/typeshed/third_party/2and3/dateutil/rrule.pyi
mypy/typeshed/third_party/2and3/dateutil/tz/__init__.pyi
mypy/typeshed/third_party/2and3/dateutil/tz/_common.pyi
mypy/typeshed/third_party/2and3/dateutil/tz/tz.pyi
mypy/typeshed/third_party/2and3/flask/__init__.pyi
mypy/typeshed/third_party/2and3/flask/app.pyi
mypy/typeshed/third_party/2and3/flask/blueprints.pyi
mypy/typeshed/third_party/2and3/flask/cli.pyi
mypy/typeshed/third_party/2and3/flask/config.pyi
mypy/typeshed/third_party/2and3/flask/ctx.pyi
mypy/typeshed/third_party/2and3/flask/debughelpers.pyi
mypy/typeshed/third_party/2and3/flask/globals.pyi
mypy/typeshed/third_party/2and3/flask/helpers.pyi
mypy/typeshed/third_party/2and3/flask/logging.pyi
mypy/typeshed/third_party/2and3/flask/sessions.pyi
mypy/typeshed/third_party/2and3/flask/signals.pyi
mypy/typeshed/third_party/2and3/flask/templating.pyi
mypy/typeshed/third_party/2and3/flask/testing.pyi
mypy/typeshed/third_party/2and3/flask/views.pyi
mypy/typeshed/third_party/2and3/flask/wrappers.pyi
mypy/typeshed/third_party/2and3/flask/json/__init__.pyi
mypy/typeshed/third_party/2and3/flask/json/tag.pyi
mypy/typeshed/third_party/2and3/google/__init__.pyi
mypy/typeshed/third_party/2and3/google/protobuf/__init__.pyi
mypy/typeshed/third_party/2and3/google/protobuf/any_pb2.pyi
......@@ -1297,12 +1330,14 @@ test-data/unit/check-literal.test
test-data/unit/check-modules.test
test-data/unit/check-multiple-inheritance.test
test-data/unit/check-namedtuple.test
test-data/unit/check-newsemanal.test
test-data/unit/check-newsyntax.test
test-data/unit/check-newtype.test
test-data/unit/check-optional.test
test-data/unit/check-overloading.test
test-data/unit/check-protocols.test
test-data/unit/check-python2.test
test-data/unit/check-redefine.test
test-data/unit/check-selftype.test
test-data/unit/check-semanal-error.test
test-data/unit/check-serialize.test
......@@ -1423,6 +1458,7 @@ test-data/unit/plugins/arg_names.py
test-data/unit/plugins/attrhook.py
test-data/unit/plugins/badreturn.py
test-data/unit/plugins/badreturn2.py
test-data/unit/plugins/callable_instance.py
test-data/unit/plugins/class_callable.py
test-data/unit/plugins/common_api_incremental.py
test-data/unit/plugins/customentry.py
......
typed-ast<1.3.0,>=1.2.0
typed-ast<1.4.0,>=1.3.1
mypy_extensions<0.5.0,>=0.4.0
[:python_version < "3.5"]
......
This diff is collapsed.
This diff is collapsed.
......@@ -32,7 +32,7 @@ from mypy.nodes import (
DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr,
YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr,
TypeAliasExpr, BackquoteExpr, EnumCallExpr, TypeAlias, SymbolNode,
ARG_POS, ARG_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2, MODULE_REF, LITERAL_TYPE, REVEAL_TYPE
ARG_POS, ARG_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE
)
from mypy.literals import literal
from mypy import nodes
......@@ -41,7 +41,7 @@ from mypy import types
from mypy.sametypes import is_same_type
from mypy.erasetype import replace_meta_vars, erase_type
from mypy.messages import MessageBuilder
from mypy import messages
from mypy import message_registry
from mypy.infer import infer_type_arguments, infer_function_type_arguments
from mypy import join
from mypy.meet import narrow_declared_type
......@@ -84,8 +84,8 @@ def extract_refexpr_names(expr: RefExpr) -> Set[str]:
Note that currently, the only two subclasses of RefExpr are NameExpr and
MemberExpr."""
output = set() # type: Set[str]
while expr.kind == MODULE_REF or expr.fullname is not None:
if expr.kind == MODULE_REF and expr.fullname is not None:
while isinstance(expr.node, MypyFile) or expr.fullname is not None:
if isinstance(expr.node, MypyFile) and expr.fullname is not None:
# If it's None, something's wrong (perhaps due to an
# import cycle or a suppressed error). For now we just
# skip it.
......@@ -395,7 +395,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if (isinstance(tp, CallableType) and tp.is_type_obj() and
tp.type_object().is_protocol and
not tp.type_object().runtime_protocol):
self.chk.fail(messages.RUNTIME_PROTOCOL_EXPECTED, e)
self.chk.fail(message_registry.RUNTIME_PROTOCOL_EXPECTED, e)
def check_protocol_issubclass(self, e: CallExpr) -> None:
for expr in mypy.checker.flatten(e.args[1]):
......@@ -434,7 +434,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
return self.check_typeddict_call_with_kwargs(
callee, OrderedDict(), context)
self.chk.fail(messages.INVALID_TYPEDDICT_ARGS, context)
self.chk.fail(message_registry.INVALID_TYPEDDICT_ARGS, context)
return AnyType(TypeOfAny.from_error)
def check_typeddict_call_with_dict(self, callee: TypedDictType,
......@@ -446,7 +446,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
for item_name_expr, item_arg in kwargs.items:
if not isinstance(item_name_expr, StrExpr):
key_context = item_name_expr or item_arg
self.chk.fail(messages.TYPEDDICT_KEY_MUST_BE_STRING_LITERAL, key_context)
self.chk.fail(message_registry.TYPEDDICT_KEY_MUST_BE_STRING_LITERAL, key_context)
return AnyType(TypeOfAny.from_error)
item_names.append(item_name_expr.value)
......@@ -472,7 +472,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
item_value = kwargs[item_name]
self.chk.check_simple_assignment(
lvalue_type=item_expected_type, rvalue=item_value, context=item_value,
msg=messages.INCOMPATIBLE_TYPES,
msg=message_registry.INCOMPATIBLE_TYPES,
lvalue_name='TypedDict item "{}"'.format(item_name),
rvalue_name='expression')
......@@ -705,8 +705,12 @@ class ExpressionChecker(ExpressionVisitor[Type]):
False, False, False, self.msg,
original_type=callee, chk=self.chk,
in_literal_context=self.is_literal_context())
callable_name = callee.type.fullname() + ".__call__"
# Apply method signature hook, if one exists
call_function = self.transform_callee_type(
callable_name, call_function, args, arg_kinds, context, arg_names, callee)
return self.check_call(call_function, args, arg_kinds, context, arg_names,
callable_node, arg_messages)
callable_node, arg_messages, callable_name, callee)
elif isinstance(callee, TypeVarType):
return self.check_call(callee.upper_bound, args, arg_kinds, context, arg_names,
callable_node, arg_messages)
......@@ -757,7 +761,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
elif (callee.is_type_obj() and callee.type_object().is_protocol
# Exception for Type[...]
and not callee.from_type_type):
self.chk.fail(messages.CANNOT_INSTANTIATE_PROTOCOL
self.chk.fail(message_registry.CANNOT_INSTANTIATE_PROTOCOL
.format(callee.type_object().name()), context)
formal_to_actual = map_actuals_to_formals(
......@@ -1005,7 +1009,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if isinstance(first_arg, (NoneTyp, UninhabitedType)):
inferred_args[0] = self.named_type('builtins.str')
elif not first_arg or not is_subtype(self.named_type('builtins.str'), first_arg):
self.msg.fail(messages.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE,
self.msg.fail(message_registry.KEYWORD_ARGUMENT_REQUIRES_STR_KEY_TYPE,
context)
else:
# In dynamically typed functions use implicit 'Any' types for
......@@ -1853,6 +1857,10 @@ class ExpressionChecker(ExpressionVisitor[Type]):
def visit_op_expr(self, e: OpExpr) -> Type:
"""Type check a binary operator expression."""
if e.op == 'in':
self.accept(e.right)
self.accept(e.left)
return self.bool_type()
if e.op == 'and' or e.op == 'or':
return self.check_boolean_op(e, e)
if e.op == '*' and isinstance(e.left, ListExpr):
......@@ -1886,6 +1894,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
That is, 'a < b > c == d' is check as 'a < b and b > c and c == d'
"""
result = None # type: Optional[Type]
sub_result = None # type: Optional[Type]
# Check each consecutive operand pair and their operator
for left, right, operator in zip(e.operands, e.operands[1:], e.operators):
......@@ -1900,8 +1909,9 @@ class ExpressionChecker(ExpressionVisitor[Type]):
# are just to verify whether something is valid typing wise).
local_errors = self.msg.copy()
local_errors.disable_count = 0
sub_result, method_type = self.check_method_call_by_name(
_, method_type = self.check_method_call_by_name(
'__contains__', right_type, [left], [ARG_POS], e, local_errors)
sub_result = self.bool_type()
if isinstance(right_type, PartialType):
# We don't really know if this is an error or not, so just shut up.
pass
......@@ -1915,13 +1925,10 @@ class ExpressionChecker(ExpressionVisitor[Type]):
[None],
self.bool_type(),
self.named_type('builtins.function'))
sub_result = self.bool_type()
if not is_subtype(left_type, itertype):
self.msg.unsupported_operand_types('in', left_type, right_type, e)
else:
self.msg.add_errors(local_errors)
if operator == 'not in':
sub_result = self.bool_type()
elif operator in nodes.op_methods:
method = self.get_operator_method(operator)
sub_result, method_type = self.check_op(method, left_type, right, e,
......@@ -2402,7 +2409,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if n >= 0 and n < len(left_type.items):
return left_type.items[n]
else:
self.chk.fail(messages.TUPLE_INDEX_OUT_OF_RANGE, e)
self.chk.fail(message_registry.TUPLE_INDEX_OUT_OF_RANGE, e)
return AnyType(TypeOfAny.from_error)
else:
return self.nonliteral_tuple_index_helper(left_type, index)
......@@ -2444,7 +2451,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
expected_type = UnionType.make_union([self.named_type('builtins.int'),
self.named_type('builtins.slice')])
if not self.chk.check_subtype(index_type, expected_type, index,
messages.INVALID_TUPLE_INDEX_TYPE,
message_registry.INVALID_TUPLE_INDEX_TYPE,
'actual type', 'expected type'):
return AnyType(TypeOfAny.from_error)
else:
......@@ -2553,14 +2560,14 @@ class ExpressionChecker(ExpressionVisitor[Type]):
tp = type_object_type(item.type, self.named_type)
return self.apply_type_arguments_to_callable(tp, item.args, tapp)
else:
self.chk.fail(messages.ONLY_CLASS_APPLICATION, tapp)
self.chk.fail(message_registry.ONLY_CLASS_APPLICATION, tapp)
return AnyType(TypeOfAny.from_error)
# Type application of a normal generic class in runtime context.
# This is typically used as `x = G[int]()`.
tp = self.accept(tapp.expr)
if isinstance(tp, (CallableType, Overloaded)):
if not tp.is_type_obj():
self.chk.fail(messages.ONLY_CLASS_APPLICATION, tapp)
self.chk.fail(message_registry.ONLY_CLASS_APPLICATION, tapp)
return self.apply_type_arguments_to_callable(tp, tapp.types, tapp)
if isinstance(tp, AnyType):
return AnyType(TypeOfAny.from_another_any, source_any=tp)
......@@ -2888,7 +2895,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
return callable_ctx, None
if callable_ctx.arg_kinds != arg_kinds:
# Incompatible context; cannot use it to infer types.
self.chk.fail(messages.CANNOT_INFER_LAMBDA_TYPE, e)
self.chk.fail(message_registry.CANNOT_INFER_LAMBDA_TYPE, e)
return None, None
return callable_ctx, callable_ctx
......@@ -2902,15 +2909,15 @@ class ExpressionChecker(ExpressionVisitor[Type]):
def check_super_arguments(self, e: SuperExpr) -> None:
"""Check arguments in a super(...) call."""
if ARG_STAR in e.call.arg_kinds:
self.chk.fail(messages.SUPER_VARARGS_NOT_SUPPORTED, e)
self.chk.fail(message_registry.SUPER_VARARGS_NOT_SUPPORTED, e)
elif e.call.args and set(e.call.arg_kinds) != {ARG_POS}:
self.chk.fail(messages.SUPER_POSITIONAL_ARGS_REQUIRED, e)
self.chk.fail(message_registry.SUPER_POSITIONAL_ARGS_REQUIRED, e)
elif len(e.call.args) == 1:
self.chk.fail(messages.SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED, e)
self.chk.fail(message_registry.SUPER_WITH_SINGLE_ARG_NOT_SUPPORTED, e)
elif len(e.call.args) > 2:
self.chk.fail(messages.TOO_MANY_ARGS_FOR_SUPER, e)
self.chk.fail(message_registry.TOO_MANY_ARGS_FOR_SUPER, e)
elif self.chk.options.python_version[0] == 2 and len(e.call.args) == 0:
self.chk.fail(messages.TOO_FEW_ARGS_FOR_SUPER, e)
self.chk.fail(message_registry.TOO_FEW_ARGS_FOR_SUPER, e)
elif len(e.call.args) == 2:
type_obj_type = self.accept(e.call.args[0])
instance_type = self.accept(e.call.args[1])
......@@ -2926,7 +2933,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if not isinstance(item, Instance):
# A complicated type object type. Too tricky, give up.
# TODO: Do something more clever here.
self.chk.fail(messages.UNSUPPORTED_ARG_1_FOR_SUPER, e)
self.chk.fail(message_registry.UNSUPPORTED_ARG_1_FOR_SUPER, e)
return
type_info = item.type
elif isinstance(type_obj_type, AnyType):
......@@ -2942,19 +2949,19 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if not isinstance(instance_type, (Instance, TupleType)):
# Too tricky, give up.
# TODO: Do something more clever here.
self.chk.fail(messages.UNSUPPORTED_ARG_2_FOR_SUPER, e)
self.chk.fail(message_registry.UNSUPPORTED_ARG_2_FOR_SUPER, e)
return
if isinstance(instance_type, TupleType):
# Needed for named tuples and other Tuple[...] subclasses.
instance_type = instance_type.fallback
if type_info not in instance_type.type.mro:
self.chk.fail(messages.SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1, e)
self.chk.fail(message_registry.SUPER_ARG_2_NOT_INSTANCE_OF_ARG_1, e)
elif isinstance(instance_type, TypeType) or (isinstance(instance_type, FunctionLike)
and instance_type.is_type_obj()):
# TODO: Check whether this is a valid type object here.
pass
elif not isinstance(instance_type, AnyType):
self.chk.fail(messages.UNSUPPORTED_ARG_2_FOR_SUPER, e)
self.chk.fail(message_registry.UNSUPPORTED_ARG_2_FOR_SUPER, e)
def analyze_super(self, e: SuperExpr, is_lvalue: bool) -> Type:
"""Type check a super expression."""
......@@ -2973,7 +2980,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if not self.chk.in_checked_function():
return AnyType(TypeOfAny.unannotated)
if self.chk.scope.active_class() is not None:
self.chk.fail(messages.SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED, e)
self.chk.fail(message_registry.SUPER_OUTSIDE_OF_METHOD_NOT_SUPPORTED, e)
return AnyType(TypeOfAny.from_error)
method = self.chk.scope.top_function()
assert method is not None
......@@ -2981,7 +2988,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
# super() in a function with empty args is an error; we
# need something in declared_self.
if not args:
self.chk.fail(messages.SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED, e)
self.chk.fail(message_registry.SUPER_ENCLOSING_POSITIONAL_ARGS_REQUIRED, e)
return AnyType(TypeOfAny.from_error)
declared_self = args[0].variable.type or fill_typevars(e.info)
return analyze_member_access(name=e.name,
......@@ -3006,7 +3013,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if index:
t = self.accept(index)
self.chk.check_subtype(t, expected,
index, messages.INVALID_SLICE_INDEX)
index, message_registry.INVALID_SLICE_INDEX)
return self.named_type('builtins.slice')
def visit_list_comprehension(self, e: ListComprehension) -> Type:
......@@ -3277,11 +3284,11 @@ class ExpressionChecker(ExpressionVisitor[Type]):
if e.expr is None:
if (not isinstance(expected_item_type, (NoneTyp, AnyType))
and self.chk.in_checked_function()):
self.chk.fail(messages.YIELD_VALUE_EXPECTED, e)
self.chk.fail(message_registry.YIELD_VALUE_EXPECTED, e)
else:
actual_item_type = self.accept(e.expr, expected_item_type)
self.chk.check_subtype(actual_item_type, expected_item_type, e,
messages.INCOMPATIBLE_TYPES_IN_YIELD,
message_registry.INCOMPATIBLE_TYPES_IN_YIELD,
'actual type', 'expected type')
return self.chk.get_generator_receive_type(return_type, False)
......@@ -3292,7 +3299,8 @@ class ExpressionChecker(ExpressionVisitor[Type]):
actual_type = self.accept(e.expr, expected_type)
if isinstance(actual_type, AnyType):
return AnyType(TypeOfAny.from_another_any, source_any=actual_type)
return self.check_awaitable_expr(actual_type, e, messages.INCOMPATIBLE_TYPES_IN_AWAIT)
return self.check_awaitable_expr(actual_type, e,
message_registry.INCOMPATIBLE_TYPES_IN_AWAIT)
def check_awaitable_expr(self, t: Type, ctx: Context, msg: str) -> Type:
"""Check the argument to `await` and extract the type of value.
......@@ -3337,8 +3345,8 @@ class ExpressionChecker(ExpressionVisitor[Type]):
self.chk.msg.yield_from_invalid_operand_type(subexpr_type, e)
iter_type = AnyType(TypeOfAny.from_error)
else:
iter_type = self.check_awaitable_expr(subexpr_type, e,
messages.INCOMPATIBLE_TYPES_IN_YIELD_FROM)
iter_type = self.check_awaitable_expr(
subexpr_type, e, message_registry.INCOMPATIBLE_TYPES_IN_YIELD_FROM)
# Check that the iterator's item type matches the type yielded by the Generator function
# containing this `yield from` expression.
......@@ -3346,7 +3354,7 @@ class ExpressionChecker(ExpressionVisitor[Type]):
actual_item_type = self.chk.get_generator_yield_type(iter_type, False)
self.chk.check_subtype(actual_item_type, expected_item_type, e,
messages.INCOMPATIBLE_TYPES_IN_YIELD_FROM,
message_registry.INCOMPATIBLE_TYPES_IN_YIELD_FROM,
'actual type', 'expected type')
# Determine the type of the entire yield from expression.
......
......@@ -9,7 +9,8 @@ from mypy.types import (
)
from mypy.nodes import (
TypeInfo, FuncBase, Var, FuncDef, SymbolNode, Context, MypyFile, TypeVarExpr,
ARG_POS, ARG_STAR, ARG_STAR2, Decorator, OverloadedFuncDef, TypeAlias, TempNode
ARG_POS, ARG_STAR, ARG_STAR2, Decorator, OverloadedFuncDef, TypeAlias, TempNode,
is_final_node
)
from mypy.messages import MessageBuilder
from mypy.maptype import map_instance_to_supertype
......@@ -18,7 +19,7 @@ from mypy.infer import infer_type_arguments
from mypy.typevars import fill_typevars
from mypy.plugin import AttributeContext
from mypy.typeanal import set_any_tvars
from mypy import messages
from mypy import message_registry
from mypy import subtypes
from mypy import meet
......@@ -147,7 +148,7 @@ def analyze_instance_member_access(name: str,
if name == '__init__' and not mx.is_super:
# Accessing __init__ in statically typed code would compromise
# type safety unless used via super().
mx.msg.fail(messages.CANNOT_ACCESS_INIT, mx.context)
mx.msg.fail(message_registry.CANNOT_ACCESS_INIT, mx.context)
return AnyType(TypeOfAny.from_error)
# The base object has an instance type.
......@@ -405,7 +406,7 @@ def analyze_descriptor_access(instance_type: Type,
dunder_get = descriptor_type.type.get_method('__get__')
if dunder_get is None:
msg.fail(messages.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context)
msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context)
return AnyType(TypeOfAny.from_error)
function = function_type(dunder_get, builtin_type('builtins.function'))
......@@ -432,7 +433,7 @@ def analyze_descriptor_access(instance_type: Type,
return inferred_dunder_get_type
if not isinstance(inferred_dunder_get_type, CallableType):
msg.fail(messages.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context)
msg.fail(message_registry.DESCRIPTOR_GET_NOT_CALLABLE.format(descriptor_type), context)
return AnyType(TypeOfAny.from_error)
return inferred_dunder_get_type.ret_type
......@@ -586,12 +587,12 @@ def analyze_class_attribute_access(itype: Instance,
if is_method:
mx.msg.cant_assign_to_method(mx.context)
if isinstance(node.node, TypeInfo):
mx.msg.fail(messages.CANNOT_ASSIGN_TO_TYPE, mx.context)
mx.msg.fail(message_registry.CANNOT_ASSIGN_TO_TYPE, mx.context)
# If a final attribute was declared on `self` in `__init__`, then it
# can't be accessed on the class object.
if node.implicit and isinstance(node.node, Var) and node.node.is_final:
mx.msg.fail(messages.CANNOT_ACCESS_FINAL_INSTANCE_ATTR
mx.msg.fail(message_registry.CANNOT_ACCESS_FINAL_INSTANCE_ATTR
.format(node.node.name()), mx.context)
# An assignment to final attribute on class object is also always an error,
......@@ -609,7 +610,7 @@ def analyze_class_attribute_access(itype: Instance,
assert isinstance(symnode, Var)
return mx.chk.handle_partial_var_type(t, mx.is_lvalue, symnode, mx.context)
if not is_method and (isinstance(t, TypeVarType) or get_type_vars(t)):
mx.msg.fail(messages.GENERIC_INSTANCE_VAR_CLASS_ACCESS, mx.context)
mx.msg.fail(message_registry.GENERIC_INSTANCE_VAR_CLASS_ACCESS, mx.context)
is_classmethod = ((is_decorated and cast(Decorator, node.node).func.is_class)
or (isinstance(node.node, FuncBase) and node.node.is_class))
result = add_class_tvars(t, itype, is_classmethod, mx.builtin_type, mx.original_type)
......@@ -622,7 +623,7 @@ def analyze_class_attribute_access(itype: Instance,
return AnyType(TypeOfAny.special_form)
if isinstance(node.node, TypeVarExpr):
mx.msg.fail(messages.CANNOT_USE_TYPEVAR_AS_EXPRESSION.format(
mx.msg.fail(message_registry.CANNOT_USE_TYPEVAR_AS_EXPRESSION.format(
itype.type.name(), name), mx.context)
return AnyType(TypeOfAny.from_error)
......@@ -895,8 +896,3 @@ def erase_to_bound(t: Type) -> Type:
if isinstance(t.item, TypeVarType):
return TypeType.make_normalized(t.item.upper_bound)
return t
def is_final_node(node: Optional[SymbolNode]) -> bool:
"""Check whether `node` corresponds to a final attribute."""
return isinstance(node, (Var, FuncDef, OverloadedFuncDef, Decorator)) and node.is_final