Skip to content

Commit

Permalink
Improve documentation of new lazy loading system
Browse files Browse the repository at this point in the history
  • Loading branch information
aatle committed Nov 25, 2024
1 parent df1f23d commit e22b31f
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/reST/ref/sndarray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Each sample is an 8-bit or 16-bit integer, depending on the data format. A
stereo sound file has two values per sample, while a mono sound file only has
one.

.. versionchanged:: 2.5.3 sndarray module is lazily loaded

.. function:: array

| :sl:`copy Sound samples into an array`
Expand Down
2 changes: 2 additions & 0 deletions docs/reST/ref/surfarray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pixels from the surface and any changes performed to the array will make changes
in the surface. As this last functions share memory with the surface, this one
will be locked during the lifetime of the array.

.. versionchanged:: 2.5.3 surfarray module is lazily loaded

.. function:: array2d

| :sl:`Copy pixels into a 2d array`
Expand Down
15 changes: 15 additions & 0 deletions src_py/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,17 +264,32 @@ def PixelArray(surface): # pylint: disable=unused-argument

# lastly, the "optional" pygame modules

# Private, persisting alias for use in __getattr__
_MissingModule = MissingModule


def __getattr__(name):
"""Implementation of lazy loading for some optional pygame modules.
The surfarray and sndarray submodules use numpy, so they are loaded
lazily to avoid a heavy numpy import if the modules are never used.
The first access of a lazily loaded submodule loads it and sets it
as an attribute on the pygame module. Pygame itself doesn't import these modules.
If the first access is an attribute access and not an import, then __getattr__ is
invoked (as the attribute isn't set yet), which imports the module dynamically.
All lazy submodules are directly referenced in the packager_imports function.
"""
from importlib import import_module

LAZY_MODULES = "surfarray", "sndarray"
if name not in LAZY_MODULES:
# Normal behavior for attribute accesses that aren't lazy modules
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
try:
module = import_module(f"{__name__}.{name}")
# A successful import automatically sets the module attribute on the package
except (ImportError, OSError):
module = _MissingModule(name, urgent=0)
globals()[name] = module
Expand Down

0 comments on commit e22b31f

Please sign in to comment.