pybase64 1.4.2__tar.gz → 1.5.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.
- {pybase64-1.4.2 → pybase64-1.5.0}/LICENSE +1 -1
- {pybase64-1.4.2/src/pybase64.egg-info → pybase64-1.5.0}/PKG-INFO +90 -43
- {pybase64-1.4.2 → pybase64-1.5.0}/README.rst +82 -25
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/.github/workflows/test.yml +49 -24
- pybase64-1.5.0/pyproject.toml +229 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/setup.py +10 -75
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/__init__.py +17 -13
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/__main__.py +120 -94
- pybase64-1.5.0/src/pybase64/_fallback.py +399 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_license.py +1 -1
- pybase64-1.5.0/src/pybase64/_pybase64.c +1678 -0
- pybase64-1.5.0/src/pybase64/_pybase64.pyi +43 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_pybase64_get_simd_flags.c +13 -19
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_pybase64_get_simd_flags.h +0 -2
- pybase64-1.5.0/src/pybase64/_typing.py +44 -0
- pybase64-1.5.0/src/pybase64/_unspecified.py +8 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_version.py +1 -1
- {pybase64-1.4.2 → pybase64-1.5.0/src/pybase64.egg-info}/PKG-INFO +90 -43
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/SOURCES.txt +2 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/tests/test_main.py +14 -6
- pybase64-1.5.0/tests/test_packaging.py +49 -0
- pybase64-1.5.0/tests/test_pybase64.py +1069 -0
- pybase64-1.4.2/pyproject.toml +0 -107
- pybase64-1.4.2/src/pybase64/_fallback.py +0 -167
- pybase64-1.4.2/src/pybase64/_pybase64.c +0 -1016
- pybase64-1.4.2/src/pybase64/_pybase64.pyi +0 -16
- pybase64-1.4.2/src/pybase64/_typing.py +0 -35
- pybase64-1.4.2/tests/test_pybase64.py +0 -481
- {pybase64-1.4.2 → pybase64-1.5.0}/MANIFEST.in +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/CMakeLists.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/LICENSE +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/Makefile +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/README.md +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/base64-benchmarks.png +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.manifest +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.rc +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/Modules/TargetArch.cmake +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/Modules/TargetSIMDInstructionSet.cmake +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/base64-config.cmake.in +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/config.h.in +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/test-arch.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/include/libbase64.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx/enc_loop_asm.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/dec_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/dec_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_loop_asm.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_translate.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/enc_reshuffle_translate.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/32/dec_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/32/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/64/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/dec_head.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/dec_tail.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/enc_head.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/enc_tail.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/dec_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_translate.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/dec_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_loop_asm.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/sse41/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/sse42/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/codec.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/dec_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/dec_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_loop.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_loop_asm.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_reshuffle.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_translate.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/codec_choose.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/codecs.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/env.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/exports.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/lib.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/lib_openmp.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/Makefile +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_dec_32bit.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_enc_12bit.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_enc_12bit.py +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_generator.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/tables.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/tables.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/CMakeLists.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/Makefile +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/benchmark.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/analysis.sh +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/checksums.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/test.sh +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci//360/237/230/265/342/200/215/360/237/222/253.bin" +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/codec_supported.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/codec_supported.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick.h +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick_base64.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick_plain.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/test_base64.c +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/setup.cfg +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_license.pyi +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/py.typed +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/dependency_links.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/entry_points.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/top_level.txt +0 -0
- {pybase64-1.4.2 → pybase64-1.5.0}/tests/test_benchmark.py +0 -0
|
@@ -1,42 +1,32 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pybase64
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
4
4
|
Summary: Fast Base64 encoding/decoding
|
|
5
|
-
Home-page: https://github.com/mayeut/pybase64
|
|
6
5
|
Author: Matthieu Darbois
|
|
7
|
-
License: BSD-2-Clause
|
|
8
|
-
Project-URL:
|
|
9
|
-
Project-URL: Tracker, https://github.com/mayeut/pybase64/issues
|
|
6
|
+
License-Expression: BSD-2-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/mayeut/pybase64
|
|
10
8
|
Project-URL: Documentation, https://pybase64.readthedocs.io/en/stable
|
|
9
|
+
Project-URL: Source, https://github.com/mayeut/pybase64
|
|
10
|
+
Project-URL: Issues, https://github.com/mayeut/pybase64/issues
|
|
11
11
|
Keywords: base64
|
|
12
12
|
Classifier: Development Status :: 5 - Production/Stable
|
|
13
13
|
Classifier: Intended Audience :: Developers
|
|
14
14
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
15
|
Classifier: Topic :: Utilities
|
|
16
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
17
16
|
Classifier: Programming Language :: C
|
|
18
17
|
Classifier: Programming Language :: Python :: 3
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.9
|
|
21
19
|
Classifier: Programming Language :: Python :: 3.10
|
|
22
20
|
Classifier: Programming Language :: Python :: 3.11
|
|
23
21
|
Classifier: Programming Language :: Python :: 3.12
|
|
24
22
|
Classifier: Programming Language :: Python :: 3.13
|
|
25
23
|
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
-
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
25
|
+
Requires-Python: >=3.9
|
|
27
26
|
Description-Content-Type: text/x-rst
|
|
28
27
|
License-File: LICENSE
|
|
29
|
-
|
|
30
|
-
Dynamic: classifier
|
|
31
|
-
Dynamic: description
|
|
32
|
-
Dynamic: description-content-type
|
|
33
|
-
Dynamic: home-page
|
|
34
|
-
Dynamic: keywords
|
|
35
|
-
Dynamic: license
|
|
28
|
+
License-File: base64/LICENSE
|
|
36
29
|
Dynamic: license-file
|
|
37
|
-
Dynamic: project-url
|
|
38
|
-
Dynamic: requires-python
|
|
39
|
-
Dynamic: summary
|
|
40
30
|
|
|
41
31
|
.. SETUP VARIABLES
|
|
42
32
|
.. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg
|
|
@@ -74,7 +64,7 @@ Usage
|
|
|
74
64
|
|
|
75
65
|
``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
|
|
76
66
|
|
|
77
|
-
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode``
|
|
67
|
+
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` with ``validate=True`` (or ``ignorechars=b""``) and ``padded=True`` when possible.
|
|
78
68
|
|
|
79
69
|
.. code:: python
|
|
80
70
|
|
|
@@ -127,33 +117,66 @@ Benchmark
|
|
|
127
117
|
|
|
128
118
|
.. begin benchmark
|
|
129
119
|
|
|
130
|
-
Running Python 3.
|
|
120
|
+
Running Python 3.15.0rc1, Apple clang version 21.0.0 (clang-2100.1.1.101), macOS 26.5.2, Apple M1 Max
|
|
131
121
|
|
|
132
122
|
.. code::
|
|
133
123
|
|
|
134
|
-
pybase64
|
|
135
|
-
bench: altchars=None, validate=
|
|
136
|
-
pybase64.
|
|
137
|
-
pybase64.
|
|
138
|
-
pybase64.
|
|
139
|
-
base64.encodebytes:
|
|
140
|
-
base64.b64encode:
|
|
141
|
-
base64.b64decode:
|
|
142
|
-
bench: altchars=None, validate=True
|
|
143
|
-
pybase64.
|
|
144
|
-
pybase64.
|
|
145
|
-
base64.b64encode:
|
|
146
|
-
base64.b64decode:
|
|
147
|
-
bench: altchars=b'
|
|
148
|
-
pybase64.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
pybase64.
|
|
155
|
-
base64.
|
|
156
|
-
|
|
124
|
+
pybase64 1.5.0 (C extension active - NEON)
|
|
125
|
+
bench: altchars=None, validate=True, padded=True
|
|
126
|
+
pybase64.encodebytes: 6595 MB/s (135,696 bytes -> 183,309 bytes)
|
|
127
|
+
pybase64.b64encode: 17492 MB/s (135,696 bytes -> 180,928 bytes)
|
|
128
|
+
pybase64.b64decode: 9037 MB/s (180,928 bytes -> 135,696 bytes)
|
|
129
|
+
base64.encodebytes: 2386 MB/s (135,696 bytes -> 183,309 bytes)
|
|
130
|
+
base64.b64encode: 2653 MB/s (135,696 bytes -> 180,928 bytes)
|
|
131
|
+
base64.b64decode: 2656 MB/s (180,928 bytes -> 135,696 bytes)
|
|
132
|
+
bench: altchars=None, validate=True, padded=False
|
|
133
|
+
pybase64.b64encode: 17547 MB/s (135,696 bytes -> 180,928 bytes)
|
|
134
|
+
pybase64.b64decode: 2521 MB/s (180,928 bytes -> 135,696 bytes)
|
|
135
|
+
base64.b64encode: 2656 MB/s (135,696 bytes -> 180,928 bytes)
|
|
136
|
+
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
|
|
137
|
+
bench: altchars=None, ignorechars=b'', padded=False
|
|
138
|
+
pybase64.b64decode: 2510 MB/s (180,928 bytes -> 135,696 bytes)
|
|
139
|
+
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
|
|
140
|
+
bench: altchars=None, ignorechars=b'\n', padded=True
|
|
141
|
+
pybase64.b64decode: 2370 MB/s (183,308 bytes -> 135,696 bytes)
|
|
142
|
+
base64.b64decode: 2087 MB/s (183,308 bytes -> 135,696 bytes)
|
|
143
|
+
bench: altchars=None, ignorechars=b'\n', padded=False
|
|
144
|
+
pybase64.b64decode: 2365 MB/s (183,308 bytes -> 135,696 bytes)
|
|
145
|
+
base64.b64decode: 1964 MB/s (183,308 bytes -> 135,696 bytes)
|
|
146
|
+
bench: altchars=None, validate=False, padded=True
|
|
147
|
+
pybase64.b64decode: 2369 MB/s (183,308 bytes -> 135,696 bytes)
|
|
148
|
+
base64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
|
|
149
|
+
bench: altchars=None, validate=False, padded=False
|
|
150
|
+
pybase64.b64decode: 2361 MB/s (183,308 bytes -> 135,696 bytes)
|
|
151
|
+
base64.b64decode: 1982 MB/s (183,308 bytes -> 135,696 bytes)
|
|
152
|
+
bench: altchars=b'-_', validate=True, padded=True
|
|
153
|
+
pybase64.b64encode: 10900 MB/s (135,696 bytes -> 180,928 bytes)
|
|
154
|
+
pybase64.b64decode: 5974 MB/s (180,928 bytes -> 135,696 bytes)
|
|
155
|
+
base64.b64encode: 2675 MB/s (135,696 bytes -> 180,928 bytes)
|
|
156
|
+
base64.b64decode: 1186 MB/s (180,928 bytes -> 135,696 bytes)
|
|
157
|
+
bench: altchars=b'-_', validate=True, padded=False
|
|
158
|
+
pybase64.b64encode: 10798 MB/s (135,696 bytes -> 180,928 bytes)
|
|
159
|
+
pybase64.b64decode: 2135 MB/s (180,928 bytes -> 135,696 bytes)
|
|
160
|
+
base64.b64encode: 2571 MB/s (135,696 bytes -> 180,928 bytes)
|
|
161
|
+
base64.b64decode: 1154 MB/s (180,928 bytes -> 135,696 bytes)
|
|
162
|
+
bench: altchars=b'-_', ignorechars=b'', padded=True
|
|
163
|
+
pybase64.b64decode: 5770 MB/s (180,928 bytes -> 135,696 bytes)
|
|
164
|
+
base64.b64decode: 2629 MB/s (180,928 bytes -> 135,696 bytes)
|
|
165
|
+
bench: altchars=b'-_', ignorechars=b'', padded=False
|
|
166
|
+
pybase64.b64decode: 2201 MB/s (180,928 bytes -> 135,696 bytes)
|
|
167
|
+
base64.b64decode: 2606 MB/s (180,928 bytes -> 135,696 bytes)
|
|
168
|
+
bench: altchars=b'-_', ignorechars=b'\n', padded=True
|
|
169
|
+
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
|
|
170
|
+
base64.b64decode: 2069 MB/s (183,308 bytes -> 135,696 bytes)
|
|
171
|
+
bench: altchars=b'-_', ignorechars=b'\n', padded=False
|
|
172
|
+
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
|
|
173
|
+
base64.b64decode: 1882 MB/s (183,308 bytes -> 135,696 bytes)
|
|
174
|
+
bench: altchars=b'-_', validate=False, padded=True
|
|
175
|
+
pybase64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
|
|
176
|
+
base64.b64decode: 1005 MB/s (183,308 bytes -> 135,696 bytes)
|
|
177
|
+
bench: altchars=b'-_', validate=False, padded=False
|
|
178
|
+
pybase64.b64decode: 2081 MB/s (183,308 bytes -> 135,696 bytes)
|
|
179
|
+
base64.b64decode: 1031 MB/s (183,308 bytes -> 135,696 bytes)
|
|
157
180
|
|
|
158
181
|
.. end benchmark
|
|
159
182
|
|
|
@@ -161,6 +184,30 @@ Running Python 3.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 1
|
|
|
161
184
|
|
|
162
185
|
Changelog
|
|
163
186
|
=========
|
|
187
|
+
1.5.0
|
|
188
|
+
------
|
|
189
|
+
- Speed-up translation on aarch64
|
|
190
|
+
- Fix invalid data successfully decoded when using altchars (slice ends with padding)
|
|
191
|
+
- Fix thread safety selecting codec
|
|
192
|
+
- Add ``padded`` and ``wrapcol`` parameters to ``b64encode``
|
|
193
|
+
- Add ``padded`` parameter to ``urlsafe_b64encode``
|
|
194
|
+
- Add ``padded`` parameter to ``b64decode`` & ``urlsafe_b64decode``
|
|
195
|
+
- ``urlsafe_b64decode`` now defaults to ``padded=False`` to align with Python 3.15 behavior
|
|
196
|
+
- Add ``ignorechars`` and ``canonical`` parameters to ``b64decode``
|
|
197
|
+
- Handle excess padding with the same behavior as CPython 3.15
|
|
198
|
+
- Reject non-ASCII strings in ``b64decode`` when ``validate=False``
|
|
199
|
+
- Deprecate accepting the ``+`` and ``/`` characters with an alternative alphabet when decoding
|
|
200
|
+
- Use ``ValueError`` instead of ``AssertionError`` on altchars length validation
|
|
201
|
+
- Add SBOM to PyPI wheels
|
|
202
|
+
- Publish python 3.15 wheels
|
|
203
|
+
- Drop python 3.8 support
|
|
204
|
+
- Stop publishing python 3.13t wheels
|
|
205
|
+
|
|
206
|
+
1.4.3
|
|
207
|
+
-----
|
|
208
|
+
- Publish Android Python 3.14 wheels
|
|
209
|
+
- Publish GraalPy v25 wheels
|
|
210
|
+
|
|
164
211
|
1.4.2
|
|
165
212
|
-----
|
|
166
213
|
- Update base64 library (Windows ARM64 Neon support)
|
|
@@ -34,7 +34,7 @@ Usage
|
|
|
34
34
|
|
|
35
35
|
``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
|
|
36
36
|
|
|
37
|
-
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode``
|
|
37
|
+
To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` with ``validate=True`` (or ``ignorechars=b""``) and ``padded=True`` when possible.
|
|
38
38
|
|
|
39
39
|
.. code:: python
|
|
40
40
|
|
|
@@ -87,33 +87,66 @@ Benchmark
|
|
|
87
87
|
|
|
88
88
|
.. begin benchmark
|
|
89
89
|
|
|
90
|
-
Running Python 3.
|
|
90
|
+
Running Python 3.15.0rc1, Apple clang version 21.0.0 (clang-2100.1.1.101), macOS 26.5.2, Apple M1 Max
|
|
91
91
|
|
|
92
92
|
.. code::
|
|
93
93
|
|
|
94
|
-
pybase64
|
|
95
|
-
bench: altchars=None, validate=
|
|
96
|
-
pybase64.
|
|
97
|
-
pybase64.
|
|
98
|
-
pybase64.
|
|
99
|
-
base64.encodebytes:
|
|
100
|
-
base64.b64encode:
|
|
101
|
-
base64.b64decode:
|
|
102
|
-
bench: altchars=None, validate=True
|
|
103
|
-
pybase64.
|
|
104
|
-
pybase64.
|
|
105
|
-
base64.b64encode:
|
|
106
|
-
base64.b64decode:
|
|
107
|
-
bench: altchars=b'
|
|
108
|
-
pybase64.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
pybase64.
|
|
115
|
-
base64.
|
|
116
|
-
|
|
94
|
+
pybase64 1.5.0 (C extension active - NEON)
|
|
95
|
+
bench: altchars=None, validate=True, padded=True
|
|
96
|
+
pybase64.encodebytes: 6595 MB/s (135,696 bytes -> 183,309 bytes)
|
|
97
|
+
pybase64.b64encode: 17492 MB/s (135,696 bytes -> 180,928 bytes)
|
|
98
|
+
pybase64.b64decode: 9037 MB/s (180,928 bytes -> 135,696 bytes)
|
|
99
|
+
base64.encodebytes: 2386 MB/s (135,696 bytes -> 183,309 bytes)
|
|
100
|
+
base64.b64encode: 2653 MB/s (135,696 bytes -> 180,928 bytes)
|
|
101
|
+
base64.b64decode: 2656 MB/s (180,928 bytes -> 135,696 bytes)
|
|
102
|
+
bench: altchars=None, validate=True, padded=False
|
|
103
|
+
pybase64.b64encode: 17547 MB/s (135,696 bytes -> 180,928 bytes)
|
|
104
|
+
pybase64.b64decode: 2521 MB/s (180,928 bytes -> 135,696 bytes)
|
|
105
|
+
base64.b64encode: 2656 MB/s (135,696 bytes -> 180,928 bytes)
|
|
106
|
+
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
|
|
107
|
+
bench: altchars=None, ignorechars=b'', padded=False
|
|
108
|
+
pybase64.b64decode: 2510 MB/s (180,928 bytes -> 135,696 bytes)
|
|
109
|
+
base64.b64decode: 2655 MB/s (180,928 bytes -> 135,696 bytes)
|
|
110
|
+
bench: altchars=None, ignorechars=b'\n', padded=True
|
|
111
|
+
pybase64.b64decode: 2370 MB/s (183,308 bytes -> 135,696 bytes)
|
|
112
|
+
base64.b64decode: 2087 MB/s (183,308 bytes -> 135,696 bytes)
|
|
113
|
+
bench: altchars=None, ignorechars=b'\n', padded=False
|
|
114
|
+
pybase64.b64decode: 2365 MB/s (183,308 bytes -> 135,696 bytes)
|
|
115
|
+
base64.b64decode: 1964 MB/s (183,308 bytes -> 135,696 bytes)
|
|
116
|
+
bench: altchars=None, validate=False, padded=True
|
|
117
|
+
pybase64.b64decode: 2369 MB/s (183,308 bytes -> 135,696 bytes)
|
|
118
|
+
base64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
|
|
119
|
+
bench: altchars=None, validate=False, padded=False
|
|
120
|
+
pybase64.b64decode: 2361 MB/s (183,308 bytes -> 135,696 bytes)
|
|
121
|
+
base64.b64decode: 1982 MB/s (183,308 bytes -> 135,696 bytes)
|
|
122
|
+
bench: altchars=b'-_', validate=True, padded=True
|
|
123
|
+
pybase64.b64encode: 10900 MB/s (135,696 bytes -> 180,928 bytes)
|
|
124
|
+
pybase64.b64decode: 5974 MB/s (180,928 bytes -> 135,696 bytes)
|
|
125
|
+
base64.b64encode: 2675 MB/s (135,696 bytes -> 180,928 bytes)
|
|
126
|
+
base64.b64decode: 1186 MB/s (180,928 bytes -> 135,696 bytes)
|
|
127
|
+
bench: altchars=b'-_', validate=True, padded=False
|
|
128
|
+
pybase64.b64encode: 10798 MB/s (135,696 bytes -> 180,928 bytes)
|
|
129
|
+
pybase64.b64decode: 2135 MB/s (180,928 bytes -> 135,696 bytes)
|
|
130
|
+
base64.b64encode: 2571 MB/s (135,696 bytes -> 180,928 bytes)
|
|
131
|
+
base64.b64decode: 1154 MB/s (180,928 bytes -> 135,696 bytes)
|
|
132
|
+
bench: altchars=b'-_', ignorechars=b'', padded=True
|
|
133
|
+
pybase64.b64decode: 5770 MB/s (180,928 bytes -> 135,696 bytes)
|
|
134
|
+
base64.b64decode: 2629 MB/s (180,928 bytes -> 135,696 bytes)
|
|
135
|
+
bench: altchars=b'-_', ignorechars=b'', padded=False
|
|
136
|
+
pybase64.b64decode: 2201 MB/s (180,928 bytes -> 135,696 bytes)
|
|
137
|
+
base64.b64decode: 2606 MB/s (180,928 bytes -> 135,696 bytes)
|
|
138
|
+
bench: altchars=b'-_', ignorechars=b'\n', padded=True
|
|
139
|
+
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
|
|
140
|
+
base64.b64decode: 2069 MB/s (183,308 bytes -> 135,696 bytes)
|
|
141
|
+
bench: altchars=b'-_', ignorechars=b'\n', padded=False
|
|
142
|
+
pybase64.b64decode: 2058 MB/s (183,308 bytes -> 135,696 bytes)
|
|
143
|
+
base64.b64decode: 1882 MB/s (183,308 bytes -> 135,696 bytes)
|
|
144
|
+
bench: altchars=b'-_', validate=False, padded=True
|
|
145
|
+
pybase64.b64decode: 2030 MB/s (183,308 bytes -> 135,696 bytes)
|
|
146
|
+
base64.b64decode: 1005 MB/s (183,308 bytes -> 135,696 bytes)
|
|
147
|
+
bench: altchars=b'-_', validate=False, padded=False
|
|
148
|
+
pybase64.b64decode: 2081 MB/s (183,308 bytes -> 135,696 bytes)
|
|
149
|
+
base64.b64decode: 1031 MB/s (183,308 bytes -> 135,696 bytes)
|
|
117
150
|
|
|
118
151
|
.. end benchmark
|
|
119
152
|
|
|
@@ -121,6 +154,30 @@ Running Python 3.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 1
|
|
|
121
154
|
|
|
122
155
|
Changelog
|
|
123
156
|
=========
|
|
157
|
+
1.5.0
|
|
158
|
+
------
|
|
159
|
+
- Speed-up translation on aarch64
|
|
160
|
+
- Fix invalid data successfully decoded when using altchars (slice ends with padding)
|
|
161
|
+
- Fix thread safety selecting codec
|
|
162
|
+
- Add ``padded`` and ``wrapcol`` parameters to ``b64encode``
|
|
163
|
+
- Add ``padded`` parameter to ``urlsafe_b64encode``
|
|
164
|
+
- Add ``padded`` parameter to ``b64decode`` & ``urlsafe_b64decode``
|
|
165
|
+
- ``urlsafe_b64decode`` now defaults to ``padded=False`` to align with Python 3.15 behavior
|
|
166
|
+
- Add ``ignorechars`` and ``canonical`` parameters to ``b64decode``
|
|
167
|
+
- Handle excess padding with the same behavior as CPython 3.15
|
|
168
|
+
- Reject non-ASCII strings in ``b64decode`` when ``validate=False``
|
|
169
|
+
- Deprecate accepting the ``+`` and ``/`` characters with an alternative alphabet when decoding
|
|
170
|
+
- Use ``ValueError`` instead of ``AssertionError`` on altchars length validation
|
|
171
|
+
- Add SBOM to PyPI wheels
|
|
172
|
+
- Publish python 3.15 wheels
|
|
173
|
+
- Drop python 3.8 support
|
|
174
|
+
- Stop publishing python 3.13t wheels
|
|
175
|
+
|
|
176
|
+
1.4.3
|
|
177
|
+
-----
|
|
178
|
+
- Publish Android Python 3.14 wheels
|
|
179
|
+
- Publish GraalPy v25 wheels
|
|
180
|
+
|
|
124
181
|
1.4.2
|
|
125
182
|
-----
|
|
126
183
|
- Update base64 library (Windows ARM64 Neon support)
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
name: Test
|
|
2
2
|
|
|
3
|
-
on: [push, pull_request]
|
|
3
|
+
on: [push, pull_request, workflow_dispatch]
|
|
4
|
+
|
|
5
|
+
concurrency:
|
|
6
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
7
|
+
cancel-in-progress: true
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
4
11
|
|
|
5
12
|
jobs:
|
|
6
13
|
makefile-analysis:
|
|
@@ -8,7 +15,9 @@ jobs:
|
|
|
8
15
|
runs-on: ubuntu-24.04
|
|
9
16
|
steps:
|
|
10
17
|
- name: Checkout
|
|
11
|
-
uses: actions/checkout@
|
|
18
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
19
|
+
with:
|
|
20
|
+
persist-credentials: false
|
|
12
21
|
- name: "Install analysis tools"
|
|
13
22
|
run: |
|
|
14
23
|
sudo apt-get update
|
|
@@ -23,11 +32,11 @@ jobs:
|
|
|
23
32
|
strategy:
|
|
24
33
|
fail-fast: false
|
|
25
34
|
matrix:
|
|
26
|
-
runner: ["ubuntu-
|
|
35
|
+
runner: ["ubuntu-24.04"]
|
|
27
36
|
compiler: ["gcc", "clang"]
|
|
28
37
|
openmp: ["0", "1"]
|
|
29
38
|
include:
|
|
30
|
-
- runner: "macos-
|
|
39
|
+
- runner: "macos-15-intel"
|
|
31
40
|
compiler: "clang"
|
|
32
41
|
openmp: "0"
|
|
33
42
|
env:
|
|
@@ -37,7 +46,9 @@ jobs:
|
|
|
37
46
|
OBJCOPY: ${{ (startsWith(matrix.runner, 'macos') && 'echo') || 'objcopy' }}
|
|
38
47
|
steps:
|
|
39
48
|
- name: Checkout
|
|
40
|
-
uses: actions/checkout@
|
|
49
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
50
|
+
with:
|
|
51
|
+
persist-credentials: false
|
|
41
52
|
- name: Install Ubuntu libomp support
|
|
42
53
|
if: runner.os == 'Linux' && matrix.compiler == 'clang' && matrix.openmp == 1
|
|
43
54
|
run: |
|
|
@@ -53,20 +64,22 @@ jobs:
|
|
|
53
64
|
strategy:
|
|
54
65
|
fail-fast: false
|
|
55
66
|
matrix:
|
|
56
|
-
runner: ["ubuntu-
|
|
67
|
+
runner: ["ubuntu-24.04", "windows-2022"]
|
|
57
68
|
platform: ["x86_64", "i686"]
|
|
58
69
|
include:
|
|
59
|
-
- runner: "macos-
|
|
70
|
+
- runner: "macos-15-intel"
|
|
60
71
|
platform: "x86_64"
|
|
61
|
-
- runner: "macos-
|
|
72
|
+
- runner: "macos-15"
|
|
62
73
|
platform: "arm64"
|
|
63
|
-
- runner: "ubuntu-
|
|
74
|
+
- runner: "ubuntu-24.04-arm"
|
|
64
75
|
platform: "aarch64"
|
|
65
76
|
- runner: "windows-11-arm"
|
|
66
77
|
platform: "ARM64"
|
|
67
78
|
steps:
|
|
68
79
|
- name: Checkout
|
|
69
|
-
uses: actions/checkout@
|
|
80
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
81
|
+
with:
|
|
82
|
+
persist-credentials: false
|
|
70
83
|
- name: Install Ubuntu i686 support
|
|
71
84
|
if: runner.os == 'Linux' && matrix.platform == 'i686'
|
|
72
85
|
run: |
|
|
@@ -94,14 +107,16 @@ jobs:
|
|
|
94
107
|
needs: makefile-analysis
|
|
95
108
|
runs-on: ubuntu-latest
|
|
96
109
|
container:
|
|
97
|
-
image: alpine:3.
|
|
110
|
+
image: alpine:3.21
|
|
98
111
|
env:
|
|
99
112
|
CC: gcc
|
|
100
113
|
steps:
|
|
101
114
|
- name: Install deps
|
|
102
115
|
run: apk add --update bash build-base git
|
|
103
116
|
- name: Checkout
|
|
104
|
-
uses: actions/checkout@
|
|
117
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
118
|
+
with:
|
|
119
|
+
persist-credentials: false
|
|
105
120
|
- name: Run tests
|
|
106
121
|
run: ./test/ci/test.sh
|
|
107
122
|
|
|
@@ -110,12 +125,14 @@ jobs:
|
|
|
110
125
|
needs: makefile-analysis
|
|
111
126
|
runs-on: ubuntu-latest
|
|
112
127
|
container:
|
|
113
|
-
image: alpine:3.
|
|
128
|
+
image: alpine:3.21
|
|
114
129
|
steps:
|
|
115
130
|
- name: Install deps
|
|
116
131
|
run: apk add --update bash build-base cmake git
|
|
117
132
|
- name: Checkout
|
|
118
|
-
uses: actions/checkout@
|
|
133
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
134
|
+
with:
|
|
135
|
+
persist-credentials: false
|
|
119
136
|
- name: CMake Configure
|
|
120
137
|
run: >
|
|
121
138
|
cmake
|
|
@@ -138,12 +155,14 @@ jobs:
|
|
|
138
155
|
strategy:
|
|
139
156
|
fail-fast: false
|
|
140
157
|
matrix:
|
|
141
|
-
arch: [armv7, aarch64, s390x, ppc64le]
|
|
158
|
+
arch: [armv7, aarch64, s390x, ppc64le, riscv64]
|
|
142
159
|
cc: [gcc, clang]
|
|
143
160
|
steps:
|
|
144
161
|
- name: Checkout
|
|
145
|
-
uses: actions/checkout@
|
|
146
|
-
|
|
162
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
163
|
+
with:
|
|
164
|
+
persist-credentials: false
|
|
165
|
+
- uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0
|
|
147
166
|
with:
|
|
148
167
|
arch: ${{matrix.arch}}
|
|
149
168
|
distro: alpine_latest
|
|
@@ -159,12 +178,14 @@ jobs:
|
|
|
159
178
|
strategy:
|
|
160
179
|
fail-fast: false
|
|
161
180
|
matrix:
|
|
162
|
-
arch: [armv7, aarch64, s390x, ppc64le]
|
|
181
|
+
arch: [armv7, aarch64, s390x, ppc64le, riscv64]
|
|
163
182
|
cc: [gcc, clang]
|
|
164
183
|
steps:
|
|
165
184
|
- name: Checkout
|
|
166
|
-
uses: actions/checkout@
|
|
167
|
-
|
|
185
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
186
|
+
with:
|
|
187
|
+
persist-credentials: false
|
|
188
|
+
- uses: uraimo/run-on-arch-action@f9b26e3a1a408d5fd530d20c17b9f3f4428ff8d9 # v3.1.0
|
|
168
189
|
with:
|
|
169
190
|
arch: ${{matrix.arch}}
|
|
170
191
|
distro: alpine_latest
|
|
@@ -198,9 +219,11 @@ jobs:
|
|
|
198
219
|
|
|
199
220
|
steps:
|
|
200
221
|
- name: Checkout
|
|
201
|
-
uses: actions/checkout@
|
|
222
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
223
|
+
with:
|
|
224
|
+
persist-credentials: false
|
|
202
225
|
- name: Setup MSYS2 ${{matrix.msystem}}
|
|
203
|
-
uses: msys2/setup-msys2@v2
|
|
226
|
+
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
|
204
227
|
with:
|
|
205
228
|
msystem: ${{matrix.msystem}}
|
|
206
229
|
update: true
|
|
@@ -250,9 +273,11 @@ jobs:
|
|
|
250
273
|
CC: cc.exe
|
|
251
274
|
steps:
|
|
252
275
|
- name: Checkout
|
|
253
|
-
uses: actions/checkout@
|
|
276
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
277
|
+
with:
|
|
278
|
+
persist-credentials: false
|
|
254
279
|
- name: Setup MSYS2 ${{matrix.msystem}}
|
|
255
|
-
uses: msys2/setup-msys2@v2
|
|
280
|
+
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
|
|
256
281
|
with:
|
|
257
282
|
msystem: ${{matrix.msystem}}
|
|
258
283
|
update: true
|