Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

implementation of mpl_init mechanism#30742

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
fecrescencio22 wants to merge2 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromfecrescencio22:refactor-for-issue-29813
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
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
32 changes: 30 additions & 2 deletionslib/matplotlib/__init__.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -995,6 +995,35 @@ def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
locale.setlocale(locale.LC_ALL, '')


def _run_submodule_inits():
"""
Initialize matplotlib submodules that require deferred initialization.

This function is called once after rcParams have been loaded, providing
a centralized orchestration point for all submodule initialization logic.
This decouples module imports from initialization, making the codebase
more maintainable and less fragile to import order issues.

Submodules that need mandatory initialization should implement a
``_mpl_init()`` function, which will be called by this orchestrator.

See Also
--------
Issue #29813 : Cleanup internal import dependencies and initialization logic
"""
# Import and initialize submodules in dependency order
# Each submodule's _mpl_init() is responsible for its own setup

# Initialize colormap registry (depends on rcParams['image.lut'])
from matplotlib import cm
if hasattr(cm, '_mpl_init'):
cm._mpl_init()


# Run submodule initialization after rcParams are loaded
_run_submodule_inits()


def rc(group, **kwargs):
"""
Set the current `.rcParams`. *group* is the grouping for the rc, e.g.,
Expand DownExpand Up@@ -1553,8 +1582,7 @@ def validate_backend(s):
return rcsetup.validate_backend(s)


# workaround: we must defer colormaps import to after loading rcParams, because
# colormap creation depends on rcParams
# Import colormap registries (they are now safely initialized via _mpl_init())
from matplotlib.cm import _colormaps as colormaps # noqa: E402
from matplotlib.cm import _multivar_colormaps as multivar_colormaps # noqa: E402
from matplotlib.cm import _bivar_colormaps as bivar_colormaps # noqa: E402
83 changes: 72 additions & 11 deletionslib/matplotlib/cm.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,22 +26,28 @@
from matplotlib._cm_bivar import cmaps as bivar_cmaps


_LUTSIZE = mpl.rcParams['image.lut']
# _LUTSIZE will be set during _mpl_init() after rcParams are available
_LUTSIZE = None


def _gen_cmap_registry():
def _gen_cmap_registry(lutsize):
"""
Generate a dict mapping standard colormap names to standard colormaps, as
well as the reversed colormaps.

Parameters
----------
lutsize : int
The number of entries in the colormap lookup table.
"""
cmap_d = {**cmaps_listed}
for name, spec in datad.items():
cmap_d[name] = ( # Precache the cmaps at a fixed lutsize..
colors.LinearSegmentedColormap(name, spec,_LUTSIZE)
colors.LinearSegmentedColormap(name, spec,lutsize)
if 'red' in spec else
colors.ListedColormap(spec['listed'], name)
if 'listed' in spec else
colors.LinearSegmentedColormap.from_list(name, spec,_LUTSIZE))
colors.LinearSegmentedColormap.from_list(name, spec,lutsize))

# Register colormap aliases for gray and grey.
aliases = {
Expand DownExpand Up@@ -230,12 +236,67 @@ def get_cmap(self, cmap):
)


# public access to the colormaps should be via `matplotlib.colormaps`. For now,
# we still create the registry here, but that should stay an implementation
# detail.
_colormaps = ColormapRegistry(_gen_cmap_registry())
globals().update(_colormaps)
# Colormap registries - initialized by _mpl_init()
_colormaps = None
_multivar_colormaps = None
_bivar_colormaps = None


def _mpl_init():
"""
Initialize the colormap registries.

This function is called by matplotlib.__init__._run_submodule_inits()
after rcParams have been loaded. This ensures that colormap creation
can access rcParams['image.lut'] without import order issues.

See Also
--------
Issue #29813 : Cleanup internal import dependencies and initialization logic
"""
global _colormaps, _multivar_colormaps, _bivar_colormaps, _LUTSIZE

# Get the lookup table size from rcParams
_LUTSIZE = mpl.rcParams['image.lut']

# Initialize the main colormap registry
_colormaps = ColormapRegistry(_gen_cmap_registry(_LUTSIZE))
# public access to the colormaps should be via `matplotlib.colormaps`.
# For now, we still update globals here, but that should stay an
# implementation detail.
globals().update(_colormaps)


_multivar_colormaps = ColormapRegistry(multivar_cmaps)
# Initialize multivariate and bivariate colormap registries
_multivar_colormaps = ColormapRegistry(multivar_cmaps)
_bivar_colormaps = ColormapRegistry(bivar_cmaps)


def _ensure_cmap(cmap):
"""
Ensure that we have a `.Colormap` object.

For internal use to preserve type stability of errors.

Parameters
----------
cmap : None, str, Colormap

- if a `Colormap`, return it
- if a string, look it up in mpl.colormaps
- if None, look up the default color map in mpl.colormaps

Returns
-------
Colormap

"""
if isinstance(cmap, colors.Colormap):
return cmap
cmap_name = mpl._val_or_rc(cmap, "image.cmap")
# use check_in_list to ensure type stability of the exception raised by
# the internal usage of this (ValueError vs KeyError)
if cmap_name not in _colormaps:
_api.check_in_list(sorted(_colormaps), cmap=cmap_name)
return mpl.colormaps[cmap_name]

_bivar_colormaps = ColormapRegistry(bivar_cmaps)
45 changes: 45 additions & 0 deletionslib/matplotlib/tests/test_matplotlib.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,3 +94,48 @@ def test_get_executable_info_timeout(mock_check_output):

with pytest.raises(matplotlib.ExecutableNotFoundError, match='Timed out'):
matplotlib._get_executable_info.__wrapped__('inkscape')


def test_mpl_init_mechanism():
"""
Test that the _mpl_init() mechanism properly initializes submodules.
This test verifies that:
1. Colormap registries are initialized after matplotlib import
2. _LUTSIZE is set correctly from rcParams
3. The initialization happens after rcParams are loaded
See Issue #29813: Cleanup internal import dependencies and initialization logic
"""
assert matplotlib.cm._colormaps is not None, \
"Colormap registry should be initialized after matplotlib import"
assert matplotlib.cm._LUTSIZE is not None, \
"_LUTSIZE should be set during initialization"
assert matplotlib.cm._LUTSIZE == matplotlib.rcParams['image.lut'], \
"_LUTSIZE should match rcParams['image.lut']"
assert len(matplotlib.colormaps) > 0, \
"Colormap registry should contain colormaps"
assert 'viridis' in matplotlib.colormaps, \
"Standard colormaps like 'viridis' should be available"
assert matplotlib.cm._multivar_colormaps is not None, \
"Multivariate colormap registry should be initialized"
assert matplotlib.cm._bivar_colormaps is not None, \
"Bivariate colormap registry should be initialized"


def test_colormap_initialization_order():
"""
Test that colormap initialization can access rcParams without import order issues.
This is a regression test for the issue where importing cm before rcParams
were loaded would cause errors.
See Issue #29813: Cleanup internal import dependencies and initialization logic
"""
program = (
"import matplotlib; "
"import matplotlib.cm as cm; "
"assert cm._colormaps is not None, 'Colormaps should be initialized'; "
"assert cm._LUTSIZE == matplotlib.rcParams['image.lut'], "
"'LUTSIZE should match rcParams'"
)
subprocess_run_for_testing(
[sys.executable, "-c", program],
env={**os.environ, "MPLBACKEND": ""}, check=True
)
Loading

[8]ページ先頭

©2009-2025 Movatter.jp