Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Make type function return Type[T] #1787

Merged

Conversation

Michael0x2a
Copy link
Collaborator

This commit is a fix for #1758 -- it special-cases the single constructor type builtin function within mypy so it returns an instance of typing.Type rather then just the generic type object.

It adds a special case within mypy rather then modifying the definition within Typeshed, but since type is defined to be a class and not a function definition in Typeshed, it was unclear how I could implement this change by only modifying Typeshed.

This commit doesn't handle the x.__class__ attribute -- it still returns type.

This commit is a fix for python#1758 -- it special-cases the single
constructor `type` builtin function within mypy so it returns an
instance of `typing.Type` rather then just the generic `type` object.
@@ -250,6 +250,11 @@ def check_call(self, callee: Type, args: List[Node],
self.check_argument_types(arg_types, arg_kinds, callee,
formal_to_actual, context,
messages=arg_messages)

ret_val_is_type_obj = is_equivalent(callee.ret_type, self.named_type('builtins.type'))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a pretty expensive call, and this case rarely triggers, so the time is usually wasted. I suggest testing the simpler conditions first and doing this call last.

@@ -250,6 +250,11 @@ def check_call(self, callee: Type, args: List[Node],
self.check_argument_types(arg_types, arg_kinds, callee,
formal_to_actual, context,
messages=arg_messages)

if callee.is_type_obj() and (len(arg_types) == 1) and \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PEP 8 conformant way to break up such a line is

if (<long condition> and
        <another long condition> and
        <you get the point>):
    <body>

Note that you have to indent the continuations an extra 4 spaces or you'll run afoul of some other PEP 8 recommendation.

(Following some debate, it's also okay to put the and at the start of the line -- mypy is inconsistent about this anyways, so do what you think is best or what you see nearby. :-)

@gvanrossum gvanrossum merged commit c5ff475 into python:master Jul 3, 2016
@gvanrossum
Copy link
Member

Whee!

@gvanrossum
Copy link
Member

There's a regression here. I've got an example:

from typing import *

class C:
  def f(self) -> None:
    print(type(self) == C)

This gives:

__tmp__.py: note: In member "f" of class "C":
__tmp__.py:5: error: Too few arguments for "__eq__" of "object"

@Michael0x2a
Copy link
Collaborator Author

Michael0x2a commented Jul 5, 2016

A simpler test case for the regression:

type(3) == int

This causes the following errors:

experiments/test1.py:1: error: Too few arguments for "__eq__" of "int"
experiments/test1.py:1: error: Unsupported operand types for == ("int" and "int")

After some probing, this issue seems to be a manifestation of a pre-existing bug in mypy. The following program throws the exact same errors when I tried running it against both the current version of mypy and a version before the merge:

int == int

Swapping out int with a custom class results in basically the same error. For example,

class G: pass

G == G

...results in:

experiments/test.py:3: error: Too few arguments for "__eq__" of "object"

The problem seems to be with the analyze_member_access function in mypy/checkmember.py; I'll investigate further.

Michael0x2a pushed a commit to Michael0x2a/mypy that referenced this pull request Jul 5, 2016
This commit introduces a workaround to fix the bug discussed in
python#1787

Previously, code where you compared two types (eg `int == int`) would
cause mypy to incorrectly report a "too few arguments" error.
Michael0x2a pushed a commit to Michael0x2a/mypy that referenced this pull request Jul 8, 2016
This commit introduces a workaround to fix the bug discussed in
python#1787

Previously, code where you compared two types (eg `int == int`) would
cause mypy to incorrectly report a "too few arguments" error.
ddfisher pushed a commit that referenced this pull request Jul 8, 2016
This commit introduces a workaround to fix the bug discussed in #1787

Previously, code where you compared two types (eg `int == int` or `int != int`) would cause mypy to incorrectly report a "too few arguments" error.
@Michael0x2a Michael0x2a deleted the make-type-func-return-specific-type branch July 21, 2016 20:54
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants