pybase64 1.4.0__cp313-cp313-win_amd64.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_b64encode",
43
+ "standard_b64decode",
44
+ "urlsafe_b64encode",
45
+ "urlsafe_b64decode",
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,299 @@
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 timeit import default_timer as timer
10
+ from typing import TYPE_CHECKING, Any, BinaryIO, cast
11
+
12
+ import pybase64
13
+
14
+ if TYPE_CHECKING:
15
+ from pybase64._typing import Decode, Encode, EncodeBytes
16
+
17
+
18
+ def bench_one(
19
+ duration: float,
20
+ data: bytes,
21
+ enc: Encode,
22
+ dec: Decode,
23
+ encbytes: EncodeBytes,
24
+ altchars: bytes | None = None,
25
+ validate: bool = False,
26
+ ) -> None:
27
+ duration = duration / 2.0
28
+
29
+ if not validate and altchars is None:
30
+ number = 0
31
+ time = timer()
32
+ while True:
33
+ encodedcontent = encbytes(data)
34
+ number += 1
35
+ if timer() - time > duration:
36
+ break
37
+ iter = number
38
+ time = timer()
39
+ while iter > 0:
40
+ encodedcontent = encbytes(data)
41
+ iter -= 1
42
+ time = timer() - time
43
+ print(
44
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
45
+ encbytes.__module__ + "." + encbytes.__name__ + ":",
46
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
47
+ len(data),
48
+ len(encodedcontent),
49
+ )
50
+ )
51
+
52
+ number = 0
53
+ time = timer()
54
+ while True:
55
+ encodedcontent = enc(data, altchars=altchars)
56
+ number += 1
57
+ if timer() - time > duration:
58
+ break
59
+ iter = number
60
+ time = timer()
61
+ while iter > 0:
62
+ encodedcontent = enc(data, altchars=altchars)
63
+ iter -= 1
64
+ time = timer() - time
65
+ print(
66
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
67
+ enc.__module__ + "." + enc.__name__ + ":",
68
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
69
+ len(data),
70
+ len(encodedcontent),
71
+ )
72
+ )
73
+
74
+ number = 0
75
+ time = timer()
76
+ while True:
77
+ decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate)
78
+ number += 1
79
+ if timer() - time > duration:
80
+ break
81
+ iter = number
82
+ time = timer()
83
+ while iter > 0:
84
+ decodedcontent = dec(encodedcontent, altchars=altchars, validate=validate)
85
+ iter -= 1
86
+ time = timer() - time
87
+ print(
88
+ "{:<32s} {:9.3f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
89
+ dec.__module__ + "." + dec.__name__ + ":",
90
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
91
+ len(encodedcontent),
92
+ len(data),
93
+ )
94
+ )
95
+ assert decodedcontent == data
96
+
97
+
98
+ def readall(file: BinaryIO) -> bytes:
99
+ if file == cast(BinaryIO, sys.stdin):
100
+ # Python 3 < 3.9 does not honor the binary flag,
101
+ # read from the underlying buffer
102
+ if hasattr(file, "buffer"):
103
+ return cast(BinaryIO, file.buffer).read()
104
+ return file.read() # pragma: no cover
105
+ # do not close the file
106
+ try:
107
+ data = file.read()
108
+ finally:
109
+ file.close()
110
+ return data
111
+
112
+
113
+ def writeall(file: BinaryIO, data: bytes) -> None:
114
+ if file == cast(BinaryIO, sys.stdout):
115
+ # Python 3 does not honor the binary flag,
116
+ # write to the underlying buffer
117
+ if hasattr(file, "buffer"):
118
+ file.buffer.write(data)
119
+ else:
120
+ file.write(data) # pragma: no cover
121
+ # do not close the file
122
+ else:
123
+ try:
124
+ file.write(data)
125
+ finally:
126
+ file.close()
127
+
128
+
129
+ def benchmark(duration: float, input: BinaryIO) -> None:
130
+ print(__package__ + " " + pybase64.get_version())
131
+ data = readall(input)
132
+ for altchars in [None, b"-_"]:
133
+ for validate in [False, True]:
134
+ print(f"bench: altchars={altchars!r:s}, validate={validate!r:s}")
135
+ bench_one(
136
+ duration,
137
+ data,
138
+ pybase64.b64encode,
139
+ pybase64.b64decode,
140
+ pybase64.encodebytes,
141
+ altchars,
142
+ validate,
143
+ )
144
+ bench_one(
145
+ duration,
146
+ data,
147
+ base64.b64encode,
148
+ b64decodeValidate,
149
+ b64encodebytes,
150
+ altchars,
151
+ validate,
152
+ )
153
+
154
+
155
+ def encode(input: BinaryIO, altchars: bytes | None, output: BinaryIO) -> None:
156
+ data = readall(input)
157
+ data = pybase64.b64encode(data, altchars)
158
+ writeall(output, data)
159
+
160
+
161
+ def decode(input: BinaryIO, altchars: bytes | None, validate: bool, output: BinaryIO) -> None:
162
+ data = readall(input)
163
+ data = pybase64.b64decode(data, altchars, validate)
164
+ writeall(output, data)
165
+
166
+
167
+ class LicenseAction(argparse.Action):
168
+ def __init__(
169
+ self,
170
+ option_strings: Sequence[str],
171
+ dest: str,
172
+ license: str | None = None,
173
+ help: str | None = "show license information and exit",
174
+ ):
175
+ super().__init__(
176
+ option_strings=option_strings,
177
+ dest=dest,
178
+ default=argparse.SUPPRESS,
179
+ nargs=0,
180
+ help=help,
181
+ )
182
+ self.license = license
183
+
184
+ def __call__(
185
+ self,
186
+ parser: argparse.ArgumentParser,
187
+ namespace: argparse.Namespace, # noqa: ARG002
188
+ values: str | Sequence[Any] | None, # noqa: ARG002
189
+ option_string: str | None = None, # noqa: ARG002
190
+ ) -> None:
191
+ print(self.license)
192
+ parser.exit()
193
+
194
+
195
+ def main(argv: Sequence[str] | None = None) -> None:
196
+ # main parser
197
+ parser = argparse.ArgumentParser(
198
+ prog=__package__, description=__package__ + " command-line tool."
199
+ )
200
+ parser.add_argument(
201
+ "-V",
202
+ "--version",
203
+ action="version",
204
+ version=__package__ + " " + pybase64.get_version(),
205
+ )
206
+ parser.add_argument("--license", action=LicenseAction, license=pybase64.get_license_text())
207
+ # create sub-parsers
208
+ subparsers = parser.add_subparsers(help="tool help")
209
+ # benchmark parser
210
+ benchmark_parser = subparsers.add_parser("benchmark", help="-h for usage")
211
+ benchmark_parser.add_argument(
212
+ "-d",
213
+ "--duration",
214
+ metavar="D",
215
+ dest="duration",
216
+ type=float,
217
+ default=1.0,
218
+ help="expected duration for a single encode or decode test",
219
+ )
220
+ benchmark_parser.add_argument(
221
+ "input", type=argparse.FileType("rb"), help="input file used for the benchmark"
222
+ )
223
+ benchmark_parser.set_defaults(func=benchmark)
224
+ # encode parser
225
+ encode_parser = subparsers.add_parser("encode", help="-h for usage")
226
+ encode_parser.add_argument(
227
+ "input", type=argparse.FileType("rb"), help="input file to be encoded"
228
+ )
229
+ group = encode_parser.add_mutually_exclusive_group()
230
+ group.add_argument(
231
+ "-u",
232
+ "--url",
233
+ action="store_const",
234
+ const=b"-_",
235
+ dest="altchars",
236
+ help="use URL encoding",
237
+ )
238
+ group.add_argument(
239
+ "-a",
240
+ "--altchars",
241
+ dest="altchars",
242
+ help="use alternative characters for encoding",
243
+ )
244
+ encode_parser.add_argument(
245
+ "-o",
246
+ "--output",
247
+ dest="output",
248
+ type=argparse.FileType("wb"),
249
+ default=sys.stdout,
250
+ help="encoded output file (default to stdout)",
251
+ )
252
+ encode_parser.set_defaults(func=encode)
253
+ # decode parser
254
+ decode_parser = subparsers.add_parser("decode", help="-h for usage")
255
+ decode_parser.add_argument(
256
+ "input", type=argparse.FileType("rb"), help="input file to be decoded"
257
+ )
258
+ group = decode_parser.add_mutually_exclusive_group()
259
+ group.add_argument(
260
+ "-u",
261
+ "--url",
262
+ action="store_const",
263
+ const=b"-_",
264
+ dest="altchars",
265
+ help="use URL decoding",
266
+ )
267
+ group.add_argument(
268
+ "-a",
269
+ "--altchars",
270
+ dest="altchars",
271
+ help="use alternative characters for decoding",
272
+ )
273
+ decode_parser.add_argument(
274
+ "-o",
275
+ "--output",
276
+ dest="output",
277
+ type=argparse.FileType("wb"),
278
+ default=sys.stdout,
279
+ help="decoded output file (default to stdout)",
280
+ )
281
+ decode_parser.add_argument(
282
+ "--no-validation",
283
+ dest="validate",
284
+ action="store_false",
285
+ help="disable validation of the input data",
286
+ )
287
+ decode_parser.set_defaults(func=decode)
288
+ # ready, parse
289
+ if argv is None:
290
+ argv = sys.argv[1:]
291
+ if len(argv) == 0:
292
+ argv = ["-h"]
293
+ args = vars(parser.parse_args(args=argv))
294
+ func = args.pop("func")
295
+ func(**args)
296
+
297
+
298
+ if __name__ == "__main__":
299
+ 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
Binary file
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.0"
pybase64/py.typed ADDED
File without changes
@@ -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,280 @@
1
+ Metadata-Version: 2.1
2
+ Name: pybase64
3
+ Version: 1.4.0
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
+ Requires-Python: >=3.8
26
+ Description-Content-Type: text/x-rst
27
+ License-File: LICENSE
28
+
29
+ .. SETUP VARIABLES
30
+ .. |license-status| image:: https://img.shields.io/badge/license-BSD%202--Clause-blue.svg
31
+ :target: https://github.com/mayeut/pybase64/blob/master/LICENSE
32
+ .. |pypi-status| image:: https://img.shields.io/pypi/v/pybase64.svg
33
+ :target: https://pypi.python.org/pypi/pybase64
34
+ .. |python-versions| image:: https://img.shields.io/pypi/pyversions/pybase64.svg
35
+ .. |rtd-status| image:: https://readthedocs.org/projects/pybase64/badge/?version=stable
36
+ :target: http://pybase64.readthedocs.io/en/stable/?badge=stable
37
+ :alt: Documentation Status
38
+ .. |gha-status| image:: https://github.com/mayeut/pybase64/workflows/Build%20and%20upload%20to%20PyPI/badge.svg
39
+ :target: https://github.com/mayeut/pybase64/actions?query=workflow%3A%22Build+and+upload+to+PyPI%22
40
+ .. |codecov-status| image:: https://codecov.io/gh/mayeut/pybase64/branch/master/graph/badge.svg
41
+ :target: https://codecov.io/gh/mayeut/pybase64/branch/master
42
+ .. END OF SETUP
43
+
44
+ Fast Base64 implementation
45
+ ==========================
46
+
47
+ |license-status| |pypi-status| |python-versions| |rtd-status| |gha-status| |codecov-status|
48
+
49
+ This project is a wrapper on `libbase64 <https://github.com/aklomp/base64>`_.
50
+
51
+ It aims to provide a fast base64 implementation for base64 encoding/decoding.
52
+
53
+ Installation
54
+ ============
55
+
56
+ .. code::
57
+
58
+ pip install pybase64
59
+
60
+ Usage
61
+ =====
62
+
63
+ ``pybase64`` uses the same API as Python base64 "modern interface" (introduced in Python 2.4) for an easy integration.
64
+
65
+ To get the fastest decoding, it is recommended to use the ``pybase64.b64decode`` and ``validate=True`` when possible.
66
+
67
+ .. code:: python
68
+
69
+ import pybase64
70
+
71
+ print(pybase64.b64encode(b'>>>foo???', altchars='_:'))
72
+ # b'Pj4_Zm9vPz8:'
73
+ print(pybase64.b64decode(b'Pj4_Zm9vPz8:', altchars='_:', validate=True))
74
+ # b'>>>foo???'
75
+
76
+ # Standard encoding helpers
77
+ print(pybase64.standard_b64encode(b'>>>foo???'))
78
+ # b'Pj4+Zm9vPz8/'
79
+ print(pybase64.standard_b64decode(b'Pj4+Zm9vPz8/'))
80
+ # b'>>>foo???'
81
+
82
+ # URL safe encoding helpers
83
+ print(pybase64.urlsafe_b64encode(b'>>>foo???'))
84
+ # b'Pj4-Zm9vPz8_'
85
+ print(pybase64.urlsafe_b64decode(b'Pj4-Zm9vPz8_'))
86
+ # b'>>>foo???'
87
+
88
+ .. begin cli
89
+
90
+ A command-line tool is also provided. It has encode, decode and benchmark subcommands.
91
+
92
+ .. code::
93
+
94
+ usage: pybase64 [-h] [-V] {benchmark,encode,decode} ...
95
+
96
+ pybase64 command-line tool.
97
+
98
+ positional arguments:
99
+ {benchmark,encode,decode}
100
+ tool help
101
+ benchmark -h for usage
102
+ encode -h for usage
103
+ decode -h for usage
104
+
105
+ optional arguments:
106
+ -h, --help show this help message and exit
107
+ -V, --version show program's version number and exit
108
+
109
+ .. end cli
110
+
111
+ Full documentation on `Read the Docs <http://pybase64.readthedocs.io/en/stable/?badge=stable>`_.
112
+
113
+ Benchmark
114
+ =========
115
+
116
+ .. begin benchmark
117
+
118
+ 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
119
+
120
+ .. code::
121
+
122
+ pybase64 0.5.0 (C extension active - AVX2)
123
+ bench: altchars=None, validate=False
124
+ pybase64._pybase64.encodebytes: 1734.776 MB/s (13,271,472 bytes -> 17,928,129 bytes)
125
+ pybase64._pybase64.b64encode: 4039.539 MB/s (13,271,472 bytes -> 17,695,296 bytes)
126
+ pybase64._pybase64.b64decode: 1854.423 MB/s (17,695,296 bytes -> 13,271,472 bytes)
127
+ base64.encodebytes: 78.352 MB/s (13,271,472 bytes -> 17,928,129 bytes)
128
+ base64.b64encode: 539.840 MB/s (13,271,472 bytes -> 17,695,296 bytes)
129
+ base64.b64decode: 287.826 MB/s (17,695,296 bytes -> 13,271,472 bytes)
130
+ bench: altchars=None, validate=True
131
+ pybase64._pybase64.b64encode: 4156.607 MB/s (13,271,472 bytes -> 17,695,296 bytes)
132
+ pybase64._pybase64.b64decode: 4107.997 MB/s (17,695,296 bytes -> 13,271,472 bytes)
133
+ base64.b64encode: 559.342 MB/s (13,271,472 bytes -> 17,695,296 bytes)
134
+ base64.b64decode: 143.674 MB/s (17,695,296 bytes -> 13,271,472 bytes)
135
+ bench: altchars=b'-_', validate=False
136
+ pybase64._pybase64.b64encode: 2786.776 MB/s (13,271,472 bytes -> 17,695,296 bytes)
137
+ pybase64._pybase64.b64decode: 1124.136 MB/s (17,695,296 bytes -> 13,271,472 bytes)
138
+ base64.b64encode: 322.427 MB/s (13,271,472 bytes -> 17,695,296 bytes)
139
+ base64.b64decode: 205.195 MB/s (17,695,296 bytes -> 13,271,472 bytes)
140
+ bench: altchars=b'-_', validate=True
141
+ pybase64._pybase64.b64encode: 2806.271 MB/s (13,271,472 bytes -> 17,695,296 bytes)
142
+ pybase64._pybase64.b64decode: 2740.456 MB/s (17,695,296 bytes -> 13,271,472 bytes)
143
+ base64.b64encode: 314.709 MB/s (13,271,472 bytes -> 17,695,296 bytes)
144
+ base64.b64decode: 121.803 MB/s (17,695,296 bytes -> 13,271,472 bytes)
145
+
146
+ .. end benchmark
147
+
148
+ .. begin changelog
149
+
150
+ Changelog
151
+ =========
152
+ 1.4.0
153
+ -----
154
+ - Publish python 3.13 wheels
155
+ - Add support for free-threaded builds
156
+ - Add MSYS2 support for C-extension
157
+ - Better logging on base64 build failure when C-extension build is optional
158
+ - Drop python 3.6 & 3.7 support
159
+
160
+ 1.3.2
161
+ -----
162
+ - Update base64 library
163
+ - PyPy: fix wrong outcome with non C-contiguous buffer
164
+
165
+ 1.3.1
166
+ -----
167
+ - Add missing py.typed marker
168
+
169
+ 1.3.0
170
+ -----
171
+ - Update base64 library
172
+ - Add AVX512-VBMI implementation
173
+ - Rework extension build to remove adherence on distutils
174
+ - Publish python 3.12 wheels
175
+ - Documentation now uses furo theme
176
+
177
+ 1.2.3
178
+ -----
179
+ - Update base64 library
180
+ - Publish python 3.11 wheels
181
+
182
+ 1.2.2
183
+ -----
184
+ - Update base64 library
185
+ - Fix C extension build on musl distros
186
+ - Publish musllinux wheels
187
+
188
+ 1.2.1
189
+ -----
190
+ - Publish PyPy 3.8 (pypy38_pp73) wheels
191
+
192
+ 1.2.0
193
+ -----
194
+ - Release the GIL
195
+ - Publish CPython 3.10 wheels
196
+ - Drop python 3.5 support
197
+
198
+ 1.1.4
199
+ -----
200
+ - Add macOS arm64 wheel
201
+
202
+ 1.1.3
203
+ -----
204
+ - GitHub Actions: fix build on tag
205
+
206
+ 1.1.2
207
+ -----
208
+ - Add PyPy wheels
209
+ - Add aarch64, ppc64le & s390x manylinux wheels
210
+
211
+ 1.1.1
212
+ -----
213
+ - Move CI from TravisCI/AppVeyor to GitHub Actions
214
+ - Fix publication of Linux/macOS wheels
215
+
216
+ 1.1.0
217
+ -----
218
+ - Add b64encode_as_string, same as b64encode but returns a str object instead of a bytes object
219
+ - Add b64decode_as_bytearray, same as b64decode but returns a bytarray object instead of a bytes object
220
+ - Speed-Up decoding from UCS1 strings
221
+
222
+ 1.0.2
223
+ -----
224
+ - Update base64 library
225
+ - Publish python 3.9 wheels
226
+
227
+ 1.0.1
228
+ -----
229
+ - Publish python 3.8 wheels
230
+
231
+ 1.0.0
232
+ -----
233
+ - Drop python 3.4 support
234
+ - Drop python 2.7 support
235
+
236
+ 0.5.0
237
+ -----
238
+ - Publish python 3.7 wheels
239
+ - Drop python 3.3 support
240
+
241
+ 0.4.0
242
+ -----
243
+ - Speed-up decoding when validate==False
244
+
245
+ 0.3.1
246
+ -----
247
+ - Fix deployment issues
248
+
249
+ 0.3.0
250
+ -----
251
+ - Add encodebytes function
252
+
253
+ 0.2.1
254
+ -----
255
+ - Fixed invalid results on Windows
256
+
257
+ 0.2.0
258
+ -----
259
+ - Added documentation
260
+ - Added subcommands to the main script:
261
+
262
+ * help
263
+ * version
264
+ * encode
265
+ * decode
266
+ * benchmark
267
+
268
+ 0.1.2
269
+ -----
270
+ - Updated base64 native library
271
+
272
+ 0.1.1
273
+ -----
274
+ - Fixed deployment issues
275
+
276
+ 0.1.0
277
+ -----
278
+ - First public release
279
+
280
+ .. end changelog
@@ -0,0 +1,16 @@
1
+ pybase64/__init__.py,sha256=zgrL4Gg84m2WW4JZGK48hbTcPnBnaKWd3dDqR4MbNbU,3230
2
+ pybase64/__main__.py,sha256=JDOvgUjyJ7f3vnofAjaqJzFCUhzc1o4EhrXt40Wxkp4,8595
3
+ pybase64/_fallback.py,sha256=L-i5KnRtLU2PfBbKIL2hNiHmNrWs1LeWYh3xGD8mriM,5800
4
+ pybase64/_license.py,sha256=q-Ur84gq4Q50vNU3gFEFBEyiSze9LcGa4AJk93KEsBw,3177
5
+ pybase64/_license.pyi,sha256=aTpwZqUJh82NsyBwHhQo_cJRZsBYSARCKxGdtb1QYPk,14
6
+ pybase64/_pybase64.cp313-win_amd64.pyd,sha256=N7PhWnpyg8KX9ytxMQ5pEh7Uco6QrraaaSBOpVi9HpE,55296
7
+ pybase64/_pybase64.pyi,sha256=wxk6eoWmafyE9NOVr2j9T0E2w2lSC-ImIL5E-HP1XcE,679
8
+ pybase64/_typing.py,sha256=QvyxFSzktrAAOT2ohlB5ah1WDbqL6bnZDRvgemDZY1k,709
9
+ pybase64/_version.py,sha256=MilKcl6wPaa9TPOkEt3xmdOe60n1ucDEAk_t2Nu8zxI,55
10
+ pybase64/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ pybase64-1.4.0.dist-info/LICENSE,sha256=XlI7VMFYHUT0WL_dLNOUTWIrsaMqpB8Hc-5No5D7RbQ,1326
12
+ pybase64-1.4.0.dist-info/METADATA,sha256=R5GkfwUV0xAVWbOLgznEdpbnQRcPPW7JuN_k7i8jz3E,8401
13
+ pybase64-1.4.0.dist-info/WHEEL,sha256=YY3whN5zaIpzxWCxMHGQtwoICDXEsGAh-bKATaD2hj4,101
14
+ pybase64-1.4.0.dist-info/entry_points.txt,sha256=qLhLeuPRnj6ju76SqeVYOuxavmDKx9ZWjXHLltpLa5o,52
15
+ pybase64-1.4.0.dist-info/top_level.txt,sha256=Tm3tmGpMnLWAvjrxORS2E5I6LARaLepOEUjGaTmFuZg,9
16
+ pybase64-1.4.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (72.1.0)
3
+ Root-Is-Purelib: false
4
+ Tag: cp313-cp313-win_amd64
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pybase64 = pybase64.__main__:main
@@ -0,0 +1 @@
1
+ pybase64