Skip to content

[clean-strict-optional] Clean-up the type checking files #3957

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

Merged
merged 5 commits into from
Sep 17, 2017

Conversation

ilevkivskyi
Copy link
Member

This makes another major piece of mypy --strict-optional clean: the type checking files.
After this PR there will be only single exception left semanal.py.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

This actually looks great, but I have a bit of a preference for avoiding variable annotations if mypy can figure them out, and I think I found a whole bunch of them. There's one that looks suspicious though, I fear there's some kind of bug in mypy.

mypy/checker.py Outdated
@@ -610,7 +610,7 @@ def check_func_def(self, defn: FuncItem, typ: CallableType, name: str) -> None:
# function. In the first case, set up another reference with the
# precise type.
if isinstance(item, FuncDef):
Copy link
Member

Choose a reason for hiding this comment

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

This is just begging to be combined with the following if -- I think the whole thing can be collapsed into

if isinstance(item, FuncDef):
    fdef = item
    # Check if __init__ has an invalid, non-None return type.
    <and the rest of that block>

mypy/checker.py Outdated
self.check_getattr_method(typ, defn, name)
elif name == '__setattr__':
self.check_setattr_method(typ, defn)
if name: # Special method names
Copy link
Member

Choose a reason for hiding this comment

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

Insert a blank line before this block, and another one before the next block at the same level.

mypy/checker.py Outdated
@@ -1454,7 +1456,7 @@ def check_compatibility_super(self, lvalue: NameExpr, lvalue_type: Optional[Type
# lvalue had a type defined; this is handled by other
# parts, and all we have to worry about in that case is
# that lvalue is compatible with the base class.
compare_node = None # type: Node
compare_node = None # type: Optional[Node]
Copy link
Member

Choose a reason for hiding this comment

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

This annotation seems unnecessary (partial types do their thing here).

@@ -217,6 +218,7 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type:
elif typ.node.is_newtype:
self.msg.fail(messages.CANNOT_ISINSTANCE_NEWTYPE, e)
self.try_infer_partial_type(e)
type_context = None # type: Optional[CallableType]
Copy link
Member

Choose a reason for hiding this comment

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

And again...

@@ -201,11 +201,12 @@ def visit_call_expr(self, e: CallExpr, allow_none_return: bool = False) -> Type:
and len(e.args) == 2):
for typ in mypy.checker.flatten(e.args[1]):
if isinstance(typ, NameExpr):
node = None # type: Optional[SymbolTableNode]
Copy link
Member

Choose a reason for hiding this comment

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

Again, partial types will do their thing here.

stride = None # type:int
begin = None # type: Optional[int]
end = None # type: Optional[int]
stride = None # type: Optional[int]
Copy link
Member

Choose a reason for hiding this comment

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

These three # type annotations seem unnecessary too...

@@ -1943,6 +1960,7 @@ def visit_dict_expr(self, e: DictExpr) -> Type:
vtdef = TypeVarDef('VT', -2, [], self.object_type())
kt = TypeVarType(ktdef)
vt = TypeVarType(vtdef)
rv = None # type: Optional[Type]
Copy link
Member

Choose a reason for hiding this comment

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

Again.

@@ -630,7 +630,7 @@ class B(A): pass

"""
if isinstance(method, Overloaded):
return cast(F, Overloaded([bind_self(c, method) for c in method.items()]))
return cast(F, Overloaded([bind_self(c, original_type) for c in method.items()]))
Copy link
Member

Choose a reason for hiding this comment

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

Wow, was that a bug?

Copy link
Contributor

Choose a reason for hiding this comment

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

Indeed. I recall fixing it in at some point, but probably only on a local branch.

The reason it hadn't surface (AFAIK) is that it requires an overloaded method with generic self that's also has as bound a supertype of the class, without overlapping the other overload. This ish is a rare combination which is hard to get right anyway, and the checking for the "being a supertype" part is too strict in the case of overload, so I actually struggle to make an example where this is the only error.

from typing import TypeVar, overload

T = TypeVar('T')

class A:
    @overload
    def f(self: T) -> T: return self
    def f(self): return self

reveal_type(A().f())

result:

../tmp.py:6: error: Single overload definition, multiple required
../tmp.py:10: error: Revealed type is 'Overload(def [T] (self: T`9) -> T`9)'

Adding a valid overload is not obvious (to me).

@@ -112,7 +112,7 @@ def __init__(self, name: str, suite: 'Optional[Suite]' = None,
self.name = name
self.suite = suite
self.old_cwd = None # type: Optional[str]
self.tmpdir = None # type: Optional[tempfile.TemporaryDirectory]
self.tmpdir = None # type: Optional[tempfile.TemporaryDirectory[str]]
Copy link
Member

Choose a reason for hiding this comment

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

Totally off-topic: this would be a case where if you converted it to PEP 526 style (tmpdir: Optional[tempfile.TemporaryDirectory[str]] at the class level) it would fail at runtime, because the real tempfile module doesn't declare TemporaryDirectory as generic -- but Łukasz's PEP 563 would save the day...

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is a good case for PEP 563.

Copy link
Contributor

Choose a reason for hiding this comment

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

This has surfaced in #5087 during self-check:

mypy/test/data.py:232: error: "TemporaryDirectory" expects no type arguments, but 1 given

How did that pass before?

[mypy-mypy.checkexpr]
strict_optional = False

; historical exception
Copy link
Member

Choose a reason for hiding this comment

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

I prefer # as comment character in .ini files.

Copy link
Member

@gvanrossum gvanrossum left a comment

Choose a reason for hiding this comment

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

LG now. We need to file and investigate (in that order!) the alleged per-file strict-optional bug.

Also, the AppVeyor build failed building some xml thing -- maybe it's a flake and a retry will pass?

@gvanrossum
Copy link
Member

gvanrossum commented Sep 17, 2017 via email

@gvanrossum
Copy link
Member

No, still the same failure. :-(

@emmatyping
Copy link
Member

The issue is there is a new lxml release and there are not Windows wheels out yet, as IIRC they are provided by a third party. For now we should pin to lxml 3.8. I'll make a PR.

@emmatyping emmatyping mentioned this pull request Sep 17, 2017
@ilevkivskyi
Copy link
Member Author

OK, all tests pass now.

@ilevkivskyi ilevkivskyi merged commit 356454a into python:master Sep 17, 2017
@ilevkivskyi ilevkivskyi deleted the clean-optional-checker branch September 17, 2017 22:33
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.

4 participants