Summary
plt.figure("label") currently uses Python's randomized hash(label) as the public figure number and as the key in the global figure registry. This makes named figure numbers vary by process, allows collisions with explicitly numbered figures, and can make the next anonymous figure number enormous. The same factory also silently ignores unknown keyword arguments.
Audited at 99eda6d.
Current behavior
Named labels are converted to numeric keys with hash(num), while an anonymous figure uses max(_figures) + 1, in python/xy/pyplot/_state.py. close() and fignum_exists() repeat the hash mapping in the same state module.
Consequences:
Figure.number for a named figure changes with PYTHONHASHSEED;
- a label hash can collide with an explicit integer figure;
get_fignums() exposes hash values rather than sequential public figure numbers;
- the next
figure() can inherit a huge hash-derived number.
figure() pops toolbar and layout and reads a few other known values, but never rejects leftover kwargs in its factory implementation. A misspelling or materially unsupported option therefore succeeds silently, contrary to the shim's fail-loud compatibility policy.
Proposed direction
Keep integer figure identity and string labels in separate registries. A new named figure should receive the next normal sequential integer number and a label-to-number entry; reusing the label should reactivate that figure. Consume an explicit allowlist of supported figure() kwargs and reject any leftovers with a clear error.
Acceptance criteria
Summary
plt.figure("label")currently uses Python's randomizedhash(label)as the public figure number and as the key in the global figure registry. This makes named figure numbers vary by process, allows collisions with explicitly numbered figures, and can make the next anonymous figure number enormous. The same factory also silently ignores unknown keyword arguments.Audited at
99eda6d.Current behavior
Named labels are converted to numeric keys with
hash(num), while an anonymous figure usesmax(_figures) + 1, inpython/xy/pyplot/_state.py.close()andfignum_exists()repeat the hash mapping in the same state module.Consequences:
Figure.numberfor a named figure changes withPYTHONHASHSEED;get_fignums()exposes hash values rather than sequential public figure numbers;figure()can inherit a huge hash-derived number.figure()popstoolbarandlayoutand reads a few other known values, but never rejects leftoverkwargsin its factory implementation. A misspelling or materially unsupported option therefore succeeds silently, contrary to the shim's fail-loud compatibility policy.Proposed direction
Keep integer figure identity and string labels in separate registries. A new named figure should receive the next normal sequential integer number and a label-to-number entry; reusing the label should reactivate that figure. Consume an explicit allowlist of supported
figure()kwargs and reject any leftovers with a clear error.Acceptance criteria
close,fignum_exists,get_fignums, andget_figlabelsremain coherent.PYTHONHASHSEEDvalues (or prove no hash-based identity remains), and unknown kwargs.