Skip to content

--no-implicit-reexport should treat names in __all__ as exported #7042

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

Closed
Zac-HD opened this issue Jun 21, 2019 · 8 comments · Fixed by #7361
Closed

--no-implicit-reexport should treat names in __all__ as exported #7042

Zac-HD opened this issue Jun 21, 2019 · 8 comments · Fixed by #7361
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-0-high

Comments

@Zac-HD
Copy link
Contributor

Zac-HD commented Jun 21, 2019

From HypothesisWorks/hypothesis#2017, passing --no-implicit-reexport with Mypy 0.710 causes error: Module 'hypothesis' has no attribute 'given' - except that it does, and given is listed in the __all__ attribute.

IMO when __all__ is present only those names should be considered explicitly re-exported, though taking the union of those and the from-import-x-as-x form would be reasonable too. Ignoring __all__ is pretty weird though!

@bluetech
Copy link
Contributor

FWIW, I agree. I ran into this when enabling --no-implicit-reexport and importing from the sentry-sdk package (this is the file: https://github.com/getsentry/sentry-python/blob/0.9.2/sentry_sdk/__init__.py, cc @untitaker).

I also intuitively think __all__ should define the export list when present. [Personally, I found the "import as-rexports" rule surprising, so I'd go further and make __all__ the only way to reexport. But I realize it may be too heavy handed.]

no-implicit-reexport is a great feature, BTW.

@untitaker
Copy link

I didn't know about this issue. Is there a workaround we can add to the SDK?

@bluetech
Copy link
Contributor

@untitaker Like @Zac-HD suggested in the Hypothesis issue, I just turned the feature off for sentry-sdk for now. I think we should wait to see whether the Mypy devs consider this a bug or not, before exploding the import * in sentry-sdk.

@JukkaL JukkaL added bug mypy got something wrong false-positive mypy gave an error on correct code priority-0-high labels Jun 28, 2019
@JukkaL
Copy link
Collaborator

JukkaL commented Jun 28, 2019

Agreed that this looks like a bug.

@JukkaL
Copy link
Collaborator

JukkaL commented Jun 28, 2019

Anybody want to try to fix this? This doesn't sound very tricky.

bluetech added a commit to bluetech/mypy that referenced this issue Jun 28, 2019
The natural expectation is that when a variable is explicitly added to a
module's `__all__`, the module explicitly means to export it.

Previously, this was not the case, and a `from [..] import [..] as [..]`
reexport was required by `--no-implicit-export` even if the variable is
listed in `__all__`.

Fixes python#7042
bluetech added a commit to bluetech/mypy that referenced this issue Jun 29, 2019
The natural expectation is that when a variable is explicitly added to a
module's `__all__`, the module explicitly means to export it.

Previously, this was not the case, and a `from [..] import [..] as [..]`
reexport was required by `--no-implicit-export` even if the variable is
listed in `__all__`.

Fixes python#7042

TODO:
- Add more test cases (interaction with `import *` especially).
@bluetech
Copy link
Contributor

bluetech commented Jul 7, 2019

I started writing tests for the PR but there is a behavior I'm not sure about. Currently, star imports always reexport. That is, given

# private_module.py
a = 1
# public_module.py
from private_module import *

then from public_module import a is legal. This is considered an explicit reexport, so --no-implicit-reexport doesn't affect it.

This behavior is documented for stub files in PEP 484:

Modules and variables imported into the stub are not considered exported from the stub unless the import uses the import ... as ... form or the equivalent from ... import ... as ... form.

However, as an exception to the previous bullet, all objects imported into a stub using from ... import * are considered exported. (This makes it easier to re-export all objects from a given module that may vary by Python version.)

My question: should star-imports be considered explicit reexports also in regular (non-stub) files?

Pro: consistent with stub files, less boilerplate for intentional reexports.

Con: surprising, makes it impossible to use star imports in modules that want to control their exports.

My personal preference is to not make them explicit reexports, but don't feel strongly; will implement which ever way is decided.

@Zac-HD
Copy link
Contributor Author

Zac-HD commented Jul 8, 2019

My personal preference is to not make them explicit reexports, but don't feel strongly; will implement which ever way is decided.

I share your preference, though I would say it's strong for me. Brevity is a virtue for stub files, but for actual source code "explicit is better than implicit" - if something from a star-import is meant to be reexported, it can be added to __all__ 😄

@msullivan
Copy link
Collaborator

My initial inclination was that they need to continue to be considered explicit, since it is a (perhaps unfortunate) common pattern to reexport everything.

But thinking about it some more, now that mypy supports in-file configuration directives, it will be easy to disable --no-implicit-reexport for just a module that is doing this.

So yeah, let's make it not considered an explicit reexport.

bluetech added a commit to bluetech/mypy that referenced this issue Aug 17, 2019
The natural expectation is that when a variable is explicitly added to a
module's `__all__`, the module explicitly means to export it.

Previously, this was not the case, and a `from [..] import [..] as [..]`
reexport was required by `--no-implicit-export` even if the variable is
listed in `__all__`.

Fixes python#7042
bluetech added a commit to bluetech/mypy that referenced this issue Aug 17, 2019
…bled

Currently, in regular files, symbols imported into module A with `from B
import *` are considered explicitly exported from module B as well, i.e.
they are considered part of module's B public API.

This behavior makes sense in stub files as a shorthand (and is specified
in PEP 484), but for regular files I think it is better to be explicit:
add the symbols to `__all__`:

    [A.py]
    from B import *
    import B
    __all__ = [...] + B.__all__

Further discussion:
python#7042 (comment)
bluetech added a commit to bluetech/mypy that referenced this issue Aug 17, 2019
…bled

Currently, in regular files, symbols imported into module A with `from B
import *` are considered explicitly exported from module B as well, i.e.
they are considered part of module's B public API.

This behavior makes sense in stub files as a shorthand (and is specified
in PEP 484), but for regular files I think it is better to be explicit:
add the symbols to `__all__`.

Further discussion:
python#7042 (comment)
ilevkivskyi pushed a commit that referenced this issue Aug 19, 2019
…abled (#7361)

Based on #7099.

Currently, in regular files, symbols imported into module A with `from B
import *` are considered explicitly exported from module A as well, i.e.
they are considered part of module's A public API.

This behavior makes sense in stub files as a shorthand (and is specified
in PEP 484), but for regular files I think it is better to be explicit:
add the symbols to `__all__`.

Fixes #7042
Further discussion: #7042 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-0-high
Projects
None yet
5 participants