Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit abfaa7a

Browse files
committed
Fix picklability of make_norm_from_scale norms.
And also fix their qualname, which was missed in a00a909.
1 parent 21b76ae commit abfaa7a

File tree

3 files changed

+42
-8
lines changed

3 files changed

+42
-8
lines changed

lib/matplotlib/colors.py

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,9 +1506,26 @@ class norm_cls(Normalize):
15061506

15071507
if init is None:
15081508
def init(vmin=None, vmax=None, clip=False): pass
1509-
bound_init_signature = inspect.signature(init)
1509+
1510+
return _make_norm_from_scale(
1511+
scale_cls, base_norm_cls, inspect.signature(init))
1512+
1513+
1514+
@functools.lru_cache(None)
1515+
def _make_norm_from_scale(scale_cls, base_norm_cls, bound_init_signature):
1516+
"""
1517+
Helper for `make_norm_from_scale`.
1518+
1519+
This function is split out so that it takes a signature object as third
1520+
argument (as signatures are picklable, contrary to arbitrary lambdas);
1521+
caching is also used so that different unpickles reuse the same class.
1522+
"""
15101523

15111524
class Norm(base_norm_cls):
1525+
def __reduce__(self):
1526+
return (_picklable_norm_constructor,
1527+
(scale_cls, base_norm_cls, bound_init_signature),
1528+
self.__dict__)
15121529

15131530
def __init__(self, *args, **kwargs):
15141531
ba = bound_init_signature.bind(*args, **kwargs)
@@ -1518,6 +1535,10 @@ def __init__(self, *args, **kwargs):
15181535
self._scale = scale_cls(axis=None, **ba.arguments)
15191536
self._trf = self._scale.get_transform()
15201537

1538+
__init__.__signature__ = bound_init_signature.replace(parameters=[
1539+
inspect.Parameter("self", inspect.Parameter.POSITIONAL_OR_KEYWORD),
1540+
*bound_init_signature.parameters.values()])
1541+
15211542
def __call__(self, value, clip=None):
15221543
value, is_scalar = self.process_value(value)
15231544
self.autoscale_None(value)
@@ -1555,17 +1576,23 @@ def inverse(self, value):
15551576
.reshape(np.shape(value)))
15561577
return value[0] if is_scalar else value
15571578

1558-
Norm.__name__ = (f"{scale_cls.__name__}Norm" if base_norm_cls is Normalize
1559-
else base_norm_cls.__name__)
1560-
Norm.__qualname__ = base_norm_cls.__qualname__
1579+
Norm.__name__ = (
1580+
f"{scale_cls.__name__}Norm" if base_norm_cls is Normalize
1581+
else base_norm_cls.__name__)
1582+
Norm.__qualname__ = (
1583+
f"{scale_cls.__qualname__}Norm" if base_norm_cls is Normalize
1584+
else base_norm_cls.__qualname__)
15611585
Norm.__module__ = base_norm_cls.__module__
15621586
Norm.__doc__ = base_norm_cls.__doc__
1563-
Norm.__init__.__signature__ = bound_init_signature.replace(parameters=[
1564-
inspect.Parameter("self", inspect.Parameter.POSITIONAL_OR_KEYWORD),
1565-
*bound_init_signature.parameters.values()])
1587+
15661588
return Norm
15671589

15681590

1591+
def _picklable_norm_constructor(*args, **kwargs):
1592+
cls = _make_norm_from_scale(*args, **kwargs)
1593+
return cls.__new__(cls)
1594+
1595+
15691596
@make_norm_from_scale(
15701597
scale.FuncScale,
15711598
init=lambda functions, vmin=None, vmax=None, clip=False: None)

lib/matplotlib/tests/test_colors.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1480,4 +1480,4 @@ def test_norm_update_figs(fig_test, fig_ref):
14801480
def test_make_norm_from_scale_name():
14811481
logitnorm = mcolors.make_norm_from_scale(
14821482
mscale.LogitScale, mcolors.Normalize)
1483-
assert logitnorm.__name__ == "LogitScaleNorm"
1483+
assert logitnorm.__name__ == logitnorm.__qualname__ == "LogitScaleNorm"

lib/matplotlib/tests/test_pickle.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,10 @@ def test_unpickle_canvas():
219219
def test_mpl_toolkits():
220220
ax = parasite_axes.host_axes([0, 0, 1, 1])
221221
assert type(pickle.loads(pickle.dumps(ax))) == parasite_axes.HostAxes
222+
223+
224+
def test_dynamic_norm():
225+
logit_norm_instance = mpl.colors.make_norm_from_scale(
226+
mpl.scale.LogitScale, mpl.colors.Normalize)()
227+
assert type(pickle.loads(pickle.dumps(logit_norm_instance))) \
228+
== type(logit_norm_instance)

0 commit comments

Comments
 (0)