pybase64 1.4.2__cp313-cp313-android_21_arm64_v8a.whl

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/__init__.py ADDED
@@ -0,0 +1,124 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from ._license import _license
6
+ from ._version import _version
7
+
8
+ if TYPE_CHECKING:
9
+ from ._typing import Buffer
10
+
11
+ try:
12
+ from ._pybase64 import (
13
+ _get_simd_flags_compile, # noqa: F401
14
+ _get_simd_flags_runtime, # noqa: F401
15
+ _get_simd_name,
16
+ _get_simd_path,
17
+ _set_simd_path, # noqa: F401
18
+ b64decode,
19
+ b64decode_as_bytearray,
20
+ b64encode,
21
+ b64encode_as_string,
22
+ encodebytes,
23
+ )
24
+ except ImportError:
25
+ from ._fallback import (
26
+ _get_simd_name,
27
+ _get_simd_path,
28
+ b64decode,
29
+ b64decode_as_bytearray,
30
+ b64encode,
31
+ b64encode_as_string,
32
+ encodebytes,
33
+ )
34
+
35
+
36
+ __all__ = (
37
+ "b64decode",
38
+ "b64decode_as_bytearray",
39
+ "b64encode",
40
+ "b64encode_as_string",
41
+ "encodebytes",
42
+ "standard_b64decode",
43
+ "standard_b64encode",
44
+ "urlsafe_b64decode",
45
+ "urlsafe_b64encode",
46
+ )
47
+
48
+ __version__ = _version
49
+
50
+
51
+ def get_license_text() -> str:
52
+ """Returns pybase64 license information as a :class:`str` object.
53
+
54
+ The result includes libbase64 license information as well.
55
+ """
56
+ return _license
57
+
58
+
59
+ def get_version() -> str:
60
+ """Returns pybase64 version as a :class:`str` object.
61
+
62
+ The result reports if the C extension is used or not.
63
+ e.g. `1.0.0 (C extension active - AVX2)`
64
+ """
65
+ simd_name = _get_simd_name(_get_simd_path())
66
+ if simd_name != "fallback":
67
+ return f"{__version__} (C extension active - {simd_name})"
68
+ return f"{__version__} (C extension inactive)"
69
+
70
+
71
+ def standard_b64encode(s: Buffer) -> bytes:
72
+ """Encode bytes using the standard Base64 alphabet.
73
+
74
+ Argument ``s`` is a :term:`bytes-like object` to encode.
75
+
76
+ The result is returned as a :class:`bytes` object.
77
+ """
78
+ return b64encode(s)
79
+
80
+
81
+ def standard_b64decode(s: str | Buffer) -> bytes:
82
+ """Decode bytes encoded with the standard Base64 alphabet.
83
+
84
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
85
+ decode.
86
+
87
+ The result is returned as a :class:`bytes` object.
88
+
89
+ A :exc:`binascii.Error` is raised if the input is incorrectly padded.
90
+
91
+ Characters that are not in the standard alphabet are discarded prior
92
+ to the padding check.
93
+ """
94
+ return b64decode(s)
95
+
96
+
97
+ def urlsafe_b64encode(s: Buffer) -> bytes:
98
+ """Encode bytes using the URL- and filesystem-safe Base64 alphabet.
99
+
100
+ Argument ``s`` is a :term:`bytes-like object` to encode.
101
+
102
+ The result is returned as a :class:`bytes` object.
103
+
104
+ The alphabet uses '-' instead of '+' and '_' instead of '/'.
105
+ """
106
+ return b64encode(s, b"-_")
107
+
108
+
109
+ def urlsafe_b64decode(s: str | Buffer) -> bytes:
110
+ """Decode bytes using the URL- and filesystem-safe Base64 alphabet.
111
+
112
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
113
+ decode.
114
+
115
+ The result is returned as a :class:`bytes` object.
116
+
117
+ A :exc:`binascii.Error` is raised if the input is incorrectly padded.
118
+
119
+ Characters that are not in the URL-safe base-64 alphabet, and are not
120
+ a plus '+' or slash '/', are discarded prior to the padding check.
121
+
122
+ The alphabet uses '-' instead of '+' and '_' instead of '/'.
123
+ """
124
+ return b64decode(s, b"-_")
pybase64/__main__.py ADDED
@@ -0,0 +1,292 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import base64
5
+ import sys
6
+ from base64 import b64decode as b64decodeValidate
7
+ from base64 import encodebytes as b64encodebytes
8
+ from collections.abc import Sequence
9
+ from pathlib import Path
10
+ from timeit import default_timer as timer
11
+ from typing import TYPE_CHECKING, Any
12
+
13
+ import pybase64
14
+
15
+ if TYPE_CHECKING:
16
+ from pybase64._typing import Decode, Encode, EncodeBytes
17
+
18
+
19
+ def bench_one(
20
+ duration: float,
21
+ data: bytes,
22
+ enc: Encode,
23
+ dec: Decode,
24
+ encbytes: EncodeBytes,
25
+ altchars: bytes | None = None,
26
+ validate: bool = False,
27
+ ) -> None:
28
+ duration = duration / 2.0
29
+
30
+ if not validate and altchars is None:
31
+ number = 0
32
+ time = timer()
33
+ while True:
34
+ encodedcontent = encbytes(data)
35
+ number += 1
36
+ if timer() - time > duration:
37
+ break
38
+ iter = number
39
+ time = timer()
40
+ while iter > 0:
41
+ encodedcontent = encbytes(data)
42
+ iter -= 1
43
+ time = timer() - time
44
+ print(
45
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
46
+ encbytes.__module__ + "." + encbytes.__name__ + ":",
47
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
48
+ len(data),
49
+ len(encodedcontent),
50
+ )
51
+ )
52
+
53
+ number = 0
54
+ time = timer()
55
+ while True:
56
+ encodedcontent = enc(data, altchars=altchars)
57
+ number += 1
58
+ if timer() - time > duration:
59
+ break
60
+ iter = number
61
+ time = timer()
62
+ while iter > 0:
63
+ encodedcontent = enc(data, altchars=altchars)
64
+ iter -= 1
65
+ time = timer() - time
66
+ print(
67
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
68
+ enc.__module__ + "." + enc.__name__ + ":",
69
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
70
+ len(data),
71
+ len(encodedcontent),
72
+ )
73
+ )
74
+
75
+ number = 0
76
+ time = timer()
77
+ while True:
78
+ decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate)
79
+ number += 1
80
+ if timer() - time > duration:
81
+ break
82
+ iter = number
83
+ time = timer()
84
+ while iter > 0:
85
+ decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate)
86
+ iter -= 1
87
+ time = timer() - time
88
+ print(
89
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
90
+ dec.__module__ + "." + dec.__name__ + ":",
91
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
92
+ len(encodedcontent),
93
+ len(data),
94
+ )
95
+ )
96
+ assert decodedcontent == data
97
+
98
+
99
+ def readall(file: str) -> bytes:
100
+ if file == "-":
101
+ return sys.stdin.buffer.read()
102
+ return Path(file).read_bytes()
103
+
104
+
105
+ def writeall(file: str, data: bytes) -> None:
106
+ if file == "-":
107
+ sys.stdout.buffer.write(data)
108
+ else:
109
+ Path(file).write_bytes(data)
110
+
111
+
112
+ def benchmark(duration: float, input: str) -> None:
113
+ print(__package__ + " " + pybase64.get_version())
114
+ data = readall(input)
115
+ for altchars in [None, b"-_"]:
116
+ for validate in [False, True]:
117
+ print(f"bench: altchars={altchars!r:s}, validate={validate!r:s}")
118
+ bench_one(
119
+ duration,
120
+ data,
121
+ pybase64.b64encode,
122
+ pybase64.b64decode,
123
+ pybase64.encodebytes,
124
+ altchars,
125
+ validate,
126
+ )
127
+ bench_one(
128
+ duration,
129
+ data,
130
+ base64.b64encode,
131
+ b64decodeValidate,
132
+ b64encodebytes,
133
+ altchars,
134
+ validate,
135
+ )
136
+
137
+
138
+ def encode(input: str, altchars: bytes | None, output: str) -> None:
139
+ data = readall(input)
140
+ data = pybase64.b64encode(data, altchars)
141
+ writeall(output, data)
142
+
143
+
144
+ def decode(input: str, altchars: bytes | None, validate: bool, output: str) -> None:
145
+ data = readall(input)
146
+ data = pybase64.b64decode(data, altchars, validate)
147
+ writeall(output, data)
148
+
149
+
150
+ class LicenseAction(argparse.Action):
151
+ def __init__(
152
+ self,
153
+ option_strings: Sequence[str],
154
+ dest: str,
155
+ license: str | None = None,
156
+ help: str | None = "show license information and exit",
157
+ ):
158
+ super().__init__(
159
+ option_strings=option_strings,
160
+ dest=dest,
161
+ default=argparse.SUPPRESS,
162
+ nargs=0,
163
+ help=help,
164
+ )
165
+ self.license = license
166
+
167
+ def __call__(
168
+ self,
169
+ parser: argparse.ArgumentParser,
170
+ namespace: argparse.Namespace, # noqa: ARG002
171
+ values: str | Sequence[Any] | None, # noqa: ARG002
172
+ option_string: str | None = None, # noqa: ARG002
173
+ ) -> None:
174
+ print(self.license)
175
+ parser.exit()
176
+
177
+
178
+ def check_file(value: str, is_input: bool) -> str:
179
+ if value == "-":
180
+ return value
181
+ path = Path(value)
182
+ if is_input:
183
+ return str(path.resolve(strict=True))
184
+ return str(path.parent.resolve(strict=True) / path.name)
185
+
186
+
187
+ def main(argv: Sequence[str] | None = None) -> None:
188
+ # main parser
189
+ parser = argparse.ArgumentParser(
190
+ prog=__package__, description=__package__ + " command-line tool."
191
+ )
192
+ parser.add_argument(
193
+ "-V",
194
+ "--version",
195
+ action="version",
196
+ version=__package__ + " " + pybase64.get_version(),
197
+ )
198
+ parser.add_argument("--license", action=LicenseAction, license=pybase64.get_license_text())
199
+ # create sub-parsers
200
+ subparsers = parser.add_subparsers(help="tool help")
201
+ # benchmark parser
202
+ benchmark_parser = subparsers.add_parser("benchmark", help="-h for usage")
203
+ benchmark_parser.add_argument(
204
+ "-d",
205
+ "--duration",
206
+ metavar="D",
207
+ dest="duration",
208
+ type=float,
209
+ default=1.0,
210
+ help="expected duration for a single encode or decode test",
211
+ )
212
+ benchmark_parser.register("type", "input file", lambda s: check_file(s, True))
213
+ benchmark_parser.add_argument(
214
+ "input", type="input file", help="input file used for the benchmark"
215
+ )
216
+ benchmark_parser.set_defaults(func=benchmark)
217
+ # encode parser
218
+ encode_parser = subparsers.add_parser("encode", help="-h for usage")
219
+ encode_parser.register("type", "input file", lambda s: check_file(s, True))
220
+ encode_parser.register("type", "output file", lambda s: check_file(s, False))
221
+ encode_parser.add_argument("input", type="input file", help="input file to be encoded")
222
+ group = encode_parser.add_mutually_exclusive_group()
223
+ group.add_argument(
224
+ "-u",
225
+ "--url",
226
+ action="store_const",
227
+ const=b"-_",
228
+ dest="altchars",
229
+ help="use URL encoding",
230
+ )
231
+ group.add_argument(
232
+ "-a",
233
+ "--altchars",
234
+ dest="altchars",
235
+ help="use alternative characters for encoding",
236
+ )
237
+ encode_parser.add_argument(
238
+ "-o",
239
+ "--output",
240
+ dest="output",
241
+ type="output file",
242
+ default="-",
243
+ help="encoded output file (default to stdout)",
244
+ )
245
+ encode_parser.set_defaults(func=encode)
246
+ # decode parser
247
+ decode_parser = subparsers.add_parser("decode", help="-h for usage")
248
+ decode_parser.register("type", "input file", lambda s: check_file(s, True))
249
+ decode_parser.register("type", "output file", lambda s: check_file(s, False))
250
+ decode_parser.add_argument("input", type="input file", help="input file to be decoded")
251
+ group = decode_parser.add_mutually_exclusive_group()
252
+ group.add_argument(
253
+ "-u",
254
+ "--url",
255
+ action="store_const",
256
+ const=b"-_",
257
+ dest="altchars",
258
+ help="use URL decoding",
259
+ )
260
+ group.add_argument(
261
+ "-a",
262
+ "--altchars",
263
+ dest="altchars",
264
+ help="use alternative characters for decoding",
265
+ )
266
+ decode_parser.add_argument(
267
+ "-o",
268
+ "--output",
269
+ dest="output",
270
+ type="output file",
271
+ default="-",
272
+ help="decoded output file (default to stdout)",
273
+ )
274
+ decode_parser.add_argument(
275
+ "--no-validation",
276
+ dest="validate",
277
+ action="store_false",
278
+ help="disable validation of the input data",
279
+ )
280
+ decode_parser.set_defaults(func=decode)
281
+ # ready, parse
282
+ if argv is None:
283
+ argv = sys.argv[1:]
284
+ if len(argv) == 0:
285
+ argv = ["-h"]
286
+ args = vars(parser.parse_args(args=argv))
287
+ func = args.pop("func")
288
+ func(**args)
289
+
290
+
291
+ if __name__ == "__main__":
292
+ main()
pybase64/_fallback.py ADDED
@@ -0,0 +1,167 @@
1
+ from __future__ import annotations
2
+
3
+ from base64 import b64decode as builtin_decode
4
+ from base64 import b64encode as builtin_encode
5
+ from base64 import encodebytes as builtin_encodebytes
6
+ from binascii import Error as BinAsciiError
7
+ from typing import TYPE_CHECKING
8
+
9
+ if TYPE_CHECKING:
10
+ from ._typing import Buffer
11
+
12
+ _bytes_types = (bytes, bytearray) # Types acceptable as binary data
13
+
14
+
15
+ def _get_simd_name(flags: int) -> str:
16
+ assert flags == 0
17
+ return "fallback"
18
+
19
+
20
+ def _get_simd_path() -> int:
21
+ return 0
22
+
23
+
24
+ def _get_bytes(s: str | Buffer) -> bytes | bytearray:
25
+ if isinstance(s, str):
26
+ try:
27
+ return s.encode("ascii")
28
+ except UnicodeEncodeError:
29
+ msg = "string argument should contain only ASCII characters"
30
+ raise ValueError(msg) from None
31
+ if isinstance(s, _bytes_types):
32
+ return s
33
+ try:
34
+ mv = memoryview(s)
35
+ if not mv.c_contiguous:
36
+ msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous"
37
+ raise BufferError(msg)
38
+ return mv.tobytes()
39
+ except TypeError:
40
+ msg = (
41
+ "argument should be a bytes-like object or ASCII "
42
+ f"string, not {s.__class__.__name__!r:s}"
43
+ )
44
+ raise TypeError(msg) from None
45
+
46
+
47
+ def b64decode(
48
+ s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False
49
+ ) -> bytes:
50
+ """Decode bytes encoded with the standard Base64 alphabet.
51
+
52
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
53
+ decode.
54
+
55
+ Optional ``altchars`` must be a :term:`bytes-like object` or ASCII
56
+ string of length 2 which specifies the alternative alphabet used instead
57
+ of the '+' and '/' characters.
58
+
59
+ If ``validate`` is ``False`` (the default), characters that are neither in
60
+ the normal base-64 alphabet nor the alternative alphabet are discarded
61
+ prior to the padding check.
62
+ If ``validate`` is ``True``, these non-alphabet characters in the input
63
+ result in a :exc:`binascii.Error`.
64
+
65
+ The result is returned as a :class:`bytes` object.
66
+
67
+ A :exc:`binascii.Error` is raised if ``s`` is incorrectly padded.
68
+ """
69
+ s = _get_bytes(s)
70
+ if altchars is not None:
71
+ altchars = _get_bytes(altchars)
72
+ if validate:
73
+ if len(s) % 4 != 0:
74
+ msg = "Incorrect padding"
75
+ raise BinAsciiError(msg)
76
+ result = builtin_decode(s, altchars, validate=False)
77
+
78
+ # check length of result vs length of input
79
+ expected_len = 0
80
+ if len(s) > 0:
81
+ padding = 0
82
+ # len(s) % 4 != 0 implies len(s) >= 4 here
83
+ if s[-2] == 61: # 61 == ord("=")
84
+ padding += 1
85
+ if s[-1] == 61:
86
+ padding += 1
87
+ expected_len = 3 * (len(s) // 4) - padding
88
+ if expected_len != len(result):
89
+ msg = "Non-base64 digit found"
90
+ raise BinAsciiError(msg)
91
+ return result
92
+ return builtin_decode(s, altchars, validate=False)
93
+
94
+
95
+ def b64decode_as_bytearray(
96
+ s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False
97
+ ) -> bytearray:
98
+ """Decode bytes encoded with the standard Base64 alphabet.
99
+
100
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
101
+ decode.
102
+
103
+ Optional ``altchars`` must be a :term:`bytes-like object` or ASCII
104
+ string of length 2 which specifies the alternative alphabet used instead
105
+ of the '+' and '/' characters.
106
+
107
+ If ``validate`` is ``False`` (the default), characters that are neither in
108
+ the normal base-64 alphabet nor the alternative alphabet are discarded
109
+ prior to the padding check.
110
+ If ``validate`` is ``True``, these non-alphabet characters in the input
111
+ result in a :exc:`binascii.Error`.
112
+
113
+ The result is returned as a :class:`bytearray` object.
114
+
115
+ A :exc:`binascii.Error` is raised if ``s`` is incorrectly padded.
116
+ """
117
+ return bytearray(b64decode(s, altchars=altchars, validate=validate))
118
+
119
+
120
+ def b64encode(s: Buffer, altchars: str | Buffer | None = None) -> bytes:
121
+ """Encode bytes using the standard Base64 alphabet.
122
+
123
+ Argument ``s`` is a :term:`bytes-like object` to encode.
124
+
125
+ Optional ``altchars`` must be a byte string of length 2 which specifies
126
+ an alternative alphabet for the '+' and '/' characters. This allows an
127
+ application to e.g. generate url or filesystem safe Base64 strings.
128
+
129
+ The result is returned as a :class:`bytes` object.
130
+ """
131
+ mv = memoryview(s)
132
+ if not mv.c_contiguous:
133
+ msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous"
134
+ raise BufferError(msg)
135
+ if altchars is not None:
136
+ altchars = _get_bytes(altchars)
137
+ return builtin_encode(s, altchars)
138
+
139
+
140
+ def b64encode_as_string(s: Buffer, altchars: str | Buffer | None = None) -> str:
141
+ """Encode bytes using the standard Base64 alphabet.
142
+
143
+ Argument ``s`` is a :term:`bytes-like object` to encode.
144
+
145
+ Optional ``altchars`` must be a byte string of length 2 which specifies
146
+ an alternative alphabet for the '+' and '/' characters. This allows an
147
+ application to e.g. generate url or filesystem safe Base64 strings.
148
+
149
+ The result is returned as a :class:`str` object.
150
+ """
151
+ return b64encode(s, altchars).decode("ascii")
152
+
153
+
154
+ def encodebytes(s: Buffer) -> bytes:
155
+ """Encode bytes into a bytes object with newlines (b'\\\\n') inserted after
156
+ every 76 bytes of output, and ensuring that there is a trailing newline,
157
+ as per :rfc:`2045` (MIME).
158
+
159
+ Argument ``s`` is a :term:`bytes-like object` to encode.
160
+
161
+ The result is returned as a :class:`bytes` object.
162
+ """
163
+ mv = memoryview(s)
164
+ if not mv.c_contiguous:
165
+ msg = f"{s.__class__.__name__!r:s}: underlying buffer is not C-contiguous"
166
+ raise BufferError(msg)
167
+ return builtin_encodebytes(s)
pybase64/_license.py ADDED
@@ -0,0 +1,61 @@
1
+ _license = """pybase64
2
+ ===============================================================================
3
+ BSD 2-Clause License
4
+
5
+ Copyright (c) 2017-2022, Matthieu Darbois
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are met:
10
+
11
+ * Redistributions of source code must retain the above copyright notice, this
12
+ list of conditions and the following disclaimer.
13
+
14
+ * Redistributions in binary form must reproduce the above copyright notice,
15
+ this list of conditions and the following disclaimer in the documentation
16
+ and/or other materials provided with the distribution.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ ===============================================================================
29
+
30
+ libbase64
31
+ ===============================================================================
32
+ Copyright (c) 2005-2007, Nick Galbreath
33
+ Copyright (c) 2015-2018, Wojciech Muła
34
+ Copyright (c) 2016-2017, Matthieu Darbois
35
+ Copyright (c) 2013-2022, Alfred Klomp
36
+ All rights reserved.
37
+
38
+ Redistribution and use in source and binary forms, with or without
39
+ modification, are permitted provided that the following conditions are
40
+ met:
41
+
42
+ - Redistributions of source code must retain the above copyright notice,
43
+ this list of conditions and the following disclaimer.
44
+
45
+ - Redistributions in binary form must reproduce the above copyright
46
+ notice, this list of conditions and the following disclaimer in the
47
+ documentation and/or other materials provided with the distribution.
48
+
49
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
50
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
52
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
53
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
55
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
56
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
57
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
58
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60
+ ==========================================================================""" \
61
+ + "====="
pybase64/_license.pyi ADDED
@@ -0,0 +1 @@
1
+ _license: str
pybase64/_pybase64.pyi ADDED
@@ -0,0 +1,16 @@
1
+ from ._typing import Buffer
2
+
3
+ def _get_simd_flags_compile() -> int: ...
4
+ def _get_simd_flags_runtime() -> int: ...
5
+ def _get_simd_name(flags: int) -> str: ...
6
+ def _get_simd_path() -> int: ...
7
+ def _set_simd_path(flags: int) -> None: ...
8
+ def b64decode(
9
+ s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False
10
+ ) -> bytes: ...
11
+ def b64decode_as_bytearray(
12
+ s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False
13
+ ) -> bytearray: ...
14
+ def b64encode(s: Buffer, altchars: str | Buffer | None = None) -> bytes: ...
15
+ def b64encode_as_string(s: Buffer, altchars: str | Buffer | None = None) -> str: ...
16
+ def encodebytes(s: Buffer) -> bytes: ...
pybase64/_typing.py ADDED
@@ -0,0 +1,35 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import Protocol
5
+
6
+ if sys.version_info < (3, 12):
7
+ from typing_extensions import Buffer
8
+ else:
9
+ from collections.abc import Buffer
10
+
11
+
12
+ class Decode(Protocol):
13
+ __name__: str
14
+ __module__: str
15
+
16
+ def __call__(
17
+ self, s: str | Buffer, altchars: str | Buffer | None = None, validate: bool = False
18
+ ) -> bytes: ...
19
+
20
+
21
+ class Encode(Protocol):
22
+ __name__: str
23
+ __module__: str
24
+
25
+ def __call__(self, s: Buffer, altchars: Buffer | None = None) -> bytes: ...
26
+
27
+
28
+ class EncodeBytes(Protocol):
29
+ __name__: str
30
+ __module__: str
31
+
32
+ def __call__(self, s: Buffer) -> bytes: ...
33
+
34
+
35
+ __all__ = ("Buffer", "Decode", "Encode", "EncodeBytes")
pybase64/_version.py ADDED
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ _version = "1.4.2"
pybase64/py.typed ADDED
File without changes
@@ -0,0 +1,306 @@
1
+ Metadata-Version: 2.4
2
+ Name: pybase64
3
+ Version: 1.4.2
4
+ Summary: Fast Base64 encoding/decoding
5
+ Home-page: https://github.com/mayeut/pybase64
6
+ 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
10
+ Project-URL: Documentation, https://pybase64.readthedocs.io/en/stable
11
+ Keywords: base64
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Topic :: Utilities
16
+ Classifier: License :: OSI Approved :: BSD License
17
+ Classifier: Programming Language :: C
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.8
20
+ Classifier: Programming Language :: Python :: 3.9
21
+ Classifier: Programming Language :: Python :: 3.10
22
+ Classifier: Programming Language :: Python :: 3.11
23
+ Classifier: Programming Language :: Python :: 3.12
24
+ Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
26
+ Requires-Python: >=3.8
27
+ Description-Content-Type: text/x-rst
28
+ 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
36
+ Dynamic: license-file
37
+ Dynamic: project-url
38
+ Dynamic: requires-python
39
+ Dynamic: summary
40
+
41
+ .. SETUP VARIABLES
42
+ .. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg
43
+ :target: https://github.com/mayeut/pybase64/blob/master/LICENSE
44
+ .. |pypi-status| image:: https://img.shields.io/pypi/v/pybase64.svg
45
+ :target: https://pypi.python.org/pypi/pybase64
46
+ .. |python-versions| image:: https://img.shields.io/pypi/pyversions/pybase64.svg
47
+ .. |rtd-status| image:: https://readthedocs.org/projects/pybase64/badge/?version=stable
48
+ :target: http://pybase64.readthedocs.io/en/stable/?badge=stable
49
+ :alt: Documentation Status
50
+ .. |gha-status| image:: https://github.com/mayeut/pybase64/workflows/Build%20and%20upload%20to%20PyPI/badge.svg
51
+ :target: https://github.com/mayeut/pybase64/actions?query=workflow%3A%22Build+and+upload+to+PyPI%22
52
+ .. |codecov-status| image:: https://codecov.io/gh/mayeut/pybase64/branch/master/graph/badge.svg
53
+ :target: https://codecov.io/gh/mayeut/pybase64/branch/master
54
+ .. END OF SETUP
55
+
56
+ Fast Base64 implementation
57
+ ==========================
58
+
59
+ |license-status| |pypi-status| |python-versions| |rtd-status| |gha-status| |codecov-status|
60
+
61
+ This project is a wrapper on `libbase64 <https://github.com/aklomp/base64>`_.
62
+
63
+ It aims to provide a fast base64 implementation for base64 encoding/decoding.
64
+
65
+ Installation
66
+ ============
67
+
68
+ .. code::
69
+
70
+ pip install pybase64
71
+
72
+ Usage
73
+ =====
74
+
75
+ ``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
76
+
77
+ To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` and ``validate=True`` when possible.
78
+
79
+ .. code:: python
80
+
81
+ import pybase64
82
+
83
+ print(pybase64.b64encode(b'>>>foo???', altchars='_:'))
84
+ # b'Pj4_Zm9vPz8:'
85
+ print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True))
86
+ # b'>>>foo???'
87
+
88
+ # Standard encoding helpers
89
+ print(pybase64.standard_b64encode(b'>>>foo???'))
90
+ # b'Pj4+Zm9vPz8/'
91
+ print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/'))
92
+ # b'>>>foo???'
93
+
94
+ # URL safe encoding helpers
95
+ print(pybase64.urlsafe_b64encode(b'>>>foo???'))
96
+ # b'Pj4-Zm9vPz8_'
97
+ print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_'))
98
+ # b'>>>foo???'
99
+
100
+ .. begin cli
101
+
102
+ A command-line tool is also provided. It has encode, decode and benchmark subcommands.
103
+
104
+ .. code::
105
+
106
+ usage: pybase64 [-h] [-V] {benchmark,encode,decode} ...
107
+
108
+ pybase64 command-line tool.
109
+
110
+ positional arguments:
111
+ {benchmark,encode,decode}
112
+ tool help
113
+ benchmark -h for usage
114
+ encode -h for usage
115
+ decode -h for usage
116
+
117
+ optional arguments:
118
+ -h, --help show this help message and exit
119
+ -V, --version show program's version number and exit
120
+
121
+ .. end cli
122
+
123
+ Full documentation on `Read the Docs <http://pybase64.readthedocs.io/en/stable/?badge=stable>`_.
124
+
125
+ Benchmark
126
+ =========
127
+
128
+ .. begin benchmark
129
+
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
131
+
132
+ .. code::
133
+
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)
157
+
158
+ .. end benchmark
159
+
160
+ .. begin changelog
161
+
162
+ Changelog
163
+ =========
164
+ 1.4.2
165
+ -----
166
+ - Update base64 library (Windows ARM64 Neon support)
167
+ - Publish Python 3.14 wheels
168
+ - Publish Linux riscv64 wheels
169
+ - Publish Android wheels
170
+ - Publish iOS wheels
171
+ - Publish GraalPy wheels
172
+
173
+ 1.4.1
174
+ -----
175
+ - Publish PyPy 3.11 wheels
176
+ - Publish armv7l wheels
177
+
178
+ 1.4.0
179
+ -----
180
+ - Publish python 3.13 wheels
181
+ - Add support for free-threaded builds
182
+ - Add MSYS2 support for C-extension
183
+ - Better logging on base64 build failure when C-extension build is optional
184
+ - Drop python 3.6 & 3.7 support
185
+
186
+ 1.3.2
187
+ -----
188
+ - Update base64 library
189
+ - PyPy: fix wrong outcome with non C-contiguous buffer
190
+
191
+ 1.3.1
192
+ -----
193
+ - Add missing py.typed marker
194
+
195
+ 1.3.0
196
+ -----
197
+ - Update base64 library
198
+ - Add AVX512-VBMI implementation
199
+ - Rework extension build to remove adherence on distutils
200
+ - Publish python 3.12 wheels
201
+ - Documentation now uses furo theme
202
+
203
+ 1.2.3
204
+ -----
205
+ - Update base64 library
206
+ - Publish python 3.11 wheels
207
+
208
+ 1.2.2
209
+ -----
210
+ - Update base64 library
211
+ - Fix C extension build on musl distros
212
+ - Publish musllinux wheels
213
+
214
+ 1.2.1
215
+ -----
216
+ - Publish PyPy 3.8 (pypy38_pp73) wheels
217
+
218
+ 1.2.0
219
+ -----
220
+ - Release the GIL
221
+ - Publish CPython 3.10 wheels
222
+ - Drop python 3.5 support
223
+
224
+ 1.1.4
225
+ -----
226
+ - Add macOS arm64 wheel
227
+
228
+ 1.1.3
229
+ -----
230
+ - GitHub Actions: fix build on tag
231
+
232
+ 1.1.2
233
+ -----
234
+ - Add PyPy wheels
235
+ - Add aarch64, ppc64le & s390x manylinux wheels
236
+
237
+ 1.1.1
238
+ -----
239
+ - Move CI from TravisCI/AppVeyor to GitHub Actions
240
+ - Fix publication of Linux/macOS wheels
241
+
242
+ 1.1.0
243
+ -----
244
+ - Add b64encode_as_string, same as b64encode but returns a str object instead of a bytes object
245
+ - Add b64decode_as_bytearray, same as b64decode but returns a bytarray object instead of a bytes object
246
+ - Speed-Up decoding from UCS1 strings
247
+
248
+ 1.0.2
249
+ -----
250
+ - Update base64 library
251
+ - Publish python 3.9 wheels
252
+
253
+ 1.0.1
254
+ -----
255
+ - Publish python 3.8 wheels
256
+
257
+ 1.0.0
258
+ -----
259
+ - Drop python 3.4 support
260
+ - Drop python 2.7 support
261
+
262
+ 0.5.0
263
+ -----
264
+ - Publish python 3.7 wheels
265
+ - Drop python 3.3 support
266
+
267
+ 0.4.0
268
+ -----
269
+ - Speed-up decoding when validate==False
270
+
271
+ 0.3.1
272
+ -----
273
+ - Fix deployment issues
274
+
275
+ 0.3.0
276
+ -----
277
+ - Add encodebytes function
278
+
279
+ 0.2.1
280
+ -----
281
+ - Fixed invalid results on Windows
282
+
283
+ 0.2.0
284
+ -----
285
+ - Added documentation
286
+ - Added subcommands to the main script:
287
+
288
+ * help
289
+ * version
290
+ * encode
291
+ * decode
292
+ * benchmark
293
+
294
+ 0.1.2
295
+ -----
296
+ - Updated base64 native library
297
+
298
+ 0.1.1
299
+ -----
300
+ - Fixed deployment issues
301
+
302
+ 0.1.0
303
+ -----
304
+ - First public release
305
+
306
+ .. end changelog
@@ -0,0 +1,16 @@
1
+ pybase64/__init__.py,sha256=wb_YG09m0-rC6lPmDKF62XsEcVhGkCxcPw2GZyxE9L4,3230
2
+ pybase64/__main__.py,sha256=djZqQ6QNmgIAjvYHQa-uIApZhxyUZj2UzvDeQjfLn0w,8530
3
+ pybase64/_fallback.py,sha256=L-i5KnRtLU2PfBbKIL2hNiHmNrWs1LeWYh3xGD8mriM,5800
4
+ pybase64/_license.py,sha256=Lu3v1O3buEcMPgKC5f4r523lGvNGgoTXhHnHh0Ys1kw,3116
5
+ pybase64/_license.pyi,sha256=aTpwZqUJh82NsyBwHhQo_cJRZsBYSARCKxGdtb1QYPk,14
6
+ pybase64/_pybase64.cpython-313-aarch64-linux-android.so,sha256=W7dRgH0KrQLx3SMGigFag79Asc3b1LeNudS56UB8vSc,48016
7
+ pybase64/_pybase64.pyi,sha256=wxk6eoWmafyE9NOVr2j9T0E2w2lSC-ImIL5E-HP1XcE,679
8
+ pybase64/_typing.py,sha256=QvyxFSzktrAAOT2ohlB5ah1WDbqL6bnZDRvgemDZY1k,709
9
+ pybase64/_version.py,sha256=_VSFxJfXwKW9isWsQYEeKF59rytvn_LO7yJ2uuV-LL0,55
10
+ pybase64/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ pybase64-1.4.2.dist-info/licenses/LICENSE,sha256=XlI7VMFYHUT0WL_dLNOUTWIrsaMqpB8Hc-5No5D7RbQ,1326
12
+ pybase64-1.4.2.dist-info/METADATA,sha256=JJqLdcfA01uCrnwagf4Jn44a_WeJcs9fTZaoL_IjXa0,8663
13
+ pybase64-1.4.2.dist-info/WHEEL,sha256=5I58AbR9O_ArnZQueeIBJrrQjT_lZqa3wHwMOp-EJ_E,112
14
+ pybase64-1.4.2.dist-info/entry_points.txt,sha256=qLhLeuPRnj6ju76SqeVYOuxavmDKx9ZWjXHLltpLa5o,52
15
+ pybase64-1.4.2.dist-info/top_level.txt,sha256=Tm3tmGpMnLWAvjrxORS2E5I6LARaLepOEUjGaTmFuZg,9
16
+ pybase64-1.4.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-android_21_arm64_v8a
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pybase64 = pybase64.__main__:main
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2017-2022, Matthieu Darbois
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1 @@
1
+ pybase64