You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
S3FileSystem.pipe_file() and AioS3FileSystem.pipe_file() handle fsspec's compression argument differently by path:
Single-request path (data up to the block size, outside a transaction): compression is passed to PutObject, which botocore rejects with ParamValidationError: Unknown parameter in input: "compression".
Buffered path (in a transaction, or data larger than the block size): compression is passed to open(), which returns a compression wrapper (e.g. GzipFile) around the S3File. A successful write uploads the compressed data. A failed write calls _close_without_commit() on the wrapper, which raises AttributeError: 'GzipFile' object has no attribute '_close_without_commit'. The original error is hidden, and a 10-byte object holding only the gzip header is still uploaded, in and outside a transaction, so the guarantee from Write pipe_file() data without committing a failed write #1003 (a failed write leaves the existing object unchanged) does not hold.
Checked offline on master fe21250 with mocked requests, and with botocore parameter validation for the single-request path.
This also blocks #1034: the write-and-close helper cannot move to S3File while open() may return a compression wrapper (found in review of PR #1035).
Proposed fix
When compression is given, pipe_file() compresses the value in memory with the codec that open() would use (fsspec.core.get_compression() + fsspec.compression.compr, including "infer" from the path), and uploads the compressed bytes through the usual paths without passing compression to open() or S3. The routing and the multipart size check then use the compressed size. The same applies to the transaction path of AioS3FileSystem.
Problem
S3FileSystem.pipe_file()andAioS3FileSystem.pipe_file()handle fsspec'scompressionargument differently by path:compressionis passed to PutObject, which botocore rejects withParamValidationError: Unknown parameter in input: "compression".compressionis passed toopen(), which returns a compression wrapper (e.g.GzipFile) around theS3File. A successful write uploads the compressed data. A failed write calls_close_without_commit()on the wrapper, which raisesAttributeError: 'GzipFile' object has no attribute '_close_without_commit'. The original error is hidden, and a 10-byte object holding only the gzip header is still uploaded, in and outside a transaction, so the guarantee from Write pipe_file() data without committing a failed write #1003 (a failed write leaves the existing object unchanged) does not hold.Checked offline on master fe21250 with mocked requests, and with botocore parameter validation for the single-request path.
This also blocks #1034: the write-and-close helper cannot move to
S3Filewhileopen()may return a compression wrapper (found in review of PR #1035).Proposed fix
When
compressionis given,pipe_file()compresses the value in memory with the codec thatopen()would use (fsspec.core.get_compression()+fsspec.compression.compr, including"infer"from the path), and uploads the compressed bytes through the usual paths without passingcompressiontoopen()or S3. The routing and the multipart size check then use the compressed size. The same applies to the transaction path ofAioS3FileSystem.