Skip to content

Commit bf1308f

Browse files
committed
Update PR for #145981
- Use the new `alphabet` parameter in `binascii` - Remove `binascii.a2b_base32hex()` and `binascii.b2a_base32hex()` - Change value for `.. versionadded::` ReST directive in docs for new `binascii` functions to "next" instead of "3.15"
1 parent 0a8e4b1 commit bf1308f

File tree

5 files changed

+213
-344
lines changed

5 files changed

+213
-344
lines changed

Doc/library/binascii.rst

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ The :mod:`!binascii` module defines the following functions:
182182

183183
.. versionadded:: 3.15
184184

185-
.. function:: a2b_base32(string, /)
185+
.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET)
186186

187187
Convert base32 data back to binary and return the binary data.
188188

@@ -193,38 +193,22 @@ The :mod:`!binascii` module defines the following functions:
193193
* Contains no excess data after padding (including excess padding, newlines, etc.).
194194
* Does not start with padding.
195195

196+
Optional *alphabet* must be a :class:`bytes` object of length 32 which
197+
specifies an alternative alphabet.
198+
196199
Invalid base32 data will raise :exc:`binascii.Error`.
197200

198-
.. versionadded:: 3.15
201+
.. versionadded:: next
199202

200-
.. function:: b2a_base32(data, /)
203+
.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET)
201204

202205
Convert binary data to a line(s) of ASCII characters in base32 coding,
203206
as specified in :rfc:`4648`. The return value is the converted line.
204207

205-
.. versionadded:: 3.15
206-
207-
.. function:: a2b_base32hex(string, /)
208-
209-
Convert base32hex data back to binary and return the binary data.
210-
211-
Valid base32hex:
212-
213-
* Conforms to :rfc:`4648`.
214-
* Contains only characters from the base32hex alphabet.
215-
* Contains no excess data after padding (including excess padding, newlines, etc.).
216-
* Does not start with padding.
217-
218-
Invalid base32hex data will raise :exc:`binascii.Error`.
219-
220-
.. versionadded:: 3.15
221-
222-
.. function:: b2a_base32hex(data, /)
223-
224-
Convert binary data to a line(s) of ASCII characters in base32hex coding,
225-
as specified in :rfc:`4648`. The return value is the converted line.
208+
Optional *alphabet* must be a :term:`bytes-like object` of length 32 which
209+
specifies an alternative alphabet.
226210

227-
.. versionadded:: 3.15
211+
.. versionadded:: next
228212

229213
.. function:: a2b_qp(data, header=False)
230214

@@ -370,6 +354,18 @@ The :mod:`!binascii` module defines the following functions:
370354

371355
.. versionadded:: next
372356

357+
.. data:: BASE32_ALPHABET
358+
359+
The base32 alphabet according to :rfc:`4648`.
360+
361+
.. versionadded:: next
362+
363+
.. data:: BASE32HEX_ALPHABET
364+
365+
The "Extended Hex" base32hex alphabet according to :rfc:`4648`.
366+
367+
.. versionadded:: next
368+
373369

374370
.. seealso::
375371

Lib/base64.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,13 @@ def b32decode(s, casefold=False, map01=None):
234234
extra_args=_B32_DECODE_MAP01_DOCSTRING)
235235

236236
def b32hexencode(s):
237-
return binascii.b2a_base32hex(s)
237+
return binascii.b2a_base32(s, alphabet=binascii.BASE32HEX_ALPHABET)
238238
b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex')
239239

240240
def b32hexdecode(s, casefold=False):
241241
# base32hex does not have the 01 mapping
242242
s = _b32decode_prepare(s, casefold)
243-
return binascii.a2b_base32hex(s)
243+
return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET)
244244
b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex',
245245
extra_args='')
246246

Lib/test/test_binascii.py

Lines changed: 25 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111

1212
# Note: "*_hex" functions are aliases for "(un)hexlify"
13-
b2a_functions = ['b2a_ascii85', 'b2a_base32', 'b2a_base32hex', 'b2a_base64', 'b2a_base85',
13+
b2a_functions = ['b2a_ascii85', 'b2a_base32', 'b2a_base64', 'b2a_base85',
1414
'b2a_hex', 'b2a_qp', 'b2a_uu',
1515
'hexlify']
16-
a2b_functions = ['a2b_ascii85', 'a2b_base32', 'a2b_base32hex', 'a2b_base64', 'a2b_base85',
16+
a2b_functions = ['a2b_ascii85', 'a2b_base32', 'a2b_base64', 'a2b_base85',
1717
'a2b_hex', 'a2b_qp', 'a2b_uu',
1818
'unhexlify']
1919
all_functions = a2b_functions + b2a_functions + ['crc32', 'crc_hqx']
@@ -820,155 +820,31 @@ def assertInvalidLength(*args):
820820
assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01")
821821
assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01")
822822

823-
def test_base32hex_valid(self):
824-
# Test base32hex with valid data
825-
lines = []
826-
step = 0
827-
i = 0
828-
while i < len(self.rawdata):
829-
b = self.type2test(self.rawdata[i:i + step])
830-
a = binascii.b2a_base32hex(b)
831-
lines.append(a)
832-
i += step
833-
step += 1
834-
res = bytes()
835-
for line in lines:
836-
a = self.type2test(line)
837-
b = binascii.a2b_base32hex(a)
838-
res += b
839-
self.assertEqual(res, self.rawdata)
840-
841-
def test_base32hex_errors(self):
842-
def _fixPadding(data):
843-
fixed = data.replace(b"=", b"")
844-
len_8 = len(fixed) % 8
845-
p = 8 - len_8 if len_8 else 0
846-
return fixed + b"=" * p
847-
848-
def _assertRegexTemplate(assert_regex, data, good_padding_result=None):
849-
with self.assertRaisesRegex(binascii.Error, assert_regex):
850-
binascii.a2b_base32hex(self.type2test(data))
851-
if good_padding_result:
852-
fixed = self.type2test(_fixPadding(data))
853-
self.assertEqual(binascii.a2b_base32hex(fixed), good_padding_result)
854-
855-
def assertNonBase32HexData(*args):
856-
_assertRegexTemplate(r"(?i)Only base32hex data", *args)
857-
858-
def assertExcessData(*args):
859-
_assertRegexTemplate(r"(?i)Excess data", *args)
860-
861-
def assertExcessPadding(*args):
862-
_assertRegexTemplate(r"(?i)Excess padding", *args)
863-
864-
def assertLeadingPadding(*args):
865-
_assertRegexTemplate(r"(?i)Leading padding", *args)
866-
867-
def assertIncorrectPadding(*args):
868-
_assertRegexTemplate(r"(?i)Incorrect padding", *args)
869-
870-
def assertDiscontinuousPadding(*args):
871-
_assertRegexTemplate(r"(?i)Discontinuous padding", *args)
872-
873-
def assertInvalidLength(*args):
874-
_assertRegexTemplate(r"(?i)Invalid.+number of data characters", *args)
875-
876-
assertNonBase32HexData(b"a")
877-
assertNonBase32HexData(b"AA-")
878-
assertNonBase32HexData(b"ABCDE==!")
879-
assertNonBase32HexData(b"ab:(){:|:&};:==")
880-
881-
assertExcessData(b"AB======C")
882-
assertExcessData(b"AB======CD")
883-
assertExcessData(b"ABCD====E")
884-
assertExcessData(b"ABCDE===FGH")
885-
assertExcessData(b"ABCDEFG=H")
886-
assertExcessData(b"4321====55555555")
887-
888-
assertExcessData(b"BE======EF", b"[\x9c")
889-
assertExcessData(b"BEEF====C", b"[\x9c\xf6")
890-
assertExcessData(b"BEEFC===AK", b"[\x9c\xf6*")
891-
assertExcessData(b"BEEFCAK=E", b"[\x9c\xf6*\x8e")
892-
893-
assertExcessPadding(b"BE=======", b"[")
894-
assertExcessPadding(b"BE========", b"[")
895-
assertExcessPadding(b"BEEF=====", b"[\x9c")
896-
assertExcessPadding(b"BEEF======", b"[\x9c")
897-
assertExcessPadding(b"BEEFC====", b"[\x9c\xf6")
898-
assertExcessPadding(b"BEEFC=====", b"[\x9c\xf6")
899-
assertExcessPadding(b"BEEFCAK==", b"[\x9c\xf6*")
900-
assertExcessPadding(b"BEEFCAK===", b"[\x9c\xf6*")
901-
assertExcessPadding(b"BEEFCAKE=", b"[\x9c\xf6*\x8e")
902-
assertExcessPadding(b"BEEFCAKE==", b"[\x9c\xf6*\x8e")
903-
assertExcessPadding(b"BEEFCAKE===", b"[\x9c\xf6*\x8e")
904-
assertExcessPadding(b"BEEFCAKE====", b"[\x9c\xf6*\x8e")
905-
assertExcessPadding(b"BEEFCAKE=====", b"[\x9c\xf6*\x8e")
906-
assertExcessPadding(b"BEEFCAKE======", b"[\x9c\xf6*\x8e")
907-
assertExcessPadding(b"BEEFCAKE=======", b"[\x9c\xf6*\x8e")
908-
assertExcessPadding(b"BEEFCAKE========", b"[\x9c\xf6*\x8e")
909-
assertExcessPadding(b"BEEFCAKE=========", b"[\x9c\xf6*\x8e")
910-
911-
assertLeadingPadding(b"=", b"")
912-
assertLeadingPadding(b"==", b"")
913-
assertLeadingPadding(b"===", b"")
914-
assertLeadingPadding(b"====", b"")
915-
assertLeadingPadding(b"=====", b"")
916-
assertLeadingPadding(b"======", b"")
917-
assertLeadingPadding(b"=======", b"")
918-
assertLeadingPadding(b"========", b"")
919-
assertLeadingPadding(b"=========", b"")
920-
assertLeadingPadding(b"=BEEFCAKE", b"[\x9c\xf6*\x8e")
921-
assertLeadingPadding(b"==BEEFCAKE", b"[\x9c\xf6*\x8e")
922-
assertLeadingPadding(b"===BEEFCAKE", b"[\x9c\xf6*\x8e")
923-
assertLeadingPadding(b"====BEEFCAKE", b"[\x9c\xf6*\x8e")
924-
assertLeadingPadding(b"=====BEEFCAKE", b"[\x9c\xf6*\x8e")
925-
assertLeadingPadding(b"======BEEFCAKE", b"[\x9c\xf6*\x8e")
926-
assertLeadingPadding(b"=======BEEFCAKE", b"[\x9c\xf6*\x8e")
927-
assertLeadingPadding(b"========BEEFCAKE", b"[\x9c\xf6*\x8e")
928-
assertLeadingPadding(b"=========BEEFCAKE", b"[\x9c\xf6*\x8e")
929-
930-
assertIncorrectPadding(b"A")
931-
assertIncorrectPadding(b"AB")
932-
assertIncorrectPadding(b"ABC")
933-
assertIncorrectPadding(b"ABCD")
934-
assertIncorrectPadding(b"ABCDE")
935-
assertIncorrectPadding(b"ABCDEF")
936-
assertIncorrectPadding(b"ABCDEFG")
937-
938-
assertIncorrectPadding(b"BE=", b"[")
939-
assertIncorrectPadding(b"BE==", b"[")
940-
assertIncorrectPadding(b"BE===", b"[")
941-
assertIncorrectPadding(b"BE====", b"[")
942-
assertIncorrectPadding(b"BE=====", b"[")
943-
assertIncorrectPadding(b"BEEF=", b"[\x9c")
944-
assertIncorrectPadding(b"BEEF==", b"[\x9c")
945-
assertIncorrectPadding(b"BEEF===", b"[\x9c")
946-
assertIncorrectPadding(b"BEEFC=", b"[\x9c\xf6")
947-
assertIncorrectPadding(b"BEEFC==", b"[\x9c\xf6")
948-
949-
assertDiscontinuousPadding(b"BE=EF===", b"[\x9c")
950-
assertDiscontinuousPadding(b"BE==EF==", b"[\x9c")
951-
assertDiscontinuousPadding(b"BEEF=C==", b"[\x9c\xf6")
952-
assertDiscontinuousPadding(b"BEEFC=AK", b"[\x9c\xf6*")
823+
def test_base32_alphabet(self):
824+
alphabet = b'0Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9JjKk'
825+
data = self.type2test(self.rawdata)
826+
encoded = binascii.b2a_base32(data, alphabet=alphabet)
827+
trans = bytes.maketrans(binascii.BASE32_ALPHABET, alphabet)
828+
expected = binascii.b2a_base32(data).translate(trans)
829+
self.assertEqual(encoded, expected)
830+
self.assertEqual(binascii.a2b_base32(encoded, alphabet=alphabet), self.rawdata)
831+
self.assertEqual(binascii.b2a_base32(data, alphabet=self.type2test(alphabet)), expected)
953832

954-
assertInvalidLength(b"A=")
955-
assertInvalidLength(b"A==")
956-
assertInvalidLength(b"A===")
957-
assertInvalidLength(b"A====")
958-
assertInvalidLength(b"A=====")
959-
assertInvalidLength(b"A======")
960-
assertInvalidLength(b"ABC=")
961-
assertInvalidLength(b"ABC==")
962-
assertInvalidLength(b"ABC===")
963-
assertInvalidLength(b"ABC====")
964-
assertInvalidLength(b"ABCDEF=")
833+
data = self.type2test(b'')
834+
self.assertEqual(binascii.b2a_base32(data, alphabet=alphabet), b'')
835+
self.assertEqual(binascii.a2b_base32(data, alphabet=alphabet), b'')
965836

966-
assertInvalidLength(b"B=E=====", b"[")
967-
assertInvalidLength(b"B==E====", b"[")
968-
assertInvalidLength(b"BEE=F===", b"[\x9c")
969-
assertInvalidLength(b"BEE==F==", b"[\x9c")
970-
assertInvalidLength(b"BEEFCA=K", b"[\x9c\xf6*")
971-
assertInvalidLength(b"BEEFCA=====K", b"[\x9c\xf6*")
837+
for func in binascii.b2a_base32, binascii.a2b_base32:
838+
with self.assertRaises(TypeError):
839+
func(data, alphabet=None)
840+
with self.assertRaises(TypeError):
841+
func(data, alphabet=alphabet.decode())
842+
with self.assertRaises(ValueError):
843+
func(data, alphabet=alphabet[:-1])
844+
with self.assertRaises(ValueError):
845+
func(data, alphabet=alphabet+b'?')
846+
with self.assertRaises(TypeError):
847+
binascii.a2b_base32(data, alphabet=bytearray(alphabet))
972848

973849
def test_uu(self):
974850
MAX_UU = 45

0 commit comments

Comments
 (0)