Publication helps you maintain public-api-friendly modules by preventing unintentional access to private implementation details via introspection
npx @tessl/cli install tessl/pypi-publication@0.0.0A Python library that helps maintain clear public APIs by preventing unintentional access to private implementation details through introspection. Publication uses the existing convention of __all__ and runtime module manipulation to hide everything that has not been marked as explicitly public, solving the problem where users accidentally depend on internal implementation details.
pip install publicationfrom publication import publishTo access version information:
from publication import __version__# yourmodule.py
import dependency1
import dependency2
from publication import publish
def implementation_detail():
"""Internal function not intended for public use."""
...
def stuff():
"""Public function that users should call."""
...
implementation_detail()
...
__all__ = [
'stuff'
]
publish()After calling publish(), only the names listed in __all__ are accessible through normal imports:
# This works - stuff is in __all__
from yourmodule import stuff
# This raises ImportError - implementation_detail is hidden
from yourmodule import implementation_detail
# This raises ImportError - dependency1 is hidden
from yourmodule import dependency1
# But implementation details are still accessible via _private namespace
from yourmodule._private import implementation_detail, dependency1Transforms a module's public interface by hiding all names not listed in __all__, while preserving access to private implementation details through a _private namespace.
def publish():
"""
Publish the interface of the calling module as defined in __all__;
relegate the rest of it to a _private API module.
Call it at the top level of your module after __all__ and all the names
described in it are defined; usually the best place to do this is as the
module's last line.
The function uses frame introspection to access the calling module's
namespace and performs the following operations:
1. Creates a new public module containing only names from __all__
2. Moves the original module to a _private namespace
3. Updates sys.modules to use the new public module
4. Preserves essential module attributes (__doc__, __file__, etc.)
Parameters:
None (uses frame introspection to access caller's module)
Returns:
None
Side Effects:
- Modifies sys.modules to replace the calling module
- Creates a _private submodule with original implementation
- Hides non-public names from direct import access
"""Package version identifier for compatibility and dependency management.
__version__: str
# Current value: "0.0.3"After publish() is called, the original module with all its implementation details becomes available as <module_name>._private:
# If yourmodule.py called publish()
from yourmodule._private import implementation_detail
from yourmodule._private import dependency1
# The _private module is also accessible in sys.modules
import sys
private_module = sys.modules['yourmodule._private']The following standard module attributes are automatically preserved in the public interface:
__all__ - The public interface definition__cached__ - Bytecode cache file path__doc__ - Module documentation string__file__ - Module source file path__loader__ - Module loader object__name__ - Module name__package__ - Parent package name__path__ - Package search path (for packages)__spec__ - Module specification objectFor static type checkers like mypy, use conditional imports:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from something import T
else:
from something._private import T
def returns_t() -> T:
...publish() is called__all__ is not defined in the calling module