Skip to main content

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__
  • 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 []

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

Metadata

Release files for pyrollup 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyrollup 0.1.0
File Size Uploaded Provenance
pyrollup-0.1.0.tar.gz 3.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pyrollup 0.1.0
File Interpreter ABI Platform
pyrollup-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 7.2 kB

Release files / pyrollup-0.1.0.tar.gz

Download URL pyrollup-0.1.0.tar.gz
Size 3.4 kB
Tags Source
SHA-256 checksum
How to use checksums
388c152b20b5467d2378462dcc6bac121db3bd98ef1902874caa0e30b24a0f21
BLAKE2b-256 checksum
How to use checksums
d72779fd7b38ba488482ed0813db78b6e0e49fde9417c967c755ca3800655f6e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.6.1 CPython/3.10.12 Linux/5.15.0-87-generic

Release files / pyrollup-0.1.0-py3-none-any.whl

Download URL pyrollup-0.1.0-py3-none-any.whl
Size 3.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a2f73b823e251f6e3c9e14dfe7ce43323824a62fe5fc66d5e6221db6d9fae6ba
BLAKE2b-256 checksum
How to use checksums
c38f4375e0fbf96962aca89243ee0661956972bf8350c283acc13ec4a6dd7918
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.6.1 CPython/3.10.12 Linux/5.15.0-87-generic

Security for pyrollup 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page