Skip to content
New issue

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

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

Already on GitHub? Sign in 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants