Repository navigation
NDI Cloud file CRC-32: lookupFiles, checksummed uploads (ndi-cloud-node#162) - #325
Conversation
…ds (ndi-cloud-node#162) Python half of VH-Lab/NDI-matlab#1025. - ndi.fun.file.crc32 / crc32ToBase64: a file's CRC-32 in the cloud's encoding (base64 of the 4-byte big-endian value), via zlib in chunks. - getFileUploadURL(..., checksum_crc32=) sends checksumCRC32; putFiles / putFileBytes(..., checksum_crc32=) send the x-amz-checksum-crc32 header that such a URL signs. Malformed values are refused. - ndi.cloud.api.files.lookupFiles: POST /files/lookup, split at 5000 uids. - uploadSingleFile sends the checksum by default (checksum=True). - getSignedURLSetAll merges the pages' fileInfo. - Bridge: lookupFiles, crc32, crc32ToBase64 recorded with matlab_branch claude/file-crc32-lookup; getFileUploadURL, putFiles, uploadSingleFile, listFiles(All), getSignedURLSet(All) and url synced to NDI-matlab 8fa6ea5e. - Tests: offline tests/test_cloud_api_files_crc32.py; live TestFileChecksums in tests/test_cloud_live.py (skips where the server predates the route). Two test_phase2_gaps uploadSingleFile tests pass checksum=False, since their file does not exist and the default now reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwsqFA9Zs1HGm6YM4g2XRV
|
MATLAB/Python bridge completeness fails here, but on entries this PR doesn't touch. Everything this PR changes passes, including drift, the hash-justification check and the branch-pending checks against
Those commits went onto the lightsheet MATLAB branch after The fix: once the lightsheet changes are ported or reviewed, bump those three Generated by Claude Code |
A skip hid whether the tests ran at all; an environment without the lookup route or fileInfo now fails these tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwsqFA9Zs1HGm6YM4g2XRV
lookupFiles, crc32 and crc32ToBase64 are on NDI-matlab main, so the ordinary bridge checks apply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SwsqFA9Zs1HGm6YM4g2XRV
This is the Python half of VH-Lab/NDI-matlab#1025. It is the client for Waltham-Data-Science/ndi-cloud-node#162, implemented in ndi-cloud-node#163. That server change is deployed to dev and prod and tested with the MATLAB client.
NDI Cloud now records a CRC-32 for every uploaded file. An importer can therefore check which cloud copies match its local files and upload only the rest.
Changes
ndi.fun.file.crc32(path)andcrc32ToBase64(value)compute a file's CRC-32 in the cloud's encoding: base64 of the 4-byte big-endian value, the same format S3 uses forx-amz-checksum-crc32. The file is read in chunks withzlib.crc32.getFileUploadURL(..., checksum_crc32=crc)sendschecksumCRC32, and the returned URL signs thex-amz-checksum-crc32header.putFiles/putFileBytes(..., checksum_crc32=crc)send that header, so S3 rejects content that does not match. A malformed value raisesValueErrorbefore any request is made.ndi.cloud.upload.uploadSingleFilenow does both by default; passchecksum=Falseto turn it off.ndi.cloud.api.files.lookupFiles(dataset_id, uids)callsPOST /datasets/{id}/files/lookupand returns{"files": [{uid, uploaded, size, crc32}], "missing": [...]}. Duplicate uids are collapsed, and lists longer than the server's 5000-uid limit are split into several calls and merged.getSignedURLSetAllmerges each page'sfileInfointo one list.getSignedURLSet,listFilesandgetFileDetailsalready return the server's JSON unchanged, socrc32andfileInfocome through without other changes.lookupFiles,crc32andcrc32ToBase64are recorded withmatlab_branch: claude/file-crc32-lookup. That marker must be removed once NDI-matlab#1025 merges, and the check will say so.getFileUploadURL,putFiles,uploadSingleFile,listFiles(All),getSignedURLSet(All)andurlare synced to NDI-matlab8fa6ea5e, with a note in each decision log.CHANGELOG.mdhas an entry under Unreleased/Added.Tests
New
tests/test_cloud_api_files_crc32.py(25 tests, no network). It covers:checksumCRC32query parameter and thex-amz-checksum-crc32header;lookupFiles: deduplication, splitting at 5000 uids, and found/missing results;fileInfo;uploadSingleFilesending the checksum by default and not sending it withchecksum=False.New
TestFileChecksumsintests/test_cloud_live.py, mirroring the MATLABFilesTest:crc32read back fromlookupFiles,getFileDetailsandlistFiles;uploadSingleFilerecording the checksum;These tests fail (they do not skip) on a server without
/files/lookup, so a missing or broken route is reported rather than hidden.Two existing tests in
tests/test_phase2_gaps.pycalluploadSingleFileon a file that doesn't exist, with the upload API mocked. They now passchecksum=False, because the default now reads the file.Local results
black --check,ruff checkandpytest tests/all pass. The live tests need credentials and were not run locally.NDI_MATLAB_PATHpointing at a shallow NDI-matlab clone onclaude/file-crc32-lookup. None of the entries this PR changes fail. The checks that do fail here fail the same way on unmodified main in this environment: the clone lacks old commits and the lightsheet branch. CI checks out the full NDI-matlab branch of the same name, so it isn't affected by this.Merge order
Deploy ndi-cloud-node#163 to prod.Done.matlab_branchmarkers if #1025 merged first.🤖 Generated with Claude Code
https://claude.ai/code/session_01SwsqFA9Zs1HGm6YM4g2XRV
Generated by Claude Code