Skip to content

Unexpected Any for complex import structure #4110

Closed

Description

@matzipan

Hello guys, I have the following snippet:

def blabla_call(command: List[str], modules: Optional[List[str]] = None) -> Tuple[int, str]:
    if modules is None:
        modules = []

    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    output_buffer = io.StringIO()

    for line in process.stdout:
        decoded_line = line.decode("utf-8")
        sys.stdout.write(decoded_line)
        output_buffer.write(decoded_line)

    if process.returncode:
        raise RuntimeError("Shell command failure")

    return process.returncode, output_buffer.getvalue()

def make_step(options: Iterable[str]) -> Tuple[int, str]:
     return blabla_call(["make"])

On the very last line of the function make_step the following warning is reported only when running with --strict enabled: warning: Returning Any from function declared to return "Tuple[int, str]".

This sounds like a type propagation bug of sorts in mypy since there is no error reported in the type defintion of blabla_call, but only further on does mypy get confused.

Activity

  1. ilevkivskyi commented on Oct 13, 2017

    @ilevkivskyi
    Member

    I cannot reproduce this on master.

  2. matzipan commented on Oct 13, 2017

    @matzipan
    Author

    I'm on 0.530 and I can't see what changed in the meanwhile that fixed it.

  3. matzipan commented on Oct 13, 2017

    @matzipan
    Author

    Ah you are right. My testcase doesn't produce the issue.

  4. matzipan commented on Oct 13, 2017

    @matzipan
    Author

    I've managed to eliminate Tuple as an issue, I still get this issue with just str: warning: Returning Any from function declared to return "str"

    I've managed to get the same issue when I have the following file:

    import sys
    from typing import Optional, List
    
    def call(command: List[str], modules: Optional[List[str]] = None) -> str:
        if modules is None:
            modules = []
    
        output_buffer = io.StringIO()
    
        return output_buffer.getvalue()
    

    But I understand this, because this doesn't import io. However, the file where I have blabla_call defined has an import io at the top and it can execute without any errors (unfortunately I can't share the full file).

  5. ilevkivskyi commented on Oct 13, 2017

    @ilevkivskyi
    Member

    Yes, everything unknown is Any.

    and it can execute without any errors

    x: int = 'hi' also executes without errors. I will be glad to fix the bug, if you show the bug, currently from what I see everything works as expected.

  6. matzipan commented on Oct 13, 2017

    @matzipan
    Author

    Ok. I think I've narrowed down and located the issue.

    I have the following directory structure:

    blamodule
    |-- __init__.py
    |-- backends
    |   |-- Bla.py
    |   `-- __init__.py
    `-- call_command.py
    

    With the following contents:

    • blamodule/__init__.py
    from . import call_command
    from . import backends
    
    • blamodule/backends/__init__.py
    from .Bla import Bla
    
    • blamodule/backends/Bla.py
    import blamodule
    from typing import Iterable
    
    class Bla:
        def __init__(self, path: str) -> None:
            self.path = path
    
        def method(self, options: Iterable[str]) -> str:
            return blamodule.call_command.call(["BLA"])
    
    • blamodule/call_command.py
    import io
    
    def call() -> str:
    
        output_buffer = io.StringIO()
    
        return output_buffer.getvalue()
    

    This works fine when I run in python because the sys.path contains the folder which is one level up of blamodule folder (the root of the project). However, mypy does not seem to take this into consideration and it can't find blamodule to import in backends/Bla.py and thus it expects a return of Any.

  7. ilevkivskyi commented on Oct 13, 2017

    @ilevkivskyi
    Member

    This may be related to #3277 but it doesn't look like a duplicate, since there are no explicit import cycle.

  8. changed the title [-]Mypy strict mode is confused about return type[/-] [+]Unexpected Any for complex import structure[/+] on Oct 13, 2017
  9. JukkaL commented on Mar 8, 2018

    @JukkaL
    Collaborator

    Looks like this was fixed by #4695.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions