Skip to content

improvements when documenting __all__ #106556

@calestyo

Description

@calestyo

Documentation

  1. Forgive me if I'm wrong (still being a Python noob ^^), but testing seems to show that the following is only half the truth:
    package. The :keyword:`import` statement uses the following convention: if a package's
    :file:`__init__.py` code defines a list named ``__all__``, it is taken to be the
    list of module names that should be imported when ``from package import *`` is
    encountered. It is up to the package author to keep this list up-to-date when a

This says __all__ would be module names only (well it doesn't explicitly say so, but neither does it mention anything else), but in fact (or at least from some poor man testing I've did), it first seems to take any "items" (functions, vars, etc.) defined inside the package itself (i.e. within __init__.py and only if that doesn't exist (for a name listed in __all__), it seems to try importing a module/subpackage thereof.

Especially when considering:

Note that when using ``from package import item``, the item can be either a
submodule (or subpackage) of the package, or some other name defined in the
package, like a function, class or variable. The ``import`` statement first
tests whether the item is defined in the package; if not, it assumes it is a
module and attempts to load it. If it fails to find it, an :exc:`ImportError`

mentioned just above, where it's explicitly told that with from bla import * takes first the in-package items and only then modules/subpackages... it may seem to the reader as if __all__ would be different, and really just take modules (as it says right now).

  1. Another thing, which could perhaps be improved is the case, when importing from a package, which contains a module/subpackage of the same name:

    Consider e.g.:
    foo/__init__.py:
bar = 0
__all__ = ["foo"]

foo/foo.py:

bar = 1

and then using:

from foo import *

AFAIU, the "local" foo where foo.bar is 0 would be overwritten by foo.foo, thus foo.bar would be 1.

Now one might argue: package author's fault, if he writes stupid package/module names and __all__ but the above, I think, would even happen with e.g. __all__ = ["somethingElse"] when doing:

import foo.foo
from foo import *

as explained here:

names defined (and submodules explicitly loaded) by :file:`__init__.py`. It
also includes any submodules of the package that were explicitly loaded by
previous :keyword:`import` statements. Consider this code::
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
In this example, the :mod:`echo` and :mod:`surround` modules are imported in the
current namespace because they are defined in the :mod:`sound.effects` package
when the ``from...import`` statement is executed. (This also works when
``__all__`` is defined.)

Thanks,
Chris.

Metadata

Metadata

Assignees

No one assigned

    Labels

    docsDocumentation in the Doc dir

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions