Git Product home page Git Product logo

mypy's Issues

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).

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).

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])
...

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.

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'

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.

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.

Support translating packages

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

The type checker already supports packages.

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

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.

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)

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)

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")

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.

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.

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).

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.

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

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.

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)

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).

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

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.

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.

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.