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

stubgen doesn't add import for typing.Any when function signature has unannotated arguments #7090

Closed
hoefling opened this issue Jun 28, 2019 · 1 comment · Fixed by #7208

Comments

@hoefling
Copy link
Contributor

commented Jun 28, 2019

I'm pretty much sure the description is dumb, but not sure how to properly describe it. Let the tests speak for themselves:

[case testFunctionPartiallyAnnotated]
def f(x) -> None:
    pass

def g(x, y: str):
    pass

class A:
    def f(self, x) -> None:
        pass

[out]
from typing import Any

def f(x: Any) -> None: ...
def g(x: Any, y: str) -> Any: ...

class A:
    def f(self, x: Any) -> None: ...

Test run yields:

$ pytest mypy/test/teststubgen.py::StubgenPythonSuite::testFunctionPartiallyAnnotated -v -n0
=================================== test session starts ===================================
platform linux -- Python 3.6.8, pytest-4.6.3, py-1.8.0, pluggy-0.12.0 -- /home/hoefling/projects/.venvs/mypy-py36/bin/python3.6
cachedir: .pytest_cache
rootdir: /home/hoefling/projects/python/mypy, inifile: pytest.ini
plugins: cov-2.7.1, xdist-1.29.0, forked-1.0.2
collected 1 item                                                                          

mypy/test/teststubgen.py::StubgenPythonSuite::testFunctionPartiallyAnnotated FAILED [100%]

======================================== FAILURES =========================================
_____________________________ testFunctionPartiallyAnnotated ______________________________
data: /home/hoefling/projects/python/mypy/test-data/unit/stubgen.test:1457:
/home/hoefling/projects/python/mypy/mypy/test/teststubgen.py:281: in run_case
    self.run_case_inner(testcase)
/home/hoefling/projects/python/mypy/mypy/test/teststubgen.py:309: in run_case_inner
    testcase.file, testcase.line))
/home/hoefling/projects/python/mypy/mypy/test/helpers.py:114: in assert_string_arrays_equal
    raise AssertionError(msg)
E   AssertionError: Invalid output (/home/hoefling/projects/python/mypy/test-data/unit/stubgen.test, line 1457)
---------------------------------- Captured stderr call -----------------------------------
Expected:
  from typing import Any                        (diff)
                                                (diff)
  def f(x: Any) -> None: ...                    (diff)
  def g(x: Any, y: str) -> Any: ...             (diff)
                                                (diff)
  class A:                                      (diff)
  ...
Actual:
  def f(x: Any) -> None: ...                    (diff)
  def g(x: Any, y: str) -> Any: ...             (diff)
                                                (diff)
  class A:                                      (diff)
  ...

Alignment of first line difference:
  E: from typing import Any
  A: def f(x: Any) -> None: ...
     ^
================================ 1 failed in 0.24 seconds =================================

Basically, once you have added type to anything in the function signature, the import from typing import Any is not written to the stub. As a fix, I would suggest to add another check for annotated_type being of type AnyType:

diff --git a/mypy/stubgen.py b/mypy/stubgen.py
index d3bc3c4b..7635e791 100755
--- a/mypy/stubgen.py
+++ b/mypy/stubgen.py
@@ -402,6 +402,8 @@ class StubGenerator(mypy.traverser.TraverserVisitor):
                 annotation = ": Any"
             elif annotated_type and not is_self_arg:
                 annotation = ": {}".format(self.print_annotation(annotated_type))
+                if isinstance(annotated_type, mypy.types.AnyType):
+                    self.add_typing_import("Any")
             else:
                 annotation = ""
             if arg_.initializer:

but not suggesting it as a PR until someone can confirm this is indeed the most appropriate solution for the issue.

@hoefling

This comment has been minimized.

Copy link
Contributor Author

commented Jun 28, 2019

Another suggestion would be to record the import in AnnotationPrinter, treating AnyType in a similar fashion as the UnboundType:

diff --git a/mypy/stubgen.py b/mypy/stubgen.py
index d3bc3c4b..f7063ca0 100755
--- a/mypy/stubgen.py
+++ b/mypy/stubgen.py
@@ -80,7 +80,7 @@ from mypy.stubutil import (
 from mypy.stubdoc import parse_all_signatures, find_unique_signatures, Sig
 from mypy.options import Options as MypyOptions
 from mypy.types import (
-    Type, TypeStrVisitor, CallableType,
+    AnyType, Type, TypeStrVisitor, CallableType,
     UnboundType, NoneType, TupleType, TypeList,
 )
 from mypy.visitor import NodeVisitor
@@ -162,6 +162,11 @@ class AnnotationPrinter(TypeStrVisitor):
         super().__init__()
         self.stubgen = stubgen
 
+    def visit_any(self, t: AnyType) -> str:
+        s = super().visit_any(t)
+        self.stubgen.import_tracker.require_name(s)
+        return s
+
     def visit_unbound_type(self, t: UnboundType) -> str:
         s = t.name
         self.stubgen.import_tracker.require_name(s)
hoefling added a commit to hoefling/mypy that referenced this issue Jul 14, 2019
Signed-off-by: Oleg Höfling <oleg.hoefling@gmail.com>
ilevkivskyi added a commit that referenced this issue Jul 14, 2019
Closes #7090.
Signed-off-by: Oleg Höfling <oleg.hoefling@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.