pybase64 1.5.0__cp313-cp313-android_24_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,128 @@
1
+ from __future__ import annotations
2
+
3
+ __lazy_modules__ = ["pybase64._license"]
4
+
5
+ from pybase64._license import _license
6
+ from pybase64._version import _version
7
+
8
+ TYPE_CHECKING = False
9
+ if TYPE_CHECKING:
10
+ from pybase64._typing import Buffer
11
+
12
+ try:
13
+ from pybase64._pybase64 import (
14
+ _get_simd_flags_compile, # noqa: F401
15
+ _get_simd_flags_runtime, # noqa: F401
16
+ _get_simd_name,
17
+ _get_simd_path,
18
+ _set_simd_path, # noqa: F401
19
+ b64decode,
20
+ b64decode_as_bytearray,
21
+ b64encode,
22
+ b64encode_as_string,
23
+ encodebytes,
24
+ )
25
+ except ImportError:
26
+ from pybase64._fallback import (
27
+ _get_simd_name,
28
+ _get_simd_path,
29
+ b64decode,
30
+ b64decode_as_bytearray,
31
+ b64encode,
32
+ b64encode_as_string,
33
+ encodebytes,
34
+ )
35
+
36
+
37
+ __all__ = (
38
+ "b64decode",
39
+ "b64decode_as_bytearray",
40
+ "b64encode",
41
+ "b64encode_as_string",
42
+ "encodebytes",
43
+ "standard_b64decode",
44
+ "standard_b64encode",
45
+ "urlsafe_b64decode",
46
+ "urlsafe_b64encode",
47
+ )
48
+
49
+ __version__ = _version
50
+
51
+
52
+ def get_license_text() -> str:
53
+ """Return pybase64 license information as a :class:`str` object.
54
+
55
+ The result includes libbase64 license information as well.
56
+ """
57
+ return _license
58
+
59
+
60
+ def get_version() -> str:
61
+ """Return pybase64 version as a :class:`str` object.
62
+
63
+ The result reports if the C extension is used or not.
64
+ e.g. `1.0.0 (C extension active - AVX2)`
65
+ """
66
+ simd_name = _get_simd_name(_get_simd_path())
67
+ if simd_name != "fallback":
68
+ return f"{__version__} (C extension active - {simd_name})"
69
+ return f"{__version__} (C extension inactive)"
70
+
71
+
72
+ def standard_b64encode(s: Buffer) -> bytes:
73
+ """Encode bytes using the standard Base64 alphabet.
74
+
75
+ Argument ``s`` is a :term:`bytes-like object` to encode.
76
+
77
+ The result is returned as a :class:`bytes` object.
78
+ """
79
+ return b64encode(s)
80
+
81
+
82
+ def standard_b64decode(s: str | Buffer) -> bytes:
83
+ """Decode bytes encoded with the standard Base64 alphabet.
84
+
85
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
86
+ decode.
87
+
88
+ The result is returned as a :class:`bytes` object.
89
+
90
+ A :exc:`binascii.Error` is raised if the input is incorrectly padded.
91
+
92
+ Characters that are not in the standard alphabet are discarded prior
93
+ to the padding check.
94
+ """
95
+ return b64decode(s)
96
+
97
+
98
+ def urlsafe_b64encode(s: Buffer, *, padded: bool = True) -> bytes:
99
+ """Encode bytes using the URL- and filesystem-safe Base64 alphabet.
100
+
101
+ Argument ``s`` is a :term:`bytes-like object` to encode.
102
+
103
+ The result is returned as a :class:`bytes` object.
104
+
105
+ The alphabet uses '-' instead of '+' and '_' instead of '/'.
106
+
107
+ The result can still contain ``=`` if ``padded`` is true (default).
108
+ """
109
+ return b64encode(s, b"-_", padded=padded)
110
+
111
+
112
+ def urlsafe_b64decode(s: str | Buffer, *, padded: bool = False) -> bytes:
113
+ """Decode bytes using the URL- and filesystem-safe Base64 alphabet.
114
+
115
+ Argument ``s`` is a :term:`bytes-like object` or ASCII string to
116
+ decode.
117
+
118
+ The result is returned as a :class:`bytes` object.
119
+
120
+ If ``padded`` is ``False``, padding in the input is not required.
121
+ Otherwise, a :exc:`binascii.Error` is raised if the input is incorrectly padded.
122
+
123
+ Characters that are not in the URL-safe base-64 alphabet, and are not
124
+ a plus '+' or slash '/', are discarded prior to the padding check.
125
+
126
+ The alphabet uses '-' instead of '+' and '_' instead of '/'.
127
+ """
128
+ return b64decode(s, b"-_", padded=padded)
pybase64/__main__.py ADDED
@@ -0,0 +1,318 @@
1
+ from __future__ import annotations
2
+
3
+ __lazy_modules__ = ["base64", "pathlib", "timeit"]
4
+
5
+ import argparse
6
+ import base64
7
+ import sys
8
+ from pathlib import Path
9
+ from timeit import default_timer as timer
10
+
11
+ import pybase64
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Sequence
16
+ from types import ModuleType
17
+ from typing import Any
18
+
19
+
20
+ def bench_one(
21
+ duration: float,
22
+ data: bytes,
23
+ module: ModuleType,
24
+ altchars: bytes | None,
25
+ kwargs: dict[str, bool | bytes],
26
+ ) -> None:
27
+ duration = duration / 2.0
28
+ combination_unsupported = all(
29
+ [
30
+ module is base64,
31
+ "ignorechars" in kwargs or "padded" in kwargs,
32
+ sys.version_info < (3, 15),
33
+ ],
34
+ )
35
+ validate = kwargs["validate"]
36
+ if validate and altchars is None and "ignorechars" not in kwargs and "padded" not in kwargs:
37
+ encbytes = module.encodebytes
38
+ number = 0
39
+ time = timer()
40
+ while True:
41
+ encodedcontent = encbytes(data)
42
+ number += 1
43
+ if timer() - time > duration:
44
+ break
45
+ iter_ = number
46
+ time = timer()
47
+ while iter_ > 0:
48
+ encodedcontent = encbytes(data)
49
+ iter_ -= 1
50
+ time = timer() - time
51
+ print(
52
+ "{:<24s} {:5.0f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
53
+ module.__name__ + "." + encbytes.__name__ + ":",
54
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
55
+ len(data),
56
+ len(encodedcontent),
57
+ ),
58
+ )
59
+
60
+ if validate and "ignorechars" not in kwargs:
61
+ enc = module.b64encode
62
+ if combination_unsupported:
63
+ print("{:<24s} N/A".format(module.__name__ + "." + enc.__name__ + ":"))
64
+ else:
65
+ number = 0
66
+ time = timer()
67
+ while True:
68
+ encodedcontent = enc(data, altchars=altchars)
69
+ number += 1
70
+ if timer() - time > duration:
71
+ break
72
+ iter_ = number
73
+ time = timer()
74
+ while iter_ > 0:
75
+ encodedcontent = enc(data, altchars=altchars)
76
+ iter_ -= 1
77
+ time = timer() - time
78
+ print(
79
+ "{:<24s} {:5.0f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
80
+ module.__name__ + "." + enc.__name__ + ":",
81
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
82
+ len(data),
83
+ len(encodedcontent),
84
+ ),
85
+ )
86
+
87
+ if kwargs.get("ignorechars") == b"\n" or not validate:
88
+ encodedcontent = pybase64.b64encode(data, altchars=altchars, wrapcol=76)
89
+ else:
90
+ encodedcontent = pybase64.b64encode(data, altchars=altchars)
91
+ dec = module.b64decode
92
+ if combination_unsupported:
93
+ print("{:<24s} N/A".format(module.__name__ + "." + dec.__name__ + ":"))
94
+ else:
95
+ number = 0
96
+ time = timer()
97
+ while True:
98
+ decodedcontent = dec(encodedcontent, altchars=altchars, **kwargs)
99
+ number += 1
100
+ if timer() - time > duration:
101
+ break
102
+ iter_ = number
103
+ time = timer()
104
+ while iter_ > 0:
105
+ decodedcontent = dec(encodedcontent, altchars=altchars, **kwargs)
106
+ iter_ -= 1
107
+ time = timer() - time
108
+ print(
109
+ "{:<24s} {:5.0f} MB/s ({:,d} bytes -> {:,d} bytes)".format(
110
+ module.__name__ + "." + dec.__name__ + ":",
111
+ ((number * len(data)) / (1024.0 * 1024.0)) / time,
112
+ len(encodedcontent),
113
+ len(data),
114
+ ),
115
+ )
116
+ assert decodedcontent == data # noqa: S101
117
+
118
+
119
+ def readall(file: str) -> bytes:
120
+ if file == "-":
121
+ return sys.stdin.buffer.read()
122
+ return Path(file).read_bytes()
123
+
124
+
125
+ def writeall(file: str, data: bytes) -> None:
126
+ if file == "-":
127
+ sys.stdout.buffer.write(data)
128
+ else:
129
+ Path(file).write_bytes(data)
130
+
131
+
132
+ def benchmark(*, duration: float, input: str) -> None: # noqa: A002
133
+ print(__package__ + " " + pybase64.get_version())
134
+ data = readall(input)
135
+ for altchars in [None, b"-_"]:
136
+ for validate in [True, False]:
137
+ for ignorechars in [None, b"", b"\n"]:
138
+ for padded in [True, False]:
139
+ # skip redundant combinations
140
+ if altchars is None and validate and padded and ignorechars == b"":
141
+ # same as "altchars is None and validate and padded and ignorechars is None"
142
+ # when altchars is not None, the alphabet translation differs
143
+ continue
144
+ kwargs: dict[str, bool | bytes] = {"validate": validate}
145
+ if ignorechars is not None:
146
+ if not validate:
147
+ continue
148
+ kwargs["ignorechars"] = ignorechars
149
+ if not padded:
150
+ kwargs["padded"] = padded
151
+ title = f"bench: altchars={altchars!r:s}"
152
+ if ignorechars is None:
153
+ title = f"{title}, validate={validate!r:s}"
154
+ else:
155
+ title = f"{title}, ignorechars={ignorechars!r:s}"
156
+ print(f"{title}, padded={padded!r:s}")
157
+ for module in [pybase64, base64]:
158
+ bench_one(duration, data, module, altchars, kwargs)
159
+
160
+
161
+ def encode(*, input: str, altchars: bytes | None, output: str) -> None: # noqa: A002
162
+ data = readall(input)
163
+ data = pybase64.b64encode(data, altchars)
164
+ writeall(output, data)
165
+
166
+
167
+ def decode(*, input: str, altchars: bytes | None, validate: bool, output: str) -> None: # noqa: A002
168
+ data = readall(input)
169
+ data = pybase64.b64decode(data, altchars, validate)
170
+ writeall(output, data)
171
+
172
+
173
+ class LicenseAction(argparse.Action):
174
+ def __init__(
175
+ self,
176
+ option_strings: Sequence[str],
177
+ dest: str,
178
+ license: str | None = None, # noqa: A002
179
+ help: str | None = "show license information and exit", # noqa: A002
180
+ ) -> None:
181
+ super().__init__(
182
+ option_strings=option_strings,
183
+ dest=dest,
184
+ default=argparse.SUPPRESS,
185
+ nargs=0,
186
+ help=help,
187
+ )
188
+ self.license = license
189
+
190
+ def __call__(
191
+ self,
192
+ parser: argparse.ArgumentParser,
193
+ namespace: argparse.Namespace, # noqa: ARG002
194
+ values: str | Sequence[Any] | None, # noqa: ARG002
195
+ option_string: str | None = None, # noqa: ARG002
196
+ ) -> None:
197
+ print(self.license)
198
+ parser.exit()
199
+
200
+
201
+ def check_file(value: str, *, is_input: bool) -> str:
202
+ if value == "-":
203
+ return value
204
+ path = Path(value)
205
+ if is_input:
206
+ return str(path.resolve(strict=True))
207
+ return str(path.parent.resolve(strict=True) / path.name)
208
+
209
+
210
+ def main(argv: Sequence[str] | None = None) -> None:
211
+ # main parser
212
+ parser = argparse.ArgumentParser(
213
+ prog=__package__,
214
+ description=__package__ + " command-line tool.",
215
+ )
216
+ parser.add_argument(
217
+ "-V",
218
+ "--version",
219
+ action="version",
220
+ version=__package__ + " " + pybase64.get_version(),
221
+ )
222
+ parser.add_argument("--license", action=LicenseAction, license=pybase64.get_license_text())
223
+ # create sub-parsers
224
+ subparsers = parser.add_subparsers(help="tool help")
225
+ # benchmark parser
226
+ benchmark_parser = subparsers.add_parser("benchmark", help="-h for usage")
227
+ benchmark_parser.add_argument(
228
+ "-d",
229
+ "--duration",
230
+ metavar="D",
231
+ dest="duration",
232
+ type=float,
233
+ default=1.0,
234
+ help="expected duration for a single encode or decode test",
235
+ )
236
+ benchmark_parser.register("type", "input file", lambda s: check_file(s, is_input=True))
237
+ benchmark_parser.add_argument(
238
+ "input",
239
+ type="input file",
240
+ help="input file used for the benchmark",
241
+ )
242
+ benchmark_parser.set_defaults(func=benchmark)
243
+ # encode parser
244
+ encode_parser = subparsers.add_parser("encode", help="-h for usage")
245
+ encode_parser.register("type", "input file", lambda s: check_file(s, is_input=True))
246
+ encode_parser.register("type", "output file", lambda s: check_file(s, is_input=False))
247
+ encode_parser.add_argument("input", type="input file", help="input file to be encoded")
248
+ group = encode_parser.add_mutually_exclusive_group()
249
+ group.add_argument(
250
+ "-u",
251
+ "--url",
252
+ action="store_const",
253
+ const=b"-_",
254
+ dest="altchars",
255
+ help="use URL encoding",
256
+ )
257
+ group.add_argument(
258
+ "-a",
259
+ "--altchars",
260
+ dest="altchars",
261
+ help="use alternative characters for encoding",
262
+ )
263
+ encode_parser.add_argument(
264
+ "-o",
265
+ "--output",
266
+ dest="output",
267
+ type="output file",
268
+ default="-",
269
+ help="encoded output file (default to stdout)",
270
+ )
271
+ encode_parser.set_defaults(func=encode)
272
+ # decode parser
273
+ decode_parser = subparsers.add_parser("decode", help="-h for usage")
274
+ decode_parser.register("type", "input file", lambda s: check_file(s, is_input=True))
275
+ decode_parser.register("type", "output file", lambda s: check_file(s, is_input=False))
276
+ decode_parser.add_argument("input", type="input file", help="input file to be decoded")
277
+ group = decode_parser.add_mutually_exclusive_group()
278
+ group.add_argument(
279
+ "-u",
280
+ "--url",
281
+ action="store_const",
282
+ const=b"-_",
283
+ dest="altchars",
284
+ help="use URL decoding",
285
+ )
286
+ group.add_argument(
287
+ "-a",
288
+ "--altchars",
289
+ dest="altchars",
290
+ help="use alternative characters for decoding",
291
+ )
292
+ decode_parser.add_argument(
293
+ "-o",
294
+ "--output",
295
+ dest="output",
296
+ type="output file",
297
+ default="-",
298
+ help="decoded output file (default to stdout)",
299
+ )
300
+ decode_parser.add_argument(
301
+ "--no-validation",
302
+ dest="validate",
303
+ action="store_false",
304
+ help="disable validation of the input data",
305
+ )
306
+ decode_parser.set_defaults(func=decode)
307
+ # ready, parse
308
+ if argv is None:
309
+ argv = sys.argv[1:]
310
+ if len(argv) == 0:
311
+ argv = ["-h"]
312
+ args = vars(parser.parse_args(args=argv))
313
+ func = args.pop("func")
314
+ func(**args)
315
+
316
+
317
+ if __name__ == "__main__":
318
+ main()