Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f47fdc7
Lazy-load top-level imports
cvanelteren Dec 30, 2025
5744830
Use warnings module in internals
cvanelteren Dec 30, 2025
eafd077
Add eager import option and tests
cvanelteren Dec 30, 2025
d785584
Cover eager setup and benchmark imports
cvanelteren Dec 30, 2025
7ea91e6
Add tests for lazy import coverage
cvanelteren Dec 30, 2025
9731ff1
update docs
cvanelteren Jan 4, 2026
23cd51d
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 4, 2026
7de24b3
refactor: Automate lazy loading and fix build error
cvanelteren Jan 4, 2026
b1a2155
update instructions
cvanelteren Jan 4, 2026
05cf17a
fix issues
cvanelteren Jan 4, 2026
94bcf34
attempt fix
cvanelteren Jan 4, 2026
b0a06d5
attempt fix
cvanelteren Jan 4, 2026
134f4a1
Fix lazy import clobbering figure
cvanelteren Jan 4, 2026
2abb008
Add regression test for figure lazy import
cvanelteren Jan 4, 2026
ebb37ab
fixed
cvanelteren Jan 4, 2026
7fb309e
Refactor lazy loader into helper module
cvanelteren Jan 4, 2026
bd61a35
bump
cvanelteren Jan 4, 2026
d15e1a9
bump
cvanelteren Jan 5, 2026
a87dcf0
resolve namespace collision
cvanelteren Jan 5, 2026
9c99e3d
resolve namespace collision
cvanelteren Jan 5, 2026
6a0c775
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 6, 2026
93dda9f
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 8, 2026
c1f3e2c
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 11, 2026
4bf18c9
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 11, 2026
a307ef9
mv docs
cvanelteren Jan 8, 2026
c7ad117
Update lazy-loading contributor docs
cvanelteren Jan 15, 2026
edbb90b
Merge branch 'main' into lazy-imports-perf
cvanelteren Jan 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,42 @@ To build the documentation locally, use the following commands:

The built documentation should be available in ``docs/_build/html``.

.. _contrib_lazy_loading:

Lazy Loading and Adding New Modules
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This documentation appears to be wrong.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I follow -- could you clarify what is wrong?

===================================

UltraPlot uses a lazy loading mechanism to improve import times. This means that
submodules are not imported until they are actually used. This is controlled by the
`__getattr__` function in `ultraplot/__init__.py`.

When adding a new submodule, you need to make sure it's compatible with the lazy
loader. Here's how to do it:

1. **Add the submodule to `_STAR_MODULES`:** In `ultraplot/__init__.py`, add the
name of your new submodule to the `_STAR_MODULES` tuple. This will make it
discoverable by the lazy loader.

2. **Add the submodule to `_MODULE_SOURCES`:** Also in `ultraplot/__init__.py`,
add an entry to the `_MODULE_SOURCES` dictionary that maps the name of your
submodule to its source file.

3. **Exposing Callables:** If you want to expose a function or class from your
submodule as a top-level attribute of the `ultraplot` package (e.g.,
`uplt.my_function`), you need to add an entry to the `_EXTRA_ATTRS`
dictionary.

* To expose a function or class `MyFunction` from `my_module.py` as
`uplt.my_function`, add the following to `_EXTRA_ATTRS`:
`"my_function": ("my_module", "MyFunction")`.
* If you want to expose the entire submodule as a top-level attribute
(e.g., `uplt.my_module`), you can add:
`"my_module": ("my_module", None)`.

By following these steps, you can ensure that your new module is correctly
integrated into the lazy loading system.


.. _contrib_pr:

Preparing pull requests
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ For more details, check the full :doc:`User guide <usage>` and :doc:`API Referen
:hidden:

api
lazy_loading
external-links
whats_new
contributing
Expand Down
54 changes: 54 additions & 0 deletions docs/lazy_loading.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. _lazy_loading:

===================================
Lazy Loading and Adding New Modules
===================================

UltraPlot uses a lazy loading mechanism to improve import times. This means that
submodules are not imported until they are actually used. This is controlled by the
:py:func:`ultraplot.__getattr__` function in :py:mod:`ultraplot`.

The lazy loading system is mostly automated. It works by scanning the `ultraplot`
directory for modules and exposing them based on conventions.

**Convention-Based Loading**

The automated system follows these rules:

1. **Single-Class Modules:** If a module `my_module.py` has an ``__all__``
variable with a single class or function `MyCallable`, it will be exposed
at the top level as ``uplt.my_module``. For example, since
:py:mod:`ultraplot.figure` has ``__all__ = ['Figure']``, you can access the `Figure`
class with ``uplt.figure``.

2. **Multi-Content Modules:** If a module has multiple items in ``__all__`` or no
``__all__``, the module itself will be exposed. For example, you can access
the `utils` module with :py:mod:`ultraplot.utils`.

**Adding New Modules**

When adding a new submodule, you usually don't need to modify :py:mod:`ultraplot`.
Simply follow these conventions:

* If you want to expose a single class or function from your module as a
top-level attribute, set the ``__all__`` variable in your module to a list
containing just that callable's name.

* If you want to expose the entire module, you can either use an ``__all__`` with
multiple items, or no ``__all__`` at all.

**Handling Exceptions**

For cases that don't fit the conventions, there is an exception-based
configuration. The `_LAZY_LOADING_EXCEPTIONS` dictionary in
:py:mod:`ultraplot` is used to manually map top-level attributes to
modules and their contents.

You should only need to edit this dictionary if you are:

* Creating an alias for a module (e.g., `crs` for `proj`).
* Exposing an internal variable (e.g., `colormaps` for `_cmap_database`).
* Exposing a submodule that doesn't follow the file/directory structure.

By following these guidelines, your new module will be correctly integrated into
the lazy loading system.
Loading