dropbox / pyannotate

Auto-generate PEP-484 annotations
Apache License 2.0
1.43k stars 59 forks source link

Fix Ellipsis bug #78

Closed laike9m closed 5 years ago

laike9m commented 5 years ago

When trying pyannotate, I found that ... is not handled properly.

A very simple case would be like:(for simplicity I just copy/paste the test case code)

def test_variadic(self):
    self.setTestData(
        [{"func_name": "nop",
          "path": "<string>",
          "line": 1,
          "signature": {
              "arg_types": ["Tuple[int, ...]"],
              "return_type": "int"},
          }])
    a = """\
        def nop(a):   return 0
        """
    b = """\
        from typing import Tuple
        def nop(a):
            # type: (Tuple[int, ...]) -> int
            return 0
        """
    self.check(a, b)

This would cause the following error

E   AssertionError: 'from typing import Tuple\ndef nop(a):\n    # t[45 chars]\n\n' != 'from .. import \nfrom typing import Tuple\ndef[59 chars]\n\n'
E   + from .. import
E     from typing import Tuple
E     def nop(a):
E   -     # type: (Tuple[int, ...]) -> int
E   ?                         ---
E   +     # type: (Tuple[int, ]) -> int
E         return 0

The problem lies in type_updater function, where it's treating words with . as pkg.mod.SomeClass, however ... is a special case.

The fix is also easy. If the word is ..., we don't need to import anything and should just return ... itself, so that it is properly added to type annotations.