spillgate 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spillgate-0.1.0/.gitattributes +10 -0
- spillgate-0.1.0/.github/CODEOWNERS +1 -0
- spillgate-0.1.0/.github/dependabot.yml +8 -0
- spillgate-0.1.0/.github/workflows/ci.yml +72 -0
- spillgate-0.1.0/.github/workflows/codeql.yml +25 -0
- spillgate-0.1.0/.github/workflows/nightly-fuzz.yml +25 -0
- spillgate-0.1.0/.github/workflows/release.yml +61 -0
- spillgate-0.1.0/.github/workflows/scorecard.yml +27 -0
- spillgate-0.1.0/.gitignore +10 -0
- spillgate-0.1.0/CHANGELOG.md +13 -0
- spillgate-0.1.0/CONTRIBUTING.md +24 -0
- spillgate-0.1.0/LICENSE +21 -0
- spillgate-0.1.0/PKG-INFO +176 -0
- spillgate-0.1.0/README.md +126 -0
- spillgate-0.1.0/RELEASING.md +46 -0
- spillgate-0.1.0/SECURITY.md +31 -0
- spillgate-0.1.0/conformance/SCHEMA.md +94 -0
- spillgate-0.1.0/conformance/SOURCE +3 -0
- spillgate-0.1.0/conformance/manifest.json +11211 -0
- spillgate-0.1.0/conformance/manifest.schema.json +122 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0019.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0020.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0021.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0022.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0023.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0024.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0025.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0026.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0027.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-BND-0028.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0015.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-CHAIN-0016.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0002.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0003.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0004.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0015.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0016.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0017.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0018.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0019.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0020.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0021.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0022.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0023.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0024.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0025.bin +2 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0026.bin +2 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0027.bin +2 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0028.bin +2 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0029.bin +2 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0030.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0031.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0032.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0033.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0034.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0035.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0036.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0037.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0038.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0039.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0040.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0041.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0042.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0043.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0044.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0045.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0046.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0047.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0048.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0049.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0050.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0051.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0052.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0053.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0054.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0055.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0056.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0057.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0058.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0059.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0060.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0061.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0062.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0063.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0064.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0065.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0066.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0067.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0068.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0069.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0070.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0071.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0072.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0073.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0074.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0075.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0076.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0077.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0078.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0079.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0080.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0081.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0082.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0083.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0084.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0085.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0086.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0087.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0088.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0089.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0090.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0091.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-HDR-0092.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0002.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0003.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0004.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-INP-0015.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0002.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0003.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0004.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIE-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0002.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0003.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0004.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-LIM-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0002.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0003.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0004.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0015.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0016.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0017.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0018.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0019.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0020.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0021.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0022.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0023.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0024.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0025.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0026.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0027.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0028.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0029.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0030.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0031.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0032.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0033.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0034.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0035.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0036.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0037.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0038.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0039.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0040.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0041.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0042.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0043.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0044.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0045.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0046.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0047.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0048.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0049.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0050.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0051.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0052.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0053.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0054.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0055.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0056.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0057.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0058.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0059.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0060.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0061.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0062.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0063.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0064.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0065.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0066.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0067.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0068.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0069.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0070.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0071.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0072.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0073.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0074.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0075.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0076.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0077.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0078.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0079.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0080.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0081.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0082.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0083.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0084.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0085.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0086.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0087.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0088.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0089.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0090.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0091.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0092.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0093.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0094.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0095.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0096.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0097.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0098.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0099.bin +1 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MAL-0100.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0002.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0003.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0004.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0005.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0006.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0007.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0008.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-MULTI-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-RAT-0001.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-RAT-0009.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0010.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0011.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0012.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0013.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0014.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0015.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0016.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0017.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0018.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0019.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0020.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0021.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0022.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0023.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0024.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0025.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0026.bin +0 -0
- spillgate-0.1.0/conformance/vectors/small/SG-V-WIN-0027.bin +0 -0
- spillgate-0.1.0/docs/how-to.md +443 -0
- spillgate-0.1.0/docs/memory.md +29 -0
- spillgate-0.1.0/pyproject.toml +58 -0
- spillgate-0.1.0/spec/SPEC.md +153 -0
- spillgate-0.1.0/spec/generators.md +49 -0
- spillgate-0.1.0/src/spillgate/__init__.py +77 -0
- spillgate-0.1.0/src/spillgate/_cancel.py +25 -0
- spillgate-0.1.0/src/spillgate/_chain.py +117 -0
- spillgate-0.1.0/src/spillgate/_deflate.py +89 -0
- spillgate-0.1.0/src/spillgate/_guard.py +154 -0
- spillgate-0.1.0/src/spillgate/_gzip.py +128 -0
- spillgate-0.1.0/src/spillgate/_inflate.py +71 -0
- spillgate-0.1.0/src/spillgate/_meter.py +204 -0
- spillgate-0.1.0/src/spillgate/br.py +203 -0
- spillgate-0.1.0/src/spillgate/codec.py +44 -0
- spillgate-0.1.0/src/spillgate/decoder.py +201 -0
- spillgate-0.1.0/src/spillgate/errors.py +224 -0
- spillgate-0.1.0/src/spillgate/header.py +106 -0
- spillgate-0.1.0/src/spillgate/limits.py +141 -0
- spillgate-0.1.0/src/spillgate/py.typed +0 -0
- spillgate-0.1.0/src/spillgate/zstd.py +275 -0
- spillgate-0.1.0/tests/corpus.py +408 -0
- spillgate-0.1.0/tests/helpers.py +74 -0
- spillgate-0.1.0/tests/test_api_contract.py +131 -0
- spillgate-0.1.0/tests/test_br.py +212 -0
- spillgate-0.1.0/tests/test_codecs.py +270 -0
- spillgate-0.1.0/tests/test_conformance.py +273 -0
- spillgate-0.1.0/tests/test_hardening.py +300 -0
- spillgate-0.1.0/tests/test_limits_and_header.py +305 -0
- spillgate-0.1.0/tests/test_properties.py +158 -0
- spillgate-0.1.0/tests/test_python_traps.py +203 -0
- spillgate-0.1.0/tests/test_reader_contract.py +462 -0
- spillgate-0.1.0/tests/test_review_codecs.py +60 -0
- spillgate-0.1.0/tests/test_review_fresh.py +56 -0
- spillgate-0.1.0/tests/test_zstd.py +308 -0
- spillgate-0.1.0/tools/spectrace.py +66 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Text is LF everywhere so hashes and golden files are identical on every OS.
|
|
2
|
+
* text=auto eol=lf
|
|
3
|
+
|
|
4
|
+
# Conformance vectors are byte-exact; never normalize them.
|
|
5
|
+
conformance/vectors/** -text
|
|
6
|
+
*.gz -text
|
|
7
|
+
*.zz -text
|
|
8
|
+
*.br -text
|
|
9
|
+
*.zst -text
|
|
10
|
+
*.bin -text
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @FelixMiddelhoff
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
21
|
+
python: ["3.11", "3.12", "3.13", "3.14"]
|
|
22
|
+
runs-on: ${{ matrix.os }}
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
with: { persist-credentials: false }
|
|
26
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
27
|
+
with: { python-version: "${{ matrix.python }}" }
|
|
28
|
+
- run: python -m pip install pytest hypothesis "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
|
|
29
|
+
- name: tests (all 354 conformance vectors with brotli and zstd, properties, traps)
|
|
30
|
+
run: python -m pytest
|
|
31
|
+
env:
|
|
32
|
+
SPILLGATE_NO_SKIPS: "1" # a missing codec fails the run instead of skipping vectors
|
|
33
|
+
core-only:
|
|
34
|
+
# The core must work and test cleanly without any optional dependency.
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
38
|
+
with: { persist-credentials: false }
|
|
39
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
40
|
+
with: { python-version: "3.11" }
|
|
41
|
+
- run: python -m pip install pytest hypothesis
|
|
42
|
+
- run: python -m pytest -m "not large"
|
|
43
|
+
audit:
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
47
|
+
with: { persist-credentials: false }
|
|
48
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
49
|
+
with: { python-version: "3.13" }
|
|
50
|
+
- run: python -m pip install pip-audit "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
|
|
51
|
+
- name: known vulnerabilities in the optional dependencies
|
|
52
|
+
run: python -m pip_audit
|
|
53
|
+
|
|
54
|
+
static:
|
|
55
|
+
runs-on: ubuntu-latest
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
58
|
+
with: { persist-credentials: false }
|
|
59
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
60
|
+
with: { python-version: "3.13" }
|
|
61
|
+
- run: python -m pip install ruff mypy pytest hypothesis build brotli zstandard
|
|
62
|
+
- run: python -m ruff check .
|
|
63
|
+
- run: python -m ruff format --check .
|
|
64
|
+
- run: python -m mypy
|
|
65
|
+
- name: every rule of the specification is covered
|
|
66
|
+
run: python tools/spectrace.py
|
|
67
|
+
- name: the package builds and installs into a clean environment
|
|
68
|
+
run: |
|
|
69
|
+
python -m build
|
|
70
|
+
python -m venv /tmp/clean
|
|
71
|
+
/tmp/clean/bin/python -m pip install dist/*.whl
|
|
72
|
+
/tmp/clean/bin/python -I -c "import spillgate; print(spillgate.Limits(max_output=1))"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: codeql
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "41 3 * * 1"
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
analyze:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
security-events: write
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
22
|
+
with: { persist-credentials: false }
|
|
23
|
+
- uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
|
24
|
+
with: { languages: python, build-mode: none }
|
|
25
|
+
- uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: nightly-fuzz
|
|
2
|
+
|
|
3
|
+
# Property tests with a much larger example budget than the pull-request run.
|
|
4
|
+
on:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: "27 2 * * *"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
hypothesis:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
timeout-minutes: 90
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
18
|
+
with: { persist-credentials: false }
|
|
19
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
20
|
+
with: { python-version: "3.13" }
|
|
21
|
+
- run: python -m pip install pytest hypothesis
|
|
22
|
+
- name: properties with a large budget
|
|
23
|
+
run: python -m pytest tests/test_properties.py
|
|
24
|
+
env:
|
|
25
|
+
SPILLGATE_HYPOTHESIS_EXAMPLES: "200000"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# Publishes to PyPI with Trusted Publishing (OpenID Connect): no API token is stored anywhere.
|
|
4
|
+
# It runs only for a tag like v0.1.0 that the maintainer pushes, builds exactly once, checks
|
|
5
|
+
# that the tag equals the package version, tests the built wheel in a clean environment and
|
|
6
|
+
# then publishes the same files from a protected environment.
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v[0-9]+.[0-9]+.[0-9]+"]
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
with: { persist-credentials: false }
|
|
20
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
21
|
+
with: { python-version: "3.13" }
|
|
22
|
+
- run: python -m pip install build twine pytest hypothesis "brotli>=1.2.1,<2" "zstandard>=0.25.0,<1"
|
|
23
|
+
- name: the tag must equal the package version
|
|
24
|
+
run: |
|
|
25
|
+
version=$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
26
|
+
test "v$version" = "$GITHUB_REF_NAME" || { echo "tag $GITHUB_REF_NAME != version $version"; exit 1; }
|
|
27
|
+
- name: the full suite passes, nothing skipped
|
|
28
|
+
run: python -m pytest
|
|
29
|
+
env:
|
|
30
|
+
SPILLGATE_NO_SKIPS: "1"
|
|
31
|
+
- run: python -m build
|
|
32
|
+
- run: python -m twine check --strict dist/*
|
|
33
|
+
- name: the wheel works in a clean environment
|
|
34
|
+
run: |
|
|
35
|
+
python -m venv /tmp/clean
|
|
36
|
+
/tmp/clean/bin/python -m pip install dist/*.whl
|
|
37
|
+
/tmp/clean/bin/python -I -c "import spillgate; print(spillgate.Limits(max_output=1))"
|
|
38
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
39
|
+
with:
|
|
40
|
+
name: dist
|
|
41
|
+
path: dist/
|
|
42
|
+
if-no-files-found: error
|
|
43
|
+
|
|
44
|
+
publish:
|
|
45
|
+
needs: build
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
# The environment "pypi" is created in the repository settings and requires the maintainer's
|
|
48
|
+
# approval before this job runs. The PyPI project trusts exactly this workflow and
|
|
49
|
+
# environment (see RELEASING.md).
|
|
50
|
+
environment:
|
|
51
|
+
name: pypi
|
|
52
|
+
url: https://pypi.org/p/spillgate
|
|
53
|
+
permissions:
|
|
54
|
+
id-token: write # the only permission that lets this job publish
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
57
|
+
with:
|
|
58
|
+
name: dist
|
|
59
|
+
path: dist/
|
|
60
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
|
|
61
|
+
# Attestations (build provenance) are produced by default and uploaded with the files.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: scorecard
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "23 4 * * 2"
|
|
9
|
+
|
|
10
|
+
permissions: read-all
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
analysis:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
security-events: write
|
|
17
|
+
id-token: write
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
with: { persist-credentials: false }
|
|
21
|
+
- uses: ossf/scorecard-action@fa7117db83c52d787ae5a89f350999701505d78e # v2.5.0
|
|
22
|
+
with:
|
|
23
|
+
results_file: results.sarif
|
|
24
|
+
results_format: sarif
|
|
25
|
+
publish_results: true
|
|
26
|
+
- uses: github/codeql-action/upload-sarif@33d7b85da1a04171e211befe2c739303b9a4c066 # v4.39.3
|
|
27
|
+
with: { sarif_file: results.sarif }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions below 1.0 may still change the API.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 - 2026-11-11
|
|
6
|
+
|
|
7
|
+
First version. The Python implementation of the spillgate specification.
|
|
8
|
+
|
|
9
|
+
- `Limits` with a required `max_output`, ratio, layer, input limits; typed, sticky errors (one exception class per outcome kind).
|
|
10
|
+
- gzip, deflate and identity in the standard-library-only core; own gzip and zlib framing over `zlib.decompressobj` with `max_length` always greater than zero.
|
|
11
|
+
- Optional extras `spillgate[brotli]` (brotli >= 1.2.1) and `spillgate[zstd]` (zstandard >= 0.25.0) with window caps and bounded steps.
|
|
12
|
+
- Passes the full conformance corpus (354 vectors) of the reference implementation.
|
|
13
|
+
- Integration guide in `docs/how-to.md`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Run the checks
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
python -m pip install pytest hypothesis ruff mypy
|
|
7
|
+
python -m pytest # everything, including the large generated vectors (about 40 s)
|
|
8
|
+
python -m pytest -m "not large" # without the GiB-scale vectors
|
|
9
|
+
python tools/spectrace.py # every rule of the specification is named by a test or vector
|
|
10
|
+
SPILLGATE_NO_SKIPS=1 python -m pytest # with brotli and zstandard installed: no vector may be skipped
|
|
11
|
+
python -m ruff check . && python -m ruff format --check .
|
|
12
|
+
python -m mypy
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Rules
|
|
16
|
+
|
|
17
|
+
- The specification comes first. Behavior that the spec does not describe is not added here: change `spec/SPEC.md` in the reference repository, add vectors there, then sync.
|
|
18
|
+
- `spectrace` counts a rule as covered when a test docstring or a vector names it; that is a checklist, not proof that the test asserts everything the rule says. Review the assertions too.
|
|
19
|
+
- Test first for every bug. A test names the rules it protects in its docstring (`Covers: SG-R-...`); `tools/spectrace.py` reads that line.
|
|
20
|
+
- Never weaken a test or a conformance vector to make code pass.
|
|
21
|
+
- `conformance/` and `spec/` are copies. Do not edit them here; update them from the reference repository and record the release in `conformance/SOURCE`.
|
|
22
|
+
- The core has no dependencies and starts no threads. Optional codecs are extras.
|
|
23
|
+
- Never call an unbounded standard-library API (`zlib.decompress`, `gzip.decompress`, `GzipFile`, `decompress()` without `max_length`, `flush()`); `tests/test_python_traps.py` fails if the source does.
|
|
24
|
+
- Code is read by people: short functions, a docstring that explains why, rule IDs where a rule applies.
|
spillgate-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Felix Middelhoff
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
spillgate-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: spillgate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Decode untrusted compressed data with mandatory limits (decompression-bomb gate).
|
|
5
|
+
Project-URL: Homepage, https://github.com/FelixMiddelhoff/spillgate-python
|
|
6
|
+
Project-URL: Specification, https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md
|
|
7
|
+
Author: Felix Middelhoff
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Felix Middelhoff
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: brotli,content-encoding,decompression-bomb,deflate,gzip,security,zstd
|
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
36
|
+
Classifier: Topic :: Security
|
|
37
|
+
Classifier: Topic :: System :: Archiving :: Compression
|
|
38
|
+
Classifier: Typing :: Typed
|
|
39
|
+
Requires-Python: >=3.11
|
|
40
|
+
Provides-Extra: brotli
|
|
41
|
+
Requires-Dist: brotli<2,>=1.2.1; extra == 'brotli'
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: hypothesis>=6.100; extra == 'dev'
|
|
44
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
45
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
46
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
47
|
+
Provides-Extra: zstd
|
|
48
|
+
Requires-Dist: zstandard<1,>=0.25.0; extra == 'zstd'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# spillgate (Python)
|
|
52
|
+
|
|
53
|
+
Decode untrusted compressed data in Python with mandatory limits. A decompression bomb
|
|
54
|
+
ends in a typed exception instead of exhausting memory.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from spillgate import Limits, OutputLimitError, decode_all
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
body = decode_all(response_bytes, "gzip", Limits(max_output=8 * 2**20))
|
|
61
|
+
except OutputLimitError:
|
|
62
|
+
... # refuse the response
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- `Content-Encoding` chains: `gzip` (and `x-gzip`), `deflate`, `identity`; `br` and `zstd` as
|
|
66
|
+
optional extras (see below).
|
|
67
|
+
- `max_output` is required. There is no unlimited setting.
|
|
68
|
+
- Every layer is limited, including the intermediate layers of a chain.
|
|
69
|
+
- Expansion ratio and chain length are limited by default.
|
|
70
|
+
- Unknown, malformed or too deep `Content-Encoding` headers are refused, never passed through.
|
|
71
|
+
- The core has no dependencies and starts no threads.
|
|
72
|
+
|
|
73
|
+
This is the Python implementation of the language-neutral
|
|
74
|
+
[spillgate specification](https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md).
|
|
75
|
+
It passes the same conformance corpus as the Go reference implementation.
|
|
76
|
+
|
|
77
|
+
Python 3.11 or newer. **Integrating it into your service: [docs/how-to.md](docs/how-to.md).**
|
|
78
|
+
|
|
79
|
+
## Use
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from spillgate import Decoder, Limits
|
|
83
|
+
|
|
84
|
+
decoder = Decoder(Limits(max_output=8 * 2**20)) # build once, share between threads
|
|
85
|
+
|
|
86
|
+
with decoder.reader(resp.raw, resp.headers.get_all("Content-Encoding", [])) as body:
|
|
87
|
+
for chunk in iter(lambda: body.read(65536), b""):
|
|
88
|
+
handle(chunk) # any exception: discard everything
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`decode_all` / `Decoder.read_all` return the whole body or raise, never partial data.
|
|
92
|
+
`Decoder.reader` streams; bytes can arrive before a later error, so treat any
|
|
93
|
+
`SpillgateError` as failure of the whole body.
|
|
94
|
+
|
|
95
|
+
`source` is `bytes` or any object with `read(n)`. It is not closed by spillgate.
|
|
96
|
+
|
|
97
|
+
### Brotli and zstd
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
pip install "spillgate[brotli]" # brotli >= 1.2.1
|
|
101
|
+
pip install "spillgate[zstd]" # zstandard >= 0.25.0
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from spillgate import Decoder, Limits, br, zstd
|
|
106
|
+
|
|
107
|
+
decoder = Decoder(
|
|
108
|
+
Limits(max_output=8 * 2**20),
|
|
109
|
+
codecs={"br": br.codec(), "zstd": zstd.codec()}, # offer only what you installed
|
|
110
|
+
)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Both decoders are C libraries and are treated as untrusted: spillgate reads the window size
|
|
114
|
+
(brotli) or the whole frame structure (zstd) itself, refuses oversized windows as `memory_limit`
|
|
115
|
+
before anything is decoded, and gives the library bounded steps. The window costs memory per
|
|
116
|
+
request: up to 16 MiB for brotli and 8 MiB for zstd by default. Lower them with
|
|
117
|
+
`br.codec(max_window_bits=22)` and `zstd.codec(max_window_bytes=2**21)` when a server decodes
|
|
118
|
+
many requests at once. Older `brotli` versions are refused at import time: before 1.2.1 they
|
|
119
|
+
had no output limit and a memory-corruption bug in the decoder (CVE-2026-111497).
|
|
120
|
+
Always close readers (`with ... as body`) so the decoder state is released.
|
|
121
|
+
|
|
122
|
+
CPU: frames and blocks that produce no output cost CPU but neither output nor ratio limit sees
|
|
123
|
+
them. A zstd body made of millions of empty frames costs about one second per MB of input
|
|
124
|
+
(gzip: milliseconds). Bound the compressed size with `max_input` or your server's body limit.
|
|
125
|
+
|
|
126
|
+
### Limits
|
|
127
|
+
|
|
128
|
+
| Field | Meaning | Default |
|
|
129
|
+
| --- | --- | --- |
|
|
130
|
+
| `max_output` | bytes one layer may produce, `1 .. 2**63-1` (required) | none |
|
|
131
|
+
| `max_layers` | longest chain, `1 .. 16` | 5 |
|
|
132
|
+
| `max_ratio` | output bytes per input byte the codec consumed | 1000 |
|
|
133
|
+
| `ratio_grace` | output below which the ratio is not checked | 64 KiB |
|
|
134
|
+
| `max_input` | cap on compressed bytes taken from the source | none |
|
|
135
|
+
| `disable_ratio_limit` | the one named opt-out of the ratio check | `False` |
|
|
136
|
+
|
|
137
|
+
`Limits` is immutable and validated when created. No number disables a limit: `0`, negative
|
|
138
|
+
values, floats, strings and `bool` are all refused with `InvalidLimitsError`.
|
|
139
|
+
|
|
140
|
+
### Errors
|
|
141
|
+
|
|
142
|
+
Every refusal is a `SpillgateError` with a `kind` (`spillgate.Kind`), a `layer` and a
|
|
143
|
+
`limit`; there is one subclass per kind: `OutputLimitError`, `RatioLimitError`,
|
|
144
|
+
`LayerLimitError`, `InputLimitError`, `MemoryLimitError`, `UnsupportedEncodingError`,
|
|
145
|
+
`MalformedEncodingError`, `CorruptError`, `InternalError`, `CanceledError`, `SourceError`,
|
|
146
|
+
`InvalidLimitsError`. Errors are sticky: after one, every later read raises the same error.
|
|
147
|
+
Error messages never contain more than 32 bytes of attacker data, and that data is escaped.
|
|
148
|
+
|
|
149
|
+
`cancel=callable` on `reader` / `read_all` is polled before every read and every 4 KiB of
|
|
150
|
+
input. It cannot interrupt one step inside the decoder; the limits bound the work there.
|
|
151
|
+
|
|
152
|
+
### Why not `zlib.decompress` or `gzip.GzipFile`?
|
|
153
|
+
|
|
154
|
+
Because they have no bound. The traps this library avoids: `decompressobj().decompress(data)`
|
|
155
|
+
without `max_length` (and `max_length=0`, which means *unlimited*), `flush()`, one-shot
|
|
156
|
+
`gzip.decompress`, and `GzipFile.read()` without a size. `tests/test_python_traps.py` scans the
|
|
157
|
+
source for them.
|
|
158
|
+
|
|
159
|
+
## What it does not cover
|
|
160
|
+
|
|
161
|
+
Archives (zip, tar), bounding the compressed input (use `max_input` or limit the request body
|
|
162
|
+
size), connection timeouts, encrypted content, and memory-safety bugs in the C libraries
|
|
163
|
+
behind `zlib` and the optional codecs beyond what the limits contain. See
|
|
164
|
+
[docs/memory.md](docs/memory.md) for the memory bounds.
|
|
165
|
+
|
|
166
|
+
## Specification and tests
|
|
167
|
+
|
|
168
|
+
`spec/SPEC.md` and `conformance/` are copies of the reference repository at the release named
|
|
169
|
+
in `conformance/SOURCE`. The suite runs all vectors (bombs, malformed streams, header attacks,
|
|
170
|
+
lying size fields), property tests, a scan for unbounded standard-library calls, and memory
|
|
171
|
+
measurements with `tracemalloc`. `python tools/spectrace.py` checks that every rule of the
|
|
172
|
+
specification is covered.
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT, see [LICENSE](LICENSE). Report vulnerabilities as described in [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# spillgate (Python)
|
|
2
|
+
|
|
3
|
+
Decode untrusted compressed data in Python with mandatory limits. A decompression bomb
|
|
4
|
+
ends in a typed exception instead of exhausting memory.
|
|
5
|
+
|
|
6
|
+
```python
|
|
7
|
+
from spillgate import Limits, OutputLimitError, decode_all
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
body = decode_all(response_bytes, "gzip", Limits(max_output=8 * 2**20))
|
|
11
|
+
except OutputLimitError:
|
|
12
|
+
... # refuse the response
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- `Content-Encoding` chains: `gzip` (and `x-gzip`), `deflate`, `identity`; `br` and `zstd` as
|
|
16
|
+
optional extras (see below).
|
|
17
|
+
- `max_output` is required. There is no unlimited setting.
|
|
18
|
+
- Every layer is limited, including the intermediate layers of a chain.
|
|
19
|
+
- Expansion ratio and chain length are limited by default.
|
|
20
|
+
- Unknown, malformed or too deep `Content-Encoding` headers are refused, never passed through.
|
|
21
|
+
- The core has no dependencies and starts no threads.
|
|
22
|
+
|
|
23
|
+
This is the Python implementation of the language-neutral
|
|
24
|
+
[spillgate specification](https://github.com/FelixMiddelhoff/spillgate/blob/main/spec/SPEC.md).
|
|
25
|
+
It passes the same conformance corpus as the Go reference implementation.
|
|
26
|
+
|
|
27
|
+
Python 3.11 or newer. **Integrating it into your service: [docs/how-to.md](docs/how-to.md).**
|
|
28
|
+
|
|
29
|
+
## Use
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from spillgate import Decoder, Limits
|
|
33
|
+
|
|
34
|
+
decoder = Decoder(Limits(max_output=8 * 2**20)) # build once, share between threads
|
|
35
|
+
|
|
36
|
+
with decoder.reader(resp.raw, resp.headers.get_all("Content-Encoding", [])) as body:
|
|
37
|
+
for chunk in iter(lambda: body.read(65536), b""):
|
|
38
|
+
handle(chunk) # any exception: discard everything
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`decode_all` / `Decoder.read_all` return the whole body or raise, never partial data.
|
|
42
|
+
`Decoder.reader` streams; bytes can arrive before a later error, so treat any
|
|
43
|
+
`SpillgateError` as failure of the whole body.
|
|
44
|
+
|
|
45
|
+
`source` is `bytes` or any object with `read(n)`. It is not closed by spillgate.
|
|
46
|
+
|
|
47
|
+
### Brotli and zstd
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
pip install "spillgate[brotli]" # brotli >= 1.2.1
|
|
51
|
+
pip install "spillgate[zstd]" # zstandard >= 0.25.0
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from spillgate import Decoder, Limits, br, zstd
|
|
56
|
+
|
|
57
|
+
decoder = Decoder(
|
|
58
|
+
Limits(max_output=8 * 2**20),
|
|
59
|
+
codecs={"br": br.codec(), "zstd": zstd.codec()}, # offer only what you installed
|
|
60
|
+
)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Both decoders are C libraries and are treated as untrusted: spillgate reads the window size
|
|
64
|
+
(brotli) or the whole frame structure (zstd) itself, refuses oversized windows as `memory_limit`
|
|
65
|
+
before anything is decoded, and gives the library bounded steps. The window costs memory per
|
|
66
|
+
request: up to 16 MiB for brotli and 8 MiB for zstd by default. Lower them with
|
|
67
|
+
`br.codec(max_window_bits=22)` and `zstd.codec(max_window_bytes=2**21)` when a server decodes
|
|
68
|
+
many requests at once. Older `brotli` versions are refused at import time: before 1.2.1 they
|
|
69
|
+
had no output limit and a memory-corruption bug in the decoder (CVE-2026-111497).
|
|
70
|
+
Always close readers (`with ... as body`) so the decoder state is released.
|
|
71
|
+
|
|
72
|
+
CPU: frames and blocks that produce no output cost CPU but neither output nor ratio limit sees
|
|
73
|
+
them. A zstd body made of millions of empty frames costs about one second per MB of input
|
|
74
|
+
(gzip: milliseconds). Bound the compressed size with `max_input` or your server's body limit.
|
|
75
|
+
|
|
76
|
+
### Limits
|
|
77
|
+
|
|
78
|
+
| Field | Meaning | Default |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `max_output` | bytes one layer may produce, `1 .. 2**63-1` (required) | none |
|
|
81
|
+
| `max_layers` | longest chain, `1 .. 16` | 5 |
|
|
82
|
+
| `max_ratio` | output bytes per input byte the codec consumed | 1000 |
|
|
83
|
+
| `ratio_grace` | output below which the ratio is not checked | 64 KiB |
|
|
84
|
+
| `max_input` | cap on compressed bytes taken from the source | none |
|
|
85
|
+
| `disable_ratio_limit` | the one named opt-out of the ratio check | `False` |
|
|
86
|
+
|
|
87
|
+
`Limits` is immutable and validated when created. No number disables a limit: `0`, negative
|
|
88
|
+
values, floats, strings and `bool` are all refused with `InvalidLimitsError`.
|
|
89
|
+
|
|
90
|
+
### Errors
|
|
91
|
+
|
|
92
|
+
Every refusal is a `SpillgateError` with a `kind` (`spillgate.Kind`), a `layer` and a
|
|
93
|
+
`limit`; there is one subclass per kind: `OutputLimitError`, `RatioLimitError`,
|
|
94
|
+
`LayerLimitError`, `InputLimitError`, `MemoryLimitError`, `UnsupportedEncodingError`,
|
|
95
|
+
`MalformedEncodingError`, `CorruptError`, `InternalError`, `CanceledError`, `SourceError`,
|
|
96
|
+
`InvalidLimitsError`. Errors are sticky: after one, every later read raises the same error.
|
|
97
|
+
Error messages never contain more than 32 bytes of attacker data, and that data is escaped.
|
|
98
|
+
|
|
99
|
+
`cancel=callable` on `reader` / `read_all` is polled before every read and every 4 KiB of
|
|
100
|
+
input. It cannot interrupt one step inside the decoder; the limits bound the work there.
|
|
101
|
+
|
|
102
|
+
### Why not `zlib.decompress` or `gzip.GzipFile`?
|
|
103
|
+
|
|
104
|
+
Because they have no bound. The traps this library avoids: `decompressobj().decompress(data)`
|
|
105
|
+
without `max_length` (and `max_length=0`, which means *unlimited*), `flush()`, one-shot
|
|
106
|
+
`gzip.decompress`, and `GzipFile.read()` without a size. `tests/test_python_traps.py` scans the
|
|
107
|
+
source for them.
|
|
108
|
+
|
|
109
|
+
## What it does not cover
|
|
110
|
+
|
|
111
|
+
Archives (zip, tar), bounding the compressed input (use `max_input` or limit the request body
|
|
112
|
+
size), connection timeouts, encrypted content, and memory-safety bugs in the C libraries
|
|
113
|
+
behind `zlib` and the optional codecs beyond what the limits contain. See
|
|
114
|
+
[docs/memory.md](docs/memory.md) for the memory bounds.
|
|
115
|
+
|
|
116
|
+
## Specification and tests
|
|
117
|
+
|
|
118
|
+
`spec/SPEC.md` and `conformance/` are copies of the reference repository at the release named
|
|
119
|
+
in `conformance/SOURCE`. The suite runs all vectors (bombs, malformed streams, header attacks,
|
|
120
|
+
lying size fields), property tests, a scan for unbounded standard-library calls, and memory
|
|
121
|
+
measurements with `tracemalloc`. `python tools/spectrace.py` checks that every rule of the
|
|
122
|
+
specification is covered.
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT, see [LICENSE](LICENSE). Report vulnerabilities as described in [SECURITY.md](SECURITY.md).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Releasing to PyPI
|
|
2
|
+
|
|
3
|
+
Releases use PyPI **Trusted Publishing**: the workflow `.github/workflows/release.yml` proves its
|
|
4
|
+
identity to PyPI with a short-lived OpenID Connect token. No password or API token exists in the
|
|
5
|
+
repository, in GitHub secrets or on a developer machine.
|
|
6
|
+
|
|
7
|
+
## One-time setup (maintainer)
|
|
8
|
+
|
|
9
|
+
1. **GitHub environment.** Repository **Settings → Environments → New environment**, name `pypi`.
|
|
10
|
+
Add yourself under *Required reviewers* so that every publish needs an explicit approval.
|
|
11
|
+
Optionally restrict *Deployment branches and tags* to the pattern `v*`.
|
|
12
|
+
2. **PyPI pending publisher.** On <https://pypi.org/manage/account/publishing/> add a *pending
|
|
13
|
+
publisher* (this creates the project name `spillgate` on the first publish):
|
|
14
|
+
- PyPI project name: `spillgate`
|
|
15
|
+
- Owner: `FelixMiddelhoff`
|
|
16
|
+
- Repository name: `spillgate-python`
|
|
17
|
+
- Workflow name: `release.yml`
|
|
18
|
+
- Environment name: `pypi`
|
|
19
|
+
3. Turn on two-factor authentication for the PyPI account and keep the recovery codes safe.
|
|
20
|
+
|
|
21
|
+
The PyPI name is reserved only when the first release is published, so do step 2 and the first
|
|
22
|
+
release close together.
|
|
23
|
+
|
|
24
|
+
## Each release
|
|
25
|
+
|
|
26
|
+
1. Update `CHANGELOG.md` and set `version` in `pyproject.toml` (for example `0.1.0`). Commit to `main` and wait for a green CI.
|
|
27
|
+
2. Tag exactly that version and push the tag:
|
|
28
|
+
```
|
|
29
|
+
git tag -a v0.1.0 -m "v0.1.0"
|
|
30
|
+
git push origin v0.1.0
|
|
31
|
+
```
|
|
32
|
+
3. The `release` workflow builds once, checks that the tag equals the version, runs the whole suite
|
|
33
|
+
with brotli and zstd installed and nothing skipped, checks the wheel in a clean environment, and
|
|
34
|
+
waits for your approval in the `pypi` environment. After the approval it publishes the same
|
|
35
|
+
files, with build attestations, to PyPI.
|
|
36
|
+
4. Check from a clean directory:
|
|
37
|
+
```
|
|
38
|
+
python -m venv t && t/bin/python -m pip install "spillgate[brotli,zstd]==0.1.0"
|
|
39
|
+
```
|
|
40
|
+
5. Create the GitHub release from the tag with the changelog text.
|
|
41
|
+
|
|
42
|
+
## Never
|
|
43
|
+
|
|
44
|
+
Never delete or move a published tag, and never re-upload a version: PyPI refuses it. A wrong
|
|
45
|
+
release is yanked on PyPI and fixed with the next patch version. Versions at or above 1.0 need
|
|
46
|
+
separate, explicit consent.
|