Useful features
Add private name to __all__¶
You can add the private name to __all__ When you write ‘unexport: public’ as a comment.
__all__ = ["name", "_protected_name", "__private_name", "_protected_function", "__private_function", "_ProtectedClass", "__PrivateClass"]
name = ... # unexport: public
_protected_name = ... # unexport: public
__private_name = ... # unexport: public
def _protected_function(): ... # unexport: public
def __private_function(): ... # unexport: public
class _ProtectedClass: ... # unexport: public
class __PrivateClass: ... # unexport: public
Remove public name from __all__¶
You can remove the public name from __all__ When you write ‘unexport: not-public’ as a comment.
PUBLIC_NAME = ... # unexport: not-public
def public_function(): ... # unexport: not-public
class PublicClass:... # unexport: not-public
Type variables¶
TypeVar, ParamSpec and TypeVarTuple definitions are module-local helpers, so they are not added to __all__. Write ‘unexport: public’ as a comment to add one anyway.
from typing import TypeVar
T = TypeVar("T") # not added to __all__
PublicT = TypeVar("PublicT") # unexport: public
Conditional names¶
A name defined in only one branch of an if whose outcome depends on the platform, the Python version or anything else unexport can’t know is not added to __all__: on the other branch it doesn’t exist, and from module import * would fail there. Names bound in every branch are added as usual. Write ‘unexport: public’ as a comment to add one anyway, or list it yourself.
import sys
if sys.platform == "win32":
class WinRegistry: ... # not added
if sys.version_info >= (3, 11):
Feature = ... # added: bound in both branches
else:
Feature = ...
Names you list yourself¶
Names that are already in __all__ stay there as long as the module still binds them, even if unexport would not add them on its own: re-exported imports, dunders such as __version__, lowercase variables or private helpers. Listed names that may exist without a visible binding are kept as well: when the module has a star import, a module __getattr__ (PEP 562), or updates globals(), and, in a package’s __init__.py, the names of its submodules (from package import * imports those). A listed name that no longer exists, or that is marked # unexport: not-public (also on an import, or on one name of a multi-line import), is removed.
from .core import Api
__all__ = ["Api", "__version__", "helper"] # all three stay
__version__ = "1.0"
def helper(): ...
How __all__ is read¶
__all__ = [...], __all__: list[str] = [...], __all__ += [...], __all__.append("x") and __all__.extend([...]) (or a tuple) at module level are all understood. When __all__ is built from several of these statements, unexport reports the difference but does not rewrite the file, since changing one statement would list names twice; update it by hand. When __all__ has parts that can’t be read statically, such as ["a"] + sub.__all__, the module is not checked.