Skip to content

fix: byteswap non-native input instead of reinterpreting it - #152

Merged
tlambert03 merged 1 commit into
pyapp-kit:mainfrom
matthiasschabel:fix/byteswap-non-native
Aug 12, 2026
Merged

fix: byteswap non-native input instead of reinterpreting it#152
tlambert03 merged 1 commit into
pyapp-kit:mainfrom
matthiasschabel:fix/byteswap-non-native

Conversation

@matthiasschabel

@matthiasschabel matthiasschabel commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Data in non-native byte order maps to the wrong colors.

  • On a little-endian host, a big-endian float array has its bytes relabelled rather than
    reordered, so -0.5, 1.5 and NaN all decode as tiny denormals.
  • They land on the first ramp color, which makes under, over and bad unreachable for
    such input.
import numpy as np
from cmap import Colormap, Color

cmap = Colormap(["red", "blue"], under="green", over="yellow", bad="black")
native = np.array([-0.5, 0.5, 1.5, np.nan])
non_native = native.astype(native.dtype.newbyteorder())

print([Color(c).hex for c in cmap(native)])
print([Color(c).hex for c in cmap(non_native)])
['#008000', '#7F0080', '#FFFF00', '#000000']   # under, ramp, over, bad
['#FF0000', '#FF0000', '#FF0000', '#FF0000']   # all the first ramp color

The numpy 2 migration in #60 replaced xa.byteswap().newbyteorder(), which numpy 2 removed,
with a plain .view() of the swapped dtype. byteswap().view(dtype.newbyteorder()) is the
numpy 2 spelling of the original, and what matplotlib uses today.

Data in non-native byte order maps to the wrong colors. On a little-endian
host, a big-endian float array has its bytes relabelled rather than reordered,
so -0.5, 1.5 and NaN all decode as tiny denormals and land on the first ramp
color. under, over and bad are unreachable for such input.

The numpy 2 migration in pyapp-kit#60 replaced xa.byteswap().newbyteorder(), which numpy
2 removed, with a plain .view() of the swapped dtype.
byteswap().view(dtype.newbyteorder()) is the numpy 2 spelling of the original,
and what matplotlib uses today.

The existing coverage maps an array of zeros and asserts only its shape, both
of which are invariant under the bug.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewed-By: Codex (gpt-5.6-sol, reasoning effort xhigh)
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.70%. Comparing base (02fa073) to head (ff1d461).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #152      +/-   ##
==========================================
- Coverage   95.71%   95.70%   -0.01%     
==========================================
  Files         168      168              
  Lines        2192     2191       -1     
==========================================
- Hits         2098     2097       -1     
  Misses         94       94              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@matthiasschabel
matthiasschabel marked this pull request as ready for review August 10, 2026 21:27
@tlambert03

Copy link
Copy Markdown
Member

thanks!

@tlambert03
tlambert03 merged commit d1521b1 into pyapp-kit:main Aug 12, 2026
27 checks passed
@matthiasschabel
matthiasschabel deleted the fix/byteswap-non-native branch August 13, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants