Skip to content

Conversation

@memsharded
Copy link
Member

@memsharded memsharded commented Dec 2, 2025

grossag and others added 19 commits September 7, 2023 16:04
This change adds zstd support to conan in the following ways:
1. The person or build running `conan upload` can set a config value
   core.upload:compression_format = zstd
   to upload binaries using zstd instead of gzip.
2. The zstd compression is done entirely in Python using a combination
   of tarfile and python-zstandard. Then the file is uploaded as normal.
3. When downloading packages, if a .tar.zst file is encountered, the
   extraction code uses tarfile and python-zstandard to extract.

I chose python-zstandard as the library because that is what urllib3 uses.
Because zstd decompression is expected to just work if the server has a
.tar.zst file, I am including zstandard in requirements.txt.
https://python-zstandard.readthedocs.io/en/latest/projectinfo.html#state-of-project
recommends that we "Pin the package version to prevent unwanted breakage when this
change occurs!", although I doubt that much will change before an eventual 1.0.
CI is unable to find 0.21.0
1. Change requirements.txt to allow either zstandard 0.20 or 0.21. That
   prevents a downgrade for people who already have 0.21 installed, while
   also allowing CI to find 0.20.
2. Move compressformat parameter earlier in compress_files() function.
   It made a bit more sense to have it earlier; as long as consumers are
   correctly using positional kwargs, it shouldn't break anyone.
1. Fix bad merge causing uploader.py change to still refer to `self._app.cache.new_config`, when now we are supposed to use `self._global_conf`.
2. Change two output calls in uploader.py to only output the package file basename to be consistent with other existing log lines.
3. Use double quotes instead of single quotes to be more consistent with existing code.
1. Downgrade bufsize to 32KB because that performs well for compression and
   decompression. The values don't need to be the same, but it happened to be
   the best value in both compression and decompression tests.
2. Use a context manager for stream_reader as I do for stream_writer.
3. Add some comments about the bufsize value.
Still need to do some testing though.
Newer Python has this warning:

DeprecationWarning: Python 3.14 will, by default, filter extracted tar archives
and reject files or modify their metadata. Use the filter argument to control
this behavior
@czoido
Copy link
Contributor

czoido commented Dec 3, 2025

Maybe we should try to raise a more meaningful error for the cases that you uploaded a package with zstd for example and try to use if in a Python < 3.14. Right now it would be something like:

-------- Downloading 1 package --------
Downloading binary packages in 14 parallel threads
pepitorl/0.1: Retrieving package 461f120128f0af7aba967bf3e9e4aaa5892a82b3 from remote 'develop' 
pepitorl/0.1: ERROR: Exception while getting package: 461f120128f0af7aba967bf3e9e4aaa5892a82b3
pepitorl/0.1: ERROR: Exception: <class 'conan.errors.ConanException'> Error while extracting downloaded file '/Users/carlosz/Documents/developer/sandbox/test-compression/conan_home/p/pepitffc37dd6b5ca5/d/conan_package.tzst' to /Users/carlosz/Documents/developer/sandbox/test-compression/conan_home/p/pepitffc37dd6b5ca5/p
file could not be opened successfully:
- method gz: ReadError('not a gzip file')
- method bz2: ReadError('not a bzip2 file')
- method xz: ReadError('not an lzma file')
- method tar: ReadError('invalid header')

ERROR: Error while extracting downloaded file '/Users/carlosz/Documents/developer/sandbox/test-compression/conan_home/p/pepitffc37dd6b5ca5/d/conan_package.tzst' to /Users/carlosz/Documents/developer/sandbox/test-compression/conan_home/p/pepitffc37dd6b5ca5/p
file could not be opened successfully:
- method gz: ReadError('not a gzip file')
- method bz2: ReadError('not a bzip2 file')
- method xz: ReadError('not an lzma file')
- method tar: ReadError('invalid header')

Also there's the case of a Client < 2.24 trying to use that package, but for this one I think we can only make a clear documentation about that this case could happen?

-------- Downloading 1 package --------
Downloading binary packages in 14 parallel threads
pepitorl/0.1: Retrieving package 461f120128f0af7aba967bf3e9e4aaa5892a82b3 from remote 'develop' 
pepitorl/0.1: ERROR: Exception while getting package: 461f120128f0af7aba967bf3e9e4aaa5892a82b3
pepitorl/0.1: ERROR: Exception: <class 'conan.errors.ConanException'> Corrupted pepitorl/0.1:461f120128f0af7aba967bf3e9e4aaa5892a82b3 in 'develop' remote: no conan_package.tgz
ERROR: Corrupted pepitorl/0.1:461f120128f0af7aba967bf3e9e4aaa5892a82b3 in 'develop' remote: no conan_package.tgz

@memsharded memsharded requested a review from czoido December 3, 2025 14:10
# No compressed file exists, need to compress
compressformat = self._global_conf.get("core.upload:compression_format",
default="gz", choices=COMPRESSIONS)
if compressformat == "zst" and sys.version_info.minor < 14:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add risk warnings because of experimental

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.

Use LZMA compression for transmission of binary packages

3 participants