Git Product home page Git Product logo

mypy's Introduction

mypy logo

Mypy: Static Typing for Python

Stable Version Downloads Build Status Documentation Status Chat at https://gitter.im/python/typing Checked with mypy Code style: black Linting: Ruff

Got a question?

We are always happy to answer questions! Here are some good places to ask them:

If you're just getting started, the documentation and type hints cheat sheet can also help answer questions.

If you think you've found a bug:

To report a bug or request an enhancement:

To discuss a new type system feature:

What is mypy?

Mypy is a static type checker for Python.

Type checkers help ensure that you're using variables and functions in your code correctly. With mypy, add type hints (PEP 484) to your Python programs, and mypy will warn you when you use those types incorrectly.

Python is a dynamic language, so usually you'll only see errors in your code when you attempt to run it. Mypy is a static checker, so it finds bugs in your programs without even running them!

Here is a small example to whet your appetite:

number = input("What is your favourite number?")
print("It is", number + 1)  # error: Unsupported operand types for + ("str" and "int")

Adding type hints for mypy does not interfere with the way your program would otherwise run. Think of type hints as similar to comments! You can always use the Python interpreter to run your code, even if mypy reports errors.

Mypy is designed with gradual typing in mind. This means you can add type hints to your code base slowly and that you can always fall back to dynamic typing when static typing is not convenient.

Mypy has a powerful and easy-to-use type system, supporting features such as type inference, generics, callable types, tuple types, union types, structural subtyping and more. Using mypy will make your programs easier to understand, debug, and maintain.

See the documentation for more examples and information.

In particular, see:

Quick start

Mypy can be installed using pip:

python3 -m pip install -U mypy

If you want to run the latest version of the code, you can install from the repo directly:

python3 -m pip install -U git+https://github.com/python/mypy.git
# or if you don't have 'git' installed
python3 -m pip install -U https://github.com/python/mypy/zipball/master

Now you can type-check the statically typed parts of a program like this:

mypy PROGRAM

You can always use the Python interpreter to run your statically typed programs, even if mypy reports type errors:

python3 PROGRAM

You can also try mypy in an online playground (developed by Yusuke Miyazaki). If you are working with large code bases, you can run mypy in daemon mode, that will give much faster (often sub-second) incremental updates:

dmypy run -- PROGRAM

Integrations

Mypy can be integrated into popular IDEs:

Web site and documentation

Additional information is available at the web site:

https://www.mypy-lang.org/

Jump straight to the documentation:

https://mypy.readthedocs.io/

Follow along our changelog at:

https://mypy-lang.blogspot.com/

Contributing

Help in testing, development, documentation and other tasks is highly appreciated and useful to the project. There are tasks for contributors of all experience levels.

To get started with developing mypy, see CONTRIBUTING.md.

If you need help getting started, don't hesitate to ask on gitter.

Mypyc and compiled version of mypy

Mypyc uses Python type hints to compile Python modules to faster C extensions. Mypy is itself compiled using mypyc: this makes mypy approximately 4 times faster than if interpreted!

To install an interpreted mypy instead, use:

python3 -m pip install --no-binary mypy -U mypy

To use a compiled version of a development version of mypy, directly install a binary from https://github.com/mypyc/mypy_mypyc-wheels/releases/latest.

To contribute to the mypyc project, check out https://github.com/mypyc/mypyc

mypy's People

Contributors

97littleleaf11 avatar alexwaygood avatar cdce8p avatar ddfisher avatar ecprice avatar elazarg avatar ethanhs avatar gnprice avatar gvanrossum avatar hamdanal avatar hauntsaninja avatar hughhan1 avatar ichard26 avatar ikonst avatar ilevkivskyi avatar ilinum avatar ivuk avatar jellezijlstra avatar jhance avatar jukkal avatar matthiaskramm avatar michael0x2a avatar msullivan avatar o11c avatar pkch avatar pranavrajpal avatar rwbarton avatar sobolevn avatar spkersten avatar th3charlie avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mypy's Issues

Do not allow returns with arguments in generators

The following is accepted by the compiler, even though it is not valid in Python:

def f():
    yield 1
    return 1

There should be a compile error if mixing return with an argument and yield within the same function.

Update: only disallow this in Python 2 (see below).

Use bytes and bytearray consistently in the library stubs

The use of bytes and bytearray in the library stubs is inconsistent. Some modules do not properly support bytes objects (e.g. os) even though they work in Python.

Also some Python functions accept only bytes objects, but others accept bytearrays as well. This needs to be reflected in the library stubs (however, Python documentation is not always explicit about this, which complicates the issue).

Give warning for assert (c, s)

An assertion such as

assert (c, s)

is always true, even though the programmer probably intended

assert c, s

Give a warning if using the first form (like Python does).

defining the choice of overload when more than one applies

I don't think it's completely clear what the following example should print:

class A: pass
class B(A): pass

def f(A a): print('A')
def f(B b): print('B')

f(B())

One might intuitively expect the 'best match' to be chosen, which would print 'B', but the current implementation actually chooses the 'first match', which would print 'A'. This isn't wrong per se but I think it's at least worth documenting.

Inconsistent error messages for overloaded functions

Type checking this code

def f(): pass
def g(): pass
def g(a): pass
f.x
g.x

produces these errors

t.py, line 4: function has no member "x"
t.py, line 5: object has no member "x"

Note that the error messages are different, even though both refer to functions (the first message refers to an ordinary function, the second to an overloaded function).

It would be better if the error message were consistent.

Arguments in function types should be contravariant

Currently function types are invariant with respect to argument types. This makes it impossible to use some useful and common idioms, for example:

print(list(map(str, [1, 2, 3])))

Function subtyping (and type inference, if needed) should be modified so that the above code works.

However, argument types should perhaps still be invariant in overriding to avoid complications with overloading.

Make it possible to use local stubs

Currently the stubs are only searched automatically from the directory stubs below the directory containing (the translated) mypy.py. It would be useful to also look for stubs in a directory relative to the program being type checked/run.

For example, consider the following hierarchy:

d/foo.py
d/stubs/mylib.py

Now if d/foo.py does import mylib, it should refer to the mylib.py file in the stubs directory under d. stubs is a magic directory name for stubs.

overloaded functions can get translated to invalid python

Contrived example:

def print_type(int x):
    print('int')

def print_type(x):
    print('unknown')

translates to

def print_type(x):
    def print_type1(x):
        print('int')

    def print_type2(x):
        print('unknown')

    if isinstance(x, int):
        return print_type1(x)
    elif : # <--- invalid syntax
        return print_type2(x)
    else:
        raise TypeError("Invalid argument types")

(comment added by me)

Dynamically typed __init__ with argument types rejected

If we introduce __init__ with def, the compiler complains if an argument has an explicit type:

class A:
    def __init__(self, int x): pass

t.py: In member "__init__" of class "A":
t.py, line 2: Cannot define return type for "__init__"

This should be valid, since it works for other methods and can be useful with overloading.

More generally, the return type of __init__ should be allowed to be void or any only.

Allow return without argument in generator

This code is rejected by the type checker, even though return without an argument is valid inside generator in Python:

from typing import Iterator

def f() -> Iterator[int]:
    yield 1
    return # Error

The compiler should accept the above code.

Overloading with list types does not work in modules

Consider this program

import m
m.f([])

assuming this module m:

void f(any[] x): print('list')
void f(int y): print('int')

When running the program, Python raises an exception:

File "...m.py", line 7, in f
    if isinstance(x, __builtins__.list):
AttributeError: 'dict' object has no attribute 'list'

Apparently we can't use __builtins__ to refer to the type object list. However, the above function f works if it is in the main file of a program instead of a module (strange).

Relevant discussion (Python 2 specific, though):

http://stackoverflow.com/questions/1184016/why-builtins-is-both-module-and-dict

References to built-in interfaces such as Iterable are not translated correctly

Interfaces such as Iterable and Sized that are defined in the mypy builtins are actually defined in the collections module in Python. Currently references to them are not translated correctly to Python:

class A(Sized): ...

gets translated into

class A(Sized): ...

which is invalid. It should be translated into something like this:

import collections as __collections
class A(__collections.Sized): ...

This affects all references to the interfaces, including these:

  • as base type in class or interface definition
  • as argument type in overloaded function
  • in an isinstance check

Copy type definition from local variables/methods in class definitions

It would be nice to be able to "self reference" local methods and variables/fields so that you can write the type definition once and refer to it elsewhere in the class definition.

If that's not easily doable, an informative error message would be preferable over a stack trace :-)

class A:
int b
void init(A self, A.b b):
print(b + 2)

Expected output:
b is defined as int, the print statement outputs the sum of b + 2.

Received output:

Traceback (most recent call last):
File "../../mypy-py/mypy.py", line 138, in
main()
File "../../mypy-py/mypy.py", line 52, in main
True)
File "/home/toor/mypydev/mypy-py/build.py", line 99, in build
return manager.process(UnprocessedFile(info, program_text))
File "/home/toor/mypydev/mypy-py/build.py", line 180, in process
next.process()
File "/home/toor/mypydev/mypy-py/build.py", line 516, in process
self.sem_analyzer().visit_file(self.tree, self.tree.path)
File "/home/toor/mypydev/mypy-py/semanal.py", line 170, in visit_file
d.accept(self)
File "/home/toor/mypydev/mypy-py/nodes.py", line 321, in accept
return visitor.visit_type_def(self)
File "/home/toor/mypydev/mypy-py/semanal.py", line 281, in visit_type_def
defn.defs.accept(self)
File "/home/toor/mypydev/mypy-py/nodes.py", line 386, in accept
return visitor.visit_block(self)
File "/home/toor/mypydev/mypy-py/semanal.py", line 351, in visit_block
s.accept(self)
File "/home/toor/mypydev/mypy-py/nodes.py", line 255, in accept
return visitor.visit_func_def(self)
File "/home/toor/mypydev/mypy-py/semanal.py", line 188, in visit_func_def
self.analyse_function(defn)
File "/home/toor/mypydev/mypy-py/semanal.py", line 209, in analyse_function
defn.typ.accept(self)
File "/home/toor/mypydev/mypy-py/nodes.py", line 907, in accept
return visitor.visit_annotation(self)
File "/home/toor/mypydev/mypy-py/semanal.py", line 300, in visit_annotation
ann.typ = self.anal_type(ann.typ)
File "/home/toor/mypydev/mypy-py/semanal.py", line 382, in anal_type
return t.accept(a)
File "/home/toor/mypydev/mypy-py/mtypes.py", line 208, in accept
return visitor.visit_callable(self)
File "/home/toor/mypydev/mypy-py/typeanal.py", line 81, in visit_callable
res = Callable(self.anal_array(t.arg_types),
File "/home/toor/mypydev/mypy-py/typeanal.py", line 98, in anal_array
res.append(t.accept(self))
File "/home/toor/mypydev/mypy-py/mtypes.py", line 38, in accept
return visitor.visit_unbound_type(self)
File "/home/toor/mypydev/mypy-py/typeanal.py", line 20, in visit_unbound_type
sym = self.lookup(t.name, t)
File "/home/toor/mypydev/mypy-py/semanal.py", line 704, in lookup_qualified
n = (n.node).names.get(parts[i], None)
AttributeError: 'TypeInfo' object has no attribute 'names'

Document library modules

Currently there is no documentation for Python standard library modules, other than a list of supported modules in the wiki. Users will have to rely on Python documentation. This is generally fine, but sometimes it's not obvious how some things translate to mypy. Additionally some Python library features are not supported yet in the stubs.

We should generate automatically HTML documentation based on the library stubs. They don't have to duplicate the Python library reference (at least initially; this would be good to have later in the project). There should be at least the following information per module:

  • all variables, functions, types and methods defined in the module, including their static types
  • link to relevevant information in the Python library reference (version 3.2)
  • additional notes about things that are different from Python or that might not be obvious to the reader (these notes could be stored in a separate file and merged automatically when building the HTML files)

Additionally there should be a contents page that lists all supported modules.

Support translating packages

The translator to Python should support packages (nested modules).

The type checker already supports packages.

Refactor code into packages

Currently the implementation does not use packages, because the Python translator does not support them yet (#24). Refactor the implementation to use packages.

The first step could be to translate all modules m into modules mypy.m (e.g. mypy.build). Later on, we could use a deeper hierarchy (e.g. mypy.checker.expressions, mypy.transform.functions).

Also rename mtypes to mypy.types (the name mtypes was used to avoid name clash with the types module).

Add support for decorators

Mypy currently lacks support for function and class decorators.
(Sorry if the example is wrong, still learning mypy syntax)
Ex.
Function decorate(Function f):
f.return foo():
print("hi")
return f()
@decorate
void foo():
print("hi")

Support interfaces with default method implementations

Currently interfaces with default method implementations are not supported. For example,
this code is rejected:

interface A:
    def f(self): return 1
class B(A): pass

Also, it should be an error if multiple implemented interfaces have a default implementation
for a method, but the class and its base classes don't defined the method.

Invalid Python generated for overload with optional arg

This code

void f(int x, str y='x'): print(1)
void f(str x): print(2)

f(1)
f('x')

is translated into

def f(x, *args):
    def f1(x, y='x'): print(1)
    def f2(x): print(2)

    if len(args) == 0 and isinstance(x, int) and isinstance(args[0], str):   # INVALID
        return f1(x, args[0])
    elif len(args) == 0 and isinstance(x, str):
        return f2(x)
    else:
        raise TypeError("Invalid argument types")

f(1)
f('x')

Note the # INVALID comment: the tuple index is out of range.

For optional arguments, there should 2 or more if cases in the dispatcher, for example:

...
    if len(args) == 0 and isinstance(x, int):
        return f1(x)
    elif len(args) == 1 and isinstance(x, int) and isinstance(args[0], str):
        return f1(x, args[0])
...

Support simple classes in the C back end

Add C back end support for simple statically typed classes which contain attributes only. For example, this code should work:

class A:
    int x
a = A()
a.x = 5
print(a.x)

Whitespace and comments in argument lists are sometimes omitted in translation

This code

void f(x,  # Foo
       int y):
    pass

gets translated into

def f(x, y):
    pass

Note that the line break, spaces and comment before int y are omitted. The translation should preserve the line break, whitespace and comments in this case and only remove the type int.

The translation works correctly if we remove the type int from the source program.

The Python back end inserts import statements before the module docstring and initial comment

When the Python back end inserts imports, they are always at the beginning of the generated file. This breaks module docstrings. The imports should be inserted only after the docstring.

Also imports should be inserted after an initial comment such as #!/usr/..., as a #! comment only has any significance as the first line.

Example 1:

"""docstring"""
x = Sized  # imports collections in generated Python code

Generated code:

import collections as __collections
"""docstring"""
x = __collections.Sized  # imports collections in generated Python code

Example 2:

#!/usr/bin/...
x = Sized

(the generated code is similar to example 1)

No error for bare asterisk after *args

The following code is accepted by the parser, even though Python gives a syntax error:

def f(*x, *, y = 1): pass

The code should generate a parse error.

Extra space in generated Python code

The code

void f(str na):
    pass

gets translated into

def f( na):
    pass

There should not a space before na.

Note that if na is replaced with n, the extra space is no longer generated.

It should be possible to access __doc__ attributes (etc) in statically typed code

The following code is rejected by the type checker, even though it's valid Python:

import re
print(re.__doc__)   # type check fails; no __doc__ attribute

The docstring attributes of modules, functions and classes should be accessible.

As a workaround, you can cast the module object to any:

import re
print(((any)re).__doc__)   # works

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.