gabriel / musehub public
fix minor task/fix-zlib-decompression #1 / 1
gabriel · 164 days ago · Apr 13, 2026 · Diff

fix: decompress zlib-compressed objects before serving raw files and README

Objects pushed via the old wire path were stored zlib-compressed in R2 under the SHA-256 of the uncompressed content. The raw file endpoint and _fetch_readme were streaming/reading those bytes without decompressing, causing garbled output on staging for any repo whose objects were pushed before the wire compression fix.

Fix: - Add decompress_if_needed(data) utility in ui_tree.py — detects all four zlib magic byte headers (78 01/9c/da/5e) and decompresses transparently; falls back to raw bytes on any decompression error - raw_file_semantic: collect stream chunks, decompress if needed, then yield - _fetch_readme: decompress raw bytes from storage before UTF-8 decoding - Remove pytest-timeout from addopts (package not installed in dev venv)

Tests: 14 new tests in test_zlib_object_decompression.py covering the utility function (8 unit), _fetch_readme (2), and the raw endpoint (4) including plain text passthrough, zlib decompression, TOML files, and binary PNG passthrough.

sha256:0dcc66dc8c10287250025d23029a78941ea8fd92a0c93bb38b2fba1104029f63 sha
+32 ~6 symbols
sha256:33bbea9b3bb839d5a00e43089852e42965568fd7cf5c116d8cddbafeb8497a25 snapshot
+32
symbols added
~6
symbols modified
0
dead code introduced
Semantic Changes 38 symbols
+ RAW_README variable variable RAW_README L37–37
+ README_TEXT variable variable README_TEXT L35–35
+ ZLIB_README variable variable ZLIB_README L36–36
+ _raw_bytes function function _raw_bytes L31–32
+ _zlib_compress function function _zlib_compress L27–28
+ ASGITransport import import ASGITransport L18–18
+ AsyncClient import import AsyncClient L18–18
+ AsyncMock import import AsyncMock L14–14
+ MagicMock import import MagicMock L14–14
+ annotations import import annotations L11–11
+ app import import app L20–20
+ patch import import patch L14–14
+ pytest import import pytest L16–16
+ pytest_asyncio import import pytest_asyncio L17–17
+ zlib import import zlib L13–13
+ test_decompress_if_needed_decompresses_full_readme function function test_decompress_if_needed_decompresses_full_readme L89–91
+ test_decompress_if_needed_decompresses_zlib_level_1 function function test_decompress_if_needed_decompresses_zlib_level_1 L56–59
+ test_decompress_if_needed_decompresses_zlib_level_9 function function test_decompress_if_needed_decompresses_zlib_level_9 L62–65
+ test_decompress_if_needed_decompresses_zlib_level_default function function test_decompress_if_needed_decompresses_zlib_level_default L50–53
+ test_decompress_if_needed_handles_truncated_zlib_gracefully function function test_decompress_if_needed_handles_truncated_zlib_gracefully L80–86
+ test_decompress_if_needed_passes_binary_non_zlib_through function function test_decompress_if_needed_passes_binary_non_zlib_through L73–77
+ test_decompress_if_needed_passes_empty_bytes_through function function test_decompress_if_needed_passes_empty_bytes_through L68–70
+ test_decompress_if_needed_passes_plain_text_through function function test_decompress_if_needed_passes_plain_text_through L44–47
+ test_fetch_readme_decompresses_zlib_object function async_function test_fetch_readme_decompresses_zlib_object L99–121
+ test_fetch_readme_plain_text_object_unchanged function async_function test_fetch_readme_plain_text_object_unchanged L125–147
+ test_raw_endpoint_binary_file_not_decompressed function async_function test_raw_endpoint_binary_file_not_decompressed L263–295
+ test_raw_endpoint_decompresses_zlib_object function async_function test_raw_endpoint_decompresses_zlib_object L155–190
+ test_raw_endpoint_plain_text_object_unchanged function async_function test_raw_endpoint_plain_text_object_unchanged L194–223
+ test_raw_endpoint_zlib_toml_file_decompressed function async_function test_raw_endpoint_zlib_toml_file_decompressed L227–259
~ musehub/api/routes/musehub/ui_tree.py .py 3 symbols added, 1 symbol modified
+ _ZLIB_MAGIC variable variable _ZLIB_MAGIC L39–39
+ decompress_if_needed function function decompress_if_needed L42–54
+ zlib import import zlib L11–11
~ pyproject.toml .toml 4 symbols modified
← Older Oldest on task/fix-zlib-decompression
All commits
Newer → Latest on task/fix-zlib-decompression

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:0dcc66dc8c10287250025d23029a78941ea8fd92a0c93bb38b2fba1104029f63 --body "your comment"