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.
Files changed (115) hide show
  1. {pybase64-1.4.2 → pybase64-1.5.0}/LICENSE +1 -1
  2. {pybase64-1.4.2/src/pybase64.egg-info → pybase64-1.5.0}/PKG-INFO +90 -43
  3. {pybase64-1.4.2 → pybase64-1.5.0}/README.rst +82 -25
  4. {pybase64-1.4.2 → pybase64-1.5.0}/base64/.github/workflows/test.yml +49 -24
  5. pybase64-1.5.0/pyproject.toml +229 -0
  6. {pybase64-1.4.2 → pybase64-1.5.0}/setup.py +10 -75
  7. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/__init__.py +17 -13
  8. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/__main__.py +120 -94
  9. pybase64-1.5.0/src/pybase64/_fallback.py +399 -0
  10. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_license.py +1 -1
  11. pybase64-1.5.0/src/pybase64/_pybase64.c +1678 -0
  12. pybase64-1.5.0/src/pybase64/_pybase64.pyi +43 -0
  13. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_pybase64_get_simd_flags.c +13 -19
  14. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_pybase64_get_simd_flags.h +0 -2
  15. pybase64-1.5.0/src/pybase64/_typing.py +44 -0
  16. pybase64-1.5.0/src/pybase64/_unspecified.py +8 -0
  17. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_version.py +1 -1
  18. {pybase64-1.4.2 → pybase64-1.5.0/src/pybase64.egg-info}/PKG-INFO +90 -43
  19. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/SOURCES.txt +2 -0
  20. {pybase64-1.4.2 → pybase64-1.5.0}/tests/test_main.py +14 -6
  21. pybase64-1.5.0/tests/test_packaging.py +49 -0
  22. pybase64-1.5.0/tests/test_pybase64.py +1069 -0
  23. pybase64-1.4.2/pyproject.toml +0 -107
  24. pybase64-1.4.2/src/pybase64/_fallback.py +0 -167
  25. pybase64-1.4.2/src/pybase64/_pybase64.c +0 -1016
  26. pybase64-1.4.2/src/pybase64/_pybase64.pyi +0 -16
  27. pybase64-1.4.2/src/pybase64/_typing.py +0 -35
  28. pybase64-1.4.2/tests/test_pybase64.py +0 -481
  29. {pybase64-1.4.2 → pybase64-1.5.0}/MANIFEST.in +0 -0
  30. {pybase64-1.4.2 → pybase64-1.5.0}/base64/CMakeLists.txt +0 -0
  31. {pybase64-1.4.2 → pybase64-1.5.0}/base64/LICENSE +0 -0
  32. {pybase64-1.4.2 → pybase64-1.5.0}/base64/Makefile +0 -0
  33. {pybase64-1.4.2 → pybase64-1.5.0}/base64/README.md +0 -0
  34. {pybase64-1.4.2 → pybase64-1.5.0}/base64/base64-benchmarks.png +0 -0
  35. {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.c +0 -0
  36. {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.manifest +0 -0
  37. {pybase64-1.4.2 → pybase64-1.5.0}/base64/bin/base64.rc +0 -0
  38. {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/Modules/TargetArch.cmake +0 -0
  39. {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/Modules/TargetSIMDInstructionSet.cmake +0 -0
  40. {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/base64-config.cmake.in +0 -0
  41. {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/config.h.in +0 -0
  42. {pybase64-1.4.2 → pybase64-1.5.0}/base64/cmake/test-arch.c +0 -0
  43. {pybase64-1.4.2 → pybase64-1.5.0}/base64/include/libbase64.h +0 -0
  44. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx/codec.c +0 -0
  45. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx/enc_loop_asm.c +0 -0
  46. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/codec.c +0 -0
  47. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/dec_loop.c +0 -0
  48. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/dec_reshuffle.c +0 -0
  49. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_loop.c +0 -0
  50. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_loop_asm.c +0 -0
  51. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_reshuffle.c +0 -0
  52. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx2/enc_translate.c +0 -0
  53. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/codec.c +0 -0
  54. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/enc_loop.c +0 -0
  55. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/avx512/enc_reshuffle_translate.c +0 -0
  56. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/32/dec_loop.c +0 -0
  57. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/32/enc_loop.c +0 -0
  58. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/64/enc_loop.c +0 -0
  59. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/codec.c +0 -0
  60. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/dec_head.c +0 -0
  61. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/dec_tail.c +0 -0
  62. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/enc_head.c +0 -0
  63. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/generic/enc_tail.c +0 -0
  64. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/codec.c +0 -0
  65. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/dec_loop.c +0 -0
  66. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_loop.c +0 -0
  67. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_reshuffle.c +0 -0
  68. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon32/enc_translate.c +0 -0
  69. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/codec.c +0 -0
  70. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/dec_loop.c +0 -0
  71. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_loop.c +0 -0
  72. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_loop_asm.c +0 -0
  73. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/neon64/enc_reshuffle.c +0 -0
  74. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/sse41/codec.c +0 -0
  75. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/sse42/codec.c +0 -0
  76. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/codec.c +0 -0
  77. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/dec_loop.c +0 -0
  78. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/dec_reshuffle.c +0 -0
  79. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_loop.c +0 -0
  80. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_loop_asm.c +0 -0
  81. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_reshuffle.c +0 -0
  82. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/arch/ssse3/enc_translate.c +0 -0
  83. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/codec_choose.c +0 -0
  84. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/codecs.h +0 -0
  85. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/env.h +0 -0
  86. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/exports.txt +0 -0
  87. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/lib.c +0 -0
  88. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/lib_openmp.c +0 -0
  89. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/Makefile +0 -0
  90. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_dec_32bit.h +0 -0
  91. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_enc_12bit.h +0 -0
  92. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_enc_12bit.py +0 -0
  93. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/table_generator.c +0 -0
  94. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/tables.c +0 -0
  95. {pybase64-1.4.2 → pybase64-1.5.0}/base64/lib/tables/tables.h +0 -0
  96. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/CMakeLists.txt +0 -0
  97. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/Makefile +0 -0
  98. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/benchmark.c +0 -0
  99. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/analysis.sh +0 -0
  100. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/checksums.txt +0 -0
  101. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/ci/test.sh +0 -0
  102. {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
  103. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/codec_supported.c +0 -0
  104. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/codec_supported.h +0 -0
  105. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick.h +0 -0
  106. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick_base64.txt +0 -0
  107. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/moby_dick_plain.txt +0 -0
  108. {pybase64-1.4.2 → pybase64-1.5.0}/base64/test/test_base64.c +0 -0
  109. {pybase64-1.4.2 → pybase64-1.5.0}/setup.cfg +0 -0
  110. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/_license.pyi +0 -0
  111. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64/py.typed +0 -0
  112. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/dependency_links.txt +0 -0
  113. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/entry_points.txt +0 -0
  114. {pybase64-1.4.2 → pybase64-1.5.0}/src/pybase64.egg-info/top_level.txt +0 -0
  115. {pybase64-1.4.2 → pybase64-1.5.0}/tests/test_benchmark.py +0 -0
@@ -1,6 +1,6 @@
1
1
  BSD 2-Clause License
2
2
 
3
- Copyright (c) 2017-2022, Matthieu Darbois
3
+ Copyright (c) 2017-2026, Matthieu Darbois
4
4
  All rights reserved.
5
5
 
6
6
  Redistribution and use in source and binary forms, with or without
@@ -1,42 +1,32 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pybase64
3
- Version: 1.4.2
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: Source, https://github.com/mayeut/pybase64
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
- Requires-Python: >=3.8
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
- Dynamic: author
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`` and ``validate=True`` when possible.
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.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 10.14.2 on an Intel Core i7-4870HQ @ 2.50GHz
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 0.5.0 (C extension active - AVX2)
135
- bench: altchars=None, validate=False
136
- pybase64._pybase64.encodebytes: 1734.776 MB/s (13,271,472 bytes -> 17,928,129 bytes)
137
- pybase64._pybase64.b64encode: 4039.539 MB/s (13,271,472 bytes -> 17,695,296 bytes)
138
- pybase64._pybase64.b64decode: 1854.423 MB/s (17,695,296 bytes -> 13,271,472 bytes)
139
- base64.encodebytes: 78.352 MB/s (13,271,472 bytes -> 17,928,129 bytes)
140
- base64.b64encode: 539.840 MB/s (13,271,472 bytes -> 17,695,296 bytes)
141
- base64.b64decode: 287.826 MB/s (17,695,296 bytes -> 13,271,472 bytes)
142
- bench: altchars=None, validate=True
143
- pybase64._pybase64.b64encode: 4156.607 MB/s (13,271,472 bytes -> 17,695,296 bytes)
144
- pybase64._pybase64.b64decode: 4107.997 MB/s (17,695,296 bytes -> 13,271,472 bytes)
145
- base64.b64encode: 559.342 MB/s (13,271,472 bytes -> 17,695,296 bytes)
146
- base64.b64decode: 143.674 MB/s (17,695,296 bytes -> 13,271,472 bytes)
147
- bench: altchars=b'-_', validate=False
148
- pybase64._pybase64.b64encode: 2786.776 MB/s (13,271,472 bytes -> 17,695,296 bytes)
149
- pybase64._pybase64.b64decode: 1124.136 MB/s (17,695,296 bytes -> 13,271,472 bytes)
150
- base64.b64encode: 322.427 MB/s (13,271,472 bytes -> 17,695,296 bytes)
151
- base64.b64decode: 205.195 MB/s (17,695,296 bytes -> 13,271,472 bytes)
152
- bench: altchars=b'-_', validate=True
153
- pybase64._pybase64.b64encode: 2806.271 MB/s (13,271,472 bytes -> 17,695,296 bytes)
154
- pybase64._pybase64.b64decode: 2740.456 MB/s (17,695,296 bytes -> 13,271,472 bytes)
155
- base64.b64encode: 314.709 MB/s (13,271,472 bytes -> 17,695,296 bytes)
156
- base64.b64decode: 121.803 MB/s (17,695,296 bytes -> 13,271,472 bytes)
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`` and ``validate=True`` when possible.
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.7.2, Apple LLVM version 10.0.0 (clang-1000.11.45.5), Mac OS X 10.14.2 on an Intel Core i7-4870HQ @ 2.50GHz
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 0.5.0 (C extension active - AVX2)
95
- bench: altchars=None, validate=False
96
- pybase64._pybase64.encodebytes: 1734.776 MB/s (13,271,472 bytes -> 17,928,129 bytes)
97
- pybase64._pybase64.b64encode: 4039.539 MB/s (13,271,472 bytes -> 17,695,296 bytes)
98
- pybase64._pybase64.b64decode: 1854.423 MB/s (17,695,296 bytes -> 13,271,472 bytes)
99
- base64.encodebytes: 78.352 MB/s (13,271,472 bytes -> 17,928,129 bytes)
100
- base64.b64encode: 539.840 MB/s (13,271,472 bytes -> 17,695,296 bytes)
101
- base64.b64decode: 287.826 MB/s (17,695,296 bytes -> 13,271,472 bytes)
102
- bench: altchars=None, validate=True
103
- pybase64._pybase64.b64encode: 4156.607 MB/s (13,271,472 bytes -> 17,695,296 bytes)
104
- pybase64._pybase64.b64decode: 4107.997 MB/s (17,695,296 bytes -> 13,271,472 bytes)
105
- base64.b64encode: 559.342 MB/s (13,271,472 bytes -> 17,695,296 bytes)
106
- base64.b64decode: 143.674 MB/s (17,695,296 bytes -> 13,271,472 bytes)
107
- bench: altchars=b'-_', validate=False
108
- pybase64._pybase64.b64encode: 2786.776 MB/s (13,271,472 bytes -> 17,695,296 bytes)
109
- pybase64._pybase64.b64decode: 1124.136 MB/s (17,695,296 bytes -> 13,271,472 bytes)
110
- base64.b64encode: 322.427 MB/s (13,271,472 bytes -> 17,695,296 bytes)
111
- base64.b64decode: 205.195 MB/s (17,695,296 bytes -> 13,271,472 bytes)
112
- bench: altchars=b'-_', validate=True
113
- pybase64._pybase64.b64encode: 2806.271 MB/s (13,271,472 bytes -> 17,695,296 bytes)
114
- pybase64._pybase64.b64decode: 2740.456 MB/s (17,695,296 bytes -> 13,271,472 bytes)
115
- base64.b64encode: 314.709 MB/s (13,271,472 bytes -> 17,695,296 bytes)
116
- base64.b64decode: 121.803 MB/s (17,695,296 bytes -> 13,271,472 bytes)
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@v4
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-22.04"]
35
+ runner: ["ubuntu-24.04"]
27
36
  compiler: ["gcc", "clang"]
28
37
  openmp: ["0", "1"]
29
38
  include:
30
- - runner: "macos-13"
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@v4
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-22.04", "windows-2019"]
67
+ runner: ["ubuntu-24.04", "windows-2022"]
57
68
  platform: ["x86_64", "i686"]
58
69
  include:
59
- - runner: "macos-13"
70
+ - runner: "macos-15-intel"
60
71
  platform: "x86_64"
61
- - runner: "macos-14"
72
+ - runner: "macos-15"
62
73
  platform: "arm64"
63
- - runner: "ubuntu-22.04-arm"
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@v4
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.12
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@v4
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.12
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@v4
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@v4
146
- - uses: uraimo/run-on-arch-action@v3
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@v4
167
- - uses: uraimo/run-on-arch-action@v3
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@v4
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@v4
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