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

MyPy not acknowledging __all__ #1606

Closed
TimSimpsonR opened this issue Jun 2, 2016 · 6 comments
Closed

MyPy not acknowledging __all__ #1606

TimSimpsonR opened this issue Jun 2, 2016 · 6 comments

Comments

@TimSimpsonR
Copy link

TimSimpsonR commented Jun 2, 2016

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.

@gvanrossum
Copy link
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.

@refi64
Copy link
Contributor

refi64 commented Jun 2, 2016

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...

@JukkaL
Copy link
Collaborator

JukkaL commented Jun 2, 2016

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).

@gvanrossum
Copy link
Member

gvanrossum commented Jun 2, 2016 via email

@refi64
Copy link
Contributor

refi64 commented Jun 3, 2016

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?

@gvanrossum
Copy link
Member

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

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

--Guido (mobile)

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

No branches or pull requests

4 participants