Simple mechanism to rollup API symbols to a Python module from its submodules
Project description
pyrollup
Simple mechanism to rollup API symbols to a Python module from its submodules
Background
Conventionally, a Python package's public API symbols (or at least a subset) are exported from the top-level package. These symbols are typically imported from various submodules in the module hierarchy. This leads to a rather tedious listing of symbols exported (via a module's __init__.py
) at each level.
For example:
from .submodule_a import ClassA, ClassA2
from .submodule_b import ClassB
from .submodule_c import ClassC
__all__ = [
ClassA,
ClassA2
ClassB,
ClassC,
]
The definition of __all__
can be omitted, although some schools of thought encourage its use.
Problem statement
With the above approach, the burden of which symbols are considered public for a given submodule falls on the containing module importing them. In addition, __all__
must be maintained alongside symbol imports, potentially resulting in duplication.
This can become problematic for complex projects with many nested symbols imported at the top-level package. For example:
from .submodule_a import ClassA, ClassA2
from .submodule_a.submodule_a1 import ClassA1_1, ClassA1_2
from .submodule_a.submodule_a2 import ClassA2_1, ClassA2_2
from .submodule_a.submodule_a3 import ClassA3_1, ClassA3_2
from .submodule_b import ClassB
from .submodule_c import ClassC
__all__ = [
ClassA,
ClassA2,
ClassA1_1,
ClassA1_2,
ClassA2_1,
ClassA2_2,
ClassA3_1,
ClassA3_2,
ClassB,
ClassC,
]
In addition, submodules must similarly maintain their own imports and/or definition of __all__
if they export symbols from their submodules.
Proposed solution
Ideally, a module should "rollup" public symbols from its submodules, letting each submodule decide which symbols those are. Submodules should therefore optionally provide an allow-list and block-list to describe which public symbols should be propagated to the parent module.
In other words, a given module should have ownership of:
- Its own public symbols (Python convention)
- Defined by
__all__
- Defined by
- Which of those public symbols should be propagated to parent modules (functionality provided by
pyrollup
)- Defined by
__rollup__
: allow-list, defaulting to__all__
__nrollup__
: block-list, defaulting to[]
- Defined by
Then, the example above can be modified as:
from pyrollup import rollup
# import submodules
from . import submodule_a, submodule_b, submodule_c
# import public symbols from each submodule
from .submodule_a import *
from .submodule_b import *
from .submodule_c import *
# export public symbols from each submodule, filtered by allow-list/block-list
__all__ = rollup(submodule_a, submodule_b, submodule_c)
This allows a project with a complex module hierarchy to flexibly propagate public symbols from wherever they are defined to the top-level package.
Downsides
Static analysis tools are unable to evaluate the value of __all__
since with this approach it is computed dynamically upon import. Therefore, code documentation generator tools using static analysis (e.g. autoapi or autodoc2) will fail to detect a module's public symbols.
Tools using the traditional approach of importing the package for which documentation is being generated (e.g. Sphinx's built-in autodoc) should have no problem with such dynamic imports.
It is possible to use a "hybrid" approach; the author has had some success with extending autodoc2 to work with dynamically-evaluated __all__
.
TODO: document and generalize this solution
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pyrollup-0.1.0.tar.gz
.
File metadata
- Download URL: pyrollup-0.1.0.tar.gz
- Upload date:
- Size: 3.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.6.1 CPython/3.10.12 Linux/5.15.0-87-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 388c152b20b5467d2378462dcc6bac121db3bd98ef1902874caa0e30b24a0f21 |
|
MD5 | 4987b1a23b3d31ebdfa47ef7d21a4dea |
|
BLAKE2b-256 | d72779fd7b38ba488482ed0813db78b6e0e49fde9417c967c755ca3800655f6e |
Provenance
File details
Details for the file pyrollup-0.1.0-py3-none-any.whl
.
File metadata
- Download URL: pyrollup-0.1.0-py3-none-any.whl
- Upload date:
- Size: 3.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.6.1 CPython/3.10.12 Linux/5.15.0-87-generic
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | a2f73b823e251f6e3c9e14dfe7ce43323824a62fe5fc66d5e6221db6d9fae6ba |
|
MD5 | 7c997e695f8b9f1f8150577c3ce5b6e0 |
|
BLAKE2b-256 | c38f4375e0fbf96962aca89243ee0661956972bf8350c283acc13ec4a6dd7918 |