Skip to content

MyPy not acknowledging __all__  #1606

Closed

Description

@TimSimpsonR

When MyPy encounters star (*) imports it considers every symbol defined in the given module as being imported even if an __all__ attribute is present on the module.

For example, say you have mypkg with two files, main.py:

from datetime import datetime
from mypkg.widgets import *

and widget.py:

from datetime import datetime

__all__ = [
    "Gadget"
]

class Gadget(object):
    pass

Running "mypy mypkg/app.py" issues the following error: "mypkg/app.py:2: error: Name 'datetime' already defined", though datetime should not be re-imported to the app module.

Activity

  1. gvanrossum commented on Jun 2, 2016

    @gvanrossum
    Member

    Thanks for the report! For whoever wants to tackle this, apparently mypy ignore the value of __all__ when computing the effect of from ... import *. That feels like it shouldn't be too hard to fix.

  2. refi64 commented on Jun 2, 2016

    @refi64
    Contributor

    Was trying to tackle this. Given a SymbolTableNode, is it possible to get the variable's initializer somehow? Can't seem to figure out anything...

  3. JukkaL commented on Jun 2, 2016

    @JukkaL
    Collaborator

    The initializer is not accessible via SymbolTableNode. One way would be to hook into the semantic analysis of assignment statements (special case __all__ at module top level).

  4. gvanrossum commented on Jun 2, 2016

    @gvanrossum
    Member
  5. refi64 commented on Jun 3, 2016

    @refi64
    Contributor

    How should messes like this be handled:

    from typing import List, Union
    
    __all__ = None # type: Union[int, str, bytes, List[int], List[str]]
    
    if True:
        __all__ = 1
    elif True:
        __all__ = 'a'
    elif True:
        __all__ = [1]
    elif True:
        __all__ = ['a']

    My guess is to make it an error if __all__ has any type other than Sequence[str], and, if __all__ is assigned to multiple times, then just try to merge them all or something. So this would be an error:

    __all__ = 1 # ERROR: type of __all__ must be Sequence[str]

    and this would attempt to make __all__ ['x', 'y']:

    if True:
        __all__ = ['x']
    else:
        __all__ = ['y']

    Any attempts to mutate it via append and such would be ignored (at least for now). How does all that sound?

  6. gvanrossum commented on Jun 3, 2016

    @gvanrossum
    Member

    Check the stdlib for patterns. IIRC asyncio has dynamic all.

    But yes, it should be Sequence of stress (or Any).

    --Guido (mobile)

  7. added a commit that references this issue on Jun 3, 2016
    8c69531
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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions