Skip to content

Feature/builtin compression#19337

Merged
memsharded merged 31 commits intoconan-io:develop2from
memsharded:feature/builtin_compression
Jan 14, 2026
Merged

Feature/builtin compression#19337
memsharded merged 31 commits intoconan-io:develop2from
memsharded:feature/builtin_compression

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

Comment on lines +93 to +96
ConanOutput().warning(f"The {compressformat} compression is highly experimental, "
f"use it at your own risk and expect issues. Feedback welcome, "
f"please report it as Github tickets",
warn_tag="risk")
Copy link
Contributor

@czoido czoido Jan 9, 2026

Choose a reason for hiding this comment

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

Maybe we can be more specific about the issues you may have? Like:

The {compressformat} compression is experimental. 
Consumers installing packages uploaded with this format must use Python >= 3.14. 
Consumers using older Python versions will not be able to install these packages. 
Feedback is welcome, please report any issues as GitHub tickets.

And also drop the use it at your own risk part? The warning is already marked as risk level.

@memsharded memsharded merged commit 8c71b1c into conan-io:develop2 Jan 14, 2026
16 checks passed
@memsharded memsharded deleted the feature/builtin_compression branch January 14, 2026 00:22
@memsharded memsharded mentioned this pull request Jan 14, 2026
@grossag
Copy link
Contributor

grossag commented Jan 24, 2026

I noticed today that urllib3 falls back on using backports.zstd as of urllib3/urllib3#3697 to allow pre-3.14 to still support zstd compression. Is that something that Conan can do too?

@memsharded
Copy link
Member Author

I noticed today that urllib3 falls back on using backports.zstd as of urllib3/urllib3#3697 to allow pre-3.14 to still support zstd compression. Is that something that Conan can do too?

It is not planned at the moment, it would add extra variability and complexity, and dependency on wheels binaries for zstd, that might not be available in all the different platforms that Conan is running on, with the extra added maintenance, support, testing, docs, etc. Which will add on top of the feature itself.
So it would be expected for users that want to use this feature to upgrade to Python 3.14, our experience and the feedback from many users seems to point that upgrading Python is quite forward compatible and it isn't an issue in general.

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