Accepting the ``+`` and ``/`` characters is now deprecated.
-.. function:: b32encode(s)
+.. function:: b32encode(s, *, wrapcol=0)
Encode the :term:`bytes-like object` *s* using Base32 and return the
encoded :class:`bytes`.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not add any newlines.
+
+ .. versionchanged:: next
+ Added the *wrapcol* parameter.
+
-.. function:: b32decode(s, casefold=False, map01=None)
+.. function:: b32decode(s, casefold=False, map01=None, *, ignorechars=b'')
Decode the Base32 encoded :term:`bytes-like object` or ASCII string *s* and
return the decoded :class:`bytes`.
digit 0 is always mapped to the letter O). For security purposes the default is
``None``, so that 0 and 1 are not allowed in the input.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
A :exc:`binascii.Error` is raised if *s* is
incorrectly padded or if there are non-alphabet characters present in the
input.
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
-.. function:: b32hexencode(s)
+.. function:: b32hexencode(s, *, wrapcol=0)
Similar to :func:`b32encode` but uses the Extended Hex Alphabet, as defined in
:rfc:`4648`.
.. versionadded:: 3.10
+ .. versionchanged:: next
+ Added the *wrapcol* parameter.
+
-.. function:: b32hexdecode(s, casefold=False)
+.. function:: b32hexdecode(s, casefold=False, *, ignorechars=b'')
Similar to :func:`b32decode` but uses the Extended Hex Alphabet, as defined in
:rfc:`4648`.
.. versionadded:: 3.10
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
-.. function:: b16encode(s)
+.. function:: b16encode(s, *, wrapcol=0)
Encode the :term:`bytes-like object` *s* using Base16 and return the
encoded :class:`bytes`.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not add any newlines.
+
+ .. versionchanged:: next
+ Added the *wrapcol* parameter.
-.. function:: b16decode(s, casefold=False)
+
+.. function:: b16decode(s, casefold=False, *, ignorechars=b'')
Decode the Base16 encoded :term:`bytes-like object` or ASCII string *s* and
return the decoded :class:`bytes`.
lowercase alphabet is acceptable as input. For security purposes, the default
is ``False``.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
A :exc:`binascii.Error` is raised if *s* is
incorrectly padded or if there are non-alphabet characters present in the
input.
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
+
.. _base64-base-85:
Base85 Encodings
.. versionadded:: 3.4
-.. function:: b85encode(b, pad=False)
+.. function:: b85encode(b, pad=False, *, wrapcol=0)
Encode the :term:`bytes-like object` *b* using base85 (as used in e.g.
git-style binary diffs) and return the encoded :class:`bytes`.
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
multiple of 4 bytes before encoding.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not add any newlines.
+
.. versionadded:: 3.4
+ .. versionchanged:: next
+ Added the *wrapcol* parameter.
-.. function:: b85decode(b)
+
+.. function:: b85decode(b, *, ignorechars=b'')
Decode the base85-encoded :term:`bytes-like object` or ASCII string *b* and
return the decoded :class:`bytes`. Padding is implicitly removed, if
necessary.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
.. versionadded:: 3.4
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
-.. function:: z85encode(s, pad=False)
+.. function:: z85encode(s, pad=False, *, wrapcol=0)
Encode the :term:`bytes-like object` *s* using Z85 (as used in ZeroMQ)
and return the encoded :class:`bytes`. See `Z85 specification
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
multiple of 4 bytes before encoding.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not add any newlines.
+
.. versionadded:: 3.13
.. versionchanged:: 3.15
The *pad* parameter was added.
+ .. versionchanged:: next
+ Added the *wrapcol* parameter.
+
-.. function:: z85decode(s)
+.. function:: z85decode(s, *, ignorechars=b'')
Decode the Z85-encoded :term:`bytes-like object` or ASCII string *s* and
return the decoded :class:`bytes`. See `Z85 specification
<https://rfc.zeromq.org/spec/32/>`_ for more information.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
.. versionadded:: 3.13
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
.. _base64-legacy:
Added the *alphabet* and *wrapcol* parameters.
-.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b"")
+.. function:: a2b_ascii85(string, /, *, foldspaces=False, adobe=False, ignorechars=b'')
Convert Ascii85 data back to binary and return the binary data.
.. versionadded:: 3.15
-.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET)
+.. function:: a2b_base85(string, /, *, alphabet=BASE85_ALPHABET, ignorechars=b'')
Convert Base85 data back to binary and return the binary data.
More than one line may be passed at a time.
Optional *alphabet* must be a :class:`bytes` object of length 85 which
specifies an alternative alphabet.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
Invalid Base85 data will raise :exc:`binascii.Error`.
.. versionadded:: 3.15
-.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, pad=False)
+.. function:: b2a_base85(data, /, *, alphabet=BASE85_ALPHABET, wrapcol=0, pad=False)
Convert binary data to a line of ASCII characters in Base85 coding.
The return value is the converted line.
Optional *alphabet* must be a :term:`bytes-like object` of length 85 which
specifies an alternative alphabet.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not insert any newlines.
+
If *pad* is true, the input is padded with ``b'\0'`` so its length is a
multiple of 4 bytes before encoding.
.. versionadded:: 3.15
-.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET)
+.. function:: a2b_base32(string, /, *, alphabet=BASE32_ALPHABET, ignorechars=b'')
Convert base32 data back to binary and return the binary data.
Optional *alphabet* must be a :class:`bytes` object of length 32 which
specifies an alternative alphabet.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+ If *ignorechars* contains the pad character ``'='``, the pad characters
+ presented before the end of the encoded data and the excess pad characters
+ will be ignored.
+
Invalid base32 data will raise :exc:`binascii.Error`.
.. versionadded:: next
-.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET)
+.. function:: b2a_base32(data, /, *, alphabet=BASE32_ALPHABET, wrapcol=0)
Convert binary data to a line of ASCII characters in base32 coding,
as specified in :rfc:`4648`. The return value is the converted line.
Optional *alphabet* must be a :term:`bytes-like object` of length 32 which
specifies an alternative alphabet.
+ If *wrapcol* is non-zero, insert a newline (``b'\n'``) character
+ after at most every *wrapcol* characters.
+ If *wrapcol* is zero (default), do not insert any newlines.
+
.. versionadded:: next
.. function:: a2b_qp(data, header=False)
.. versionchanged:: 3.8
The *sep* and *bytes_per_sep* parameters were added.
-.. function:: a2b_hex(hexstr)
- unhexlify(hexstr)
+.. function:: a2b_hex(hexstr, *, ignorechars=b'')
+ unhexlify(hexstr, *, ignorechars=b'')
Return the binary data represented by the hexadecimal string *hexstr*. This
function is the inverse of :func:`b2a_hex`. *hexstr* must contain an even number
of hexadecimal digits (which can be upper or lower case), otherwise an
:exc:`Error` exception is raised.
+ *ignorechars* should be a :term:`bytes-like object` containing characters
+ to ignore from the input.
+
Similar functionality (accepting only text string arguments, but more
liberal towards whitespace) is also accessible using the
:meth:`bytes.fromhex` class method.
+ .. versionchanged:: next
+ Added the *ignorechars* parameter.
+
+
.. exception:: Error
Exception raised on errors. These are usually programming errors.
* Added the *pad* parameter in :func:`~base64.z85encode`.
(Contributed by Hauke Dämpfling in :gh:`143103`.)
-* Added the *wrapcol* parameter in :func:`~base64.b64encode`.
- (Contributed by Serhiy Storchaka in :gh:`143214`.)
+* Added the *wrapcol* parameter in :func:`~base64.b16encode`,
+ :func:`~base64.b32encode`, :func:`~base64.b32hexencode`,
+ :func:`~base64.b64encode`, :func:`~base64.b85encode`, and
+ :func:`~base64.z85encode`.
+ (Contributed by Serhiy Storchaka in :gh:`143214` and :gh:`146431`.)
-* Added the *ignorechars* parameter in :func:`~base64.b64decode`.
- (Contributed by Serhiy Storchaka in :gh:`144001`.)
+* Added the *ignorechars* parameter in :func:`~base64.b16decode`,
+ :func:`~base64.b32decode`, :func:`~base64.b32hexdecode`,
+ :func:`~base64.b64decode`, :func:`~base64.b85decode`, and
+ :func:`~base64.z85decode`.
+ (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.)
binascii
--------
+* Added functions for Base32 encoding:
+
+ - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32`
+
+ (Contributed by James Seo in :gh:`146192`.)
+
* Added functions for Ascii85, Base85, and Z85 encoding:
- :func:`~binascii.b2a_ascii85` and :func:`~binascii.a2b_ascii85`
:func:`~binascii.a2b_base64`.
(Contributed by Serhiy Storchaka in :gh:`145980`.)
-* Added the *ignorechars* parameter in :func:`~binascii.a2b_base64`.
- (Contributed by Serhiy Storchaka in :gh:`144001`.)
-
-* Added functions for Base32 encoding:
-
- - :func:`~binascii.b2a_base32` and :func:`~binascii.a2b_base32`
-
- (Contributed by James Seo in :gh:`146192`.)
+* Added the *ignorechars* parameter in :func:`~binascii.a2b_hex`,
+ :func:`~binascii.unhexlify`, and :func:`~binascii.a2b_base64`.
+ (Contributed by Serhiy Storchaka in :gh:`144001` and :gh:`146431`.)
calendar
# Base32 encoding/decoding must be done in Python
_B32_ENCODE_DOCSTRING = '''
Encode the bytes-like objects using {encoding} and return a bytes object.
+
+If wrapcol is non-zero, insert a newline (b'\\n') character after at most
+every wrapcol characters.
'''
_B32_DECODE_DOCSTRING = '''
Decode the {encoding} encoded bytes-like object or ASCII string s.
Optional casefold is a flag specifying whether a lowercase alphabet is
acceptable as input. For security purposes, the default is False.
+
+ignorechars should be a byte string containing characters to ignore
+from the input.
{extra_args}
The result is returned as a bytes object. A binascii.Error is raised if
the input is incorrectly padded or if there are non-alphabet
0 and 1 are not allowed in the input.
'''
-def b32encode(s):
- return binascii.b2a_base32(s)
+def b32encode(s, *, wrapcol=0):
+ return binascii.b2a_base32(s, wrapcol=wrapcol)
b32encode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32')
-def b32decode(s, casefold=False, map01=None):
+def b32decode(s, casefold=False, map01=None, *, ignorechars=b''):
s = _bytes_from_decode_data(s)
# Handle section 2.4 zero and one mapping. The flag map01 will be either
# False, or the character to map the digit 1 (one) to. It should be
s = s.translate(bytes.maketrans(b'01', b'O' + map01))
if casefold:
s = s.upper()
- return binascii.a2b_base32(s)
+ return binascii.a2b_base32(s, ignorechars=ignorechars)
b32decode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32',
extra_args=_B32_DECODE_MAP01_DOCSTRING)
-def b32hexencode(s):
- return binascii.b2a_base32(s, alphabet=binascii.BASE32HEX_ALPHABET)
+def b32hexencode(s, *, wrapcol=0):
+ return binascii.b2a_base32(s, wrapcol=wrapcol,
+ alphabet=binascii.BASE32HEX_ALPHABET)
b32hexencode.__doc__ = _B32_ENCODE_DOCSTRING.format(encoding='base32hex')
-def b32hexdecode(s, casefold=False):
+def b32hexdecode(s, casefold=False, *, ignorechars=b''):
s = _bytes_from_decode_data(s)
# base32hex does not have the 01 mapping
if casefold:
s = s.upper()
- return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET)
+ return binascii.a2b_base32(s, alphabet=binascii.BASE32HEX_ALPHABET,
+ ignorechars=ignorechars)
b32hexdecode.__doc__ = _B32_DECODE_DOCSTRING.format(encoding='base32hex',
extra_args='')
# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
# lowercase. The RFC also recommends against accepting input case
# insensitively.
-def b16encode(s):
+def b16encode(s, *, wrapcol=0):
"""Encode the bytes-like object s using Base16 and return a bytes object.
+
+ If wrapcol is non-zero, insert a newline (b'\\n') character after at most
+ every wrapcol characters.
"""
- return binascii.hexlify(s).upper()
+ if not wrapcol:
+ return binascii.hexlify(s).upper()
+ if wrapcol < 0:
+ raise ValueError('Negative wrapcol')
+ if wrapcol < 2:
+ wrapcol = 2
+ return binascii.hexlify(s, bytes_per_sep=-(wrapcol//2), sep=b'\n').upper()
-def b16decode(s, casefold=False):
+def b16decode(s, casefold=False, *, ignorechars=b''):
"""Decode the Base16 encoded bytes-like object or ASCII string s.
Optional casefold is a flag specifying whether a lowercase alphabet is
acceptable as input. For security purposes, the default is False.
+ ignorechars should be a byte string containing characters to ignore
+ from the input.
+
The result is returned as a bytes object. A binascii.Error is raised if
s is incorrectly padded or if there are non-alphabet characters present
in the input.
"""
- s = _bytes_from_decode_data(s)
- if casefold:
- s = s.upper()
- if s.translate(None, delete=b'0123456789ABCDEF'):
- raise binascii.Error('Non-base16 digit found')
- return binascii.unhexlify(s)
+ if not casefold:
+ s = _bytes_from_decode_data(s)
+ if not isinstance(ignorechars, bytes):
+ ignorechars = bytes(memoryview(ignorechars))
+ for b in b'abcdef':
+ if b in s and b not in ignorechars:
+ raise binascii.Error('Non-base16 digit found')
+ s = s.translate(None, delete=b'abcdef')
+ return binascii.unhexlify(s, ignorechars=ignorechars)
#
# Ascii85 encoding/decoding
return binascii.a2b_ascii85(b, foldspaces=foldspaces,
adobe=adobe, ignorechars=ignorechars)
-def b85encode(b, pad=False):
+def b85encode(b, pad=False, *, wrapcol=0):
"""Encode bytes-like object b in base85 format and return a bytes object.
+ If wrapcol is non-zero, insert a newline (b'\\n') character after at most
+ every wrapcol characters.
+
If pad is true, the input is padded with b'\\0' so its length is a multiple of
4 bytes before encoding.
"""
- return binascii.b2a_base85(b, pad=pad)
+ return binascii.b2a_base85(b, wrapcol=wrapcol, pad=pad)
-def b85decode(b):
+def b85decode(b, *, ignorechars=b''):\r
"""Decode the base85-encoded bytes-like object or ASCII string b
The result is returned as a bytes object.
"""
- return binascii.a2b_base85(b)
+ return binascii.a2b_base85(b, ignorechars=ignorechars)
+
+def z85encode(s, pad=False, *, wrapcol=0):
+ """Encode bytes-like object b in z85 format and return a bytes object.
-def z85encode(s, pad=False):
- """Encode bytes-like object b in z85 format and return a bytes object."""
- return binascii.b2a_base85(s, pad=pad, alphabet=binascii.Z85_ALPHABET)
+ If wrapcol is non-zero, insert a newline (b'\\n') character after at most
+ every wrapcol characters.
+
+ If pad is true, the input is padded with b'\\0' so its length is a multiple of
+ 4 bytes before encoding.
+ """
+ return binascii.b2a_base85(s, wrapcol=wrapcol, pad=pad,
+ alphabet=binascii.Z85_ALPHABET)
-def z85decode(s):
+def z85decode(s, *, ignorechars=b''):\r
"""Decode the z85-encoded bytes-like object or ASCII string b
The result is returned as a bytes object.
"""
- return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET)
+ return binascii.a2b_base85(s, alphabet=binascii.Z85_ALPHABET, ignorechars=ignorechars)
# Legacy interface. This code could be cleaned up since I don't believe
# binascii has any line length limitations. It just doesn't seem worth it
b'\xd3V\xbeo\xf7\x1d', b'01a-b_cd')
self.check_encode_type_errors(base64.urlsafe_b64encode)
- def test_b64encode_wrapcol(self):
+ def _common_test_wrapcol(self, func, data):
eq = self.assertEqual
- b = b'www.python.org'
- eq(base64.b64encode(b, wrapcol=0), b'd3d3LnB5dGhvbi5vcmc=')
- eq(base64.b64encode(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=')
- eq(base64.b64encode(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=')
- eq(base64.b64encode(b, wrapcol=76), b'd3d3LnB5dGhvbi5vcmc=')
- eq(base64.b64encode(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=')
- eq(base64.b64encode(b, wrapcol=sys.maxsize), b'd3d3LnB5dGhvbi5vcmc=')
+ expected = func(data)
+ eq(func(data, wrapcol=0), expected)
+ eq(func(data, wrapcol=80), expected)
+ eq(func(b'', wrapcol=0), func(b''))
+ eq(func(b'', wrapcol=1), func(b''))
+ if func is not base64.b16encode:
+ eq(func(data, wrapcol=sys.maxsize), expected)
if check_impl_detail():
- eq(base64.b64encode(b, wrapcol=sys.maxsize*2),
- b'd3d3LnB5dGhvbi5vcmc=')
+ if func is not base64.b16encode:
+ eq(func(data, wrapcol=sys.maxsize*2), expected)
with self.assertRaises(OverflowError):
- base64.b64encode(b, wrapcol=2**1000)
+ func(data, wrapcol=2**1000)
with self.assertRaises(ValueError):
- base64.b64encode(b, wrapcol=-8)
- with self.assertRaises(TypeError):
- base64.b64encode(b, wrapcol=8.0)
+ func(data, wrapcol=-80)
with self.assertRaises(TypeError):
- base64.b64encode(b, wrapcol='8')
+ func(data, wrapcol=80.0)
with self.assertRaises(TypeError):
- base64.b64encode(b, wrapcol=None)
- eq(base64.b64encode(b'', wrapcol=0), b'')
- eq(base64.b64encode(b'', wrapcol=8), b'')
+ func(data, wrapcol='80')
+ if func is not base64.b16encode:
+ with self.assertRaises(TypeError):
+ func(data, wrapcol=None)
+
+ def test_b64encode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'www.python.org'
+ self._common_test_wrapcol(base64.b64encode, b)
+ eq(base64.b64encode(b, wrapcol=8), b'd3d3LnB5\ndGhvbi5v\ncmc=')
+ eq(base64.b64encode(b, wrapcol=11), b'd3d3LnB5\ndGhvbi5v\ncmc=')
+ eq(base64.b64encode(b, wrapcol=1), b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=')
def test_b64decode(self):
eq = self.assertEqual
self.assertRaises(binascii.Error, base64.b64decode, b'abc')
self.assertRaises(binascii.Error, base64.b64decode, 'abc')
+ def _common_test_ignorechars(self, func):
+ eq = self.assertEqual
+ eq(func(b'', ignorechars=b' \n'), b'')
+ eq(func(b'', ignorechars=b''), b'')
+ eq(func(b' \n', ignorechars=b' \n'), b'')
+ with self.assertRaises(binascii.Error):
+ func(b' \n', ignorechars=b'')
+ with self.assertRaises(binascii.Error):
+ func(b' \n', ignorechars=b' ')
+ with self.assertRaises(binascii.Error):
+ func(b' \n', ignorechars=b'\n')
+ with self.assertRaises(TypeError):
+ func(b'', ignorechars='')
+ with self.assertRaises(TypeError):
+ func(b'', ignorechars=[])
+ with self.assertRaises(TypeError):
+ func(b'', ignorechars=None)
+
def test_b64decode_invalid_chars(self):
# issue 1466065: Test some invalid characters.
tests = ((b'%3d==', b'\xdd', b'%$'),
r = base64.b64decode(bstr, ignorechars=ignorechars)
self.assertEqual(r, res)
- with self.assertRaises(TypeError):
- base64.b64decode(b'', ignorechars='')
- with self.assertRaises(TypeError):
- base64.b64decode(b'', ignorechars=[])
- with self.assertRaises(TypeError):
- base64.b64decode(b'', ignorechars=None)
+ self._common_test_ignorechars(base64.b64decode)
# Normal alphabet characters will be discarded when alternative given
discarded = ("invalid character %a in Base64 data with %s "
self.check_other_types(base64.b32encode, b'abcd', b'MFRGGZA=')
self.check_encode_type_errors(base64.b32encode)
+ def test_b32encode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'www.python.org'
+ self._common_test_wrapcol(base64.b32encode, b)
+ eq(base64.b32encode(b, wrapcol=16), b'O53XOLTQPF2GQ33O\nFZXXEZY=')
+ eq(base64.b32encode(b, wrapcol=23), b'O53XOLTQPF2GQ33O\nFZXXEZY=')
+ eq(base64.b32encode(b, wrapcol=1), b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=')
+
def test_b32decode(self):
eq = self.assertEqual
tests = {b'': b'',
for data, res in tests.items():
eq(base64.b32decode(data, True), res)
+ eq(base64.b32decode(data, casefold=True), res)
eq(base64.b32decode(data.decode('ascii'), True), res)
self.assertRaises(binascii.Error, base64.b32decode, b'me======')
eq(base64.b32decode(b'M%c023456' % map01, map01=map01), res)
eq(base64.b32decode(b'M%cO23456' % map01, map01=map01), res)
+ def test_b32decode_ignorechars(self):
+ self._common_test_ignorechars(base64.b32decode)
+ eq = self.assertEqual
+ eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde')
+ eq(base64.b32decode(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde')
+ eq(base64.b32decode(b'M=======FRGGZDF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MF======RGGZDF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFR=====GGZDF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRG====GZDF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRGG===ZDF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRGGZ==DF', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRGGZD=F', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRGGZDF=', ignorechars=b'='), b'abcde')
+ eq(base64.b32decode(b'MFRA======', ignorechars=b'='), b'ab')
+
+ eq(base64.b32decode(b'mfRggzDfmzTQ====', ignorechars=b'mfgz'),
+ b'\x88\xe7')
+ eq(base64.b32decode(b'mfRggzDfmzTQ====', casefold=True, ignorechars=b'mfgz'),
+ b'abcdefg')
+ eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', ignorechars=b'01'), b'abcde')
+ eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'L', ignorechars=b'01'),
+ b'c\x8a\xb8\xb8\xcb3\xb2\xb1\xb8\xab')
+ eq(base64.b32decode(b'M0F1R0G1G0Z1D0F1', map01=b'I', ignorechars=b'01'),
+ b'c\x8a\x88\xb8\xc83\xb2\x81\xb8\xa8')
+
def test_b32decode_error(self):
tests = [b'abc', b'ABCDEF==', b'==ABCDEF']
prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
self.check_other_types(base64.b32hexencode, b'abcd', b'C5H66P0=')
self.check_encode_type_errors(base64.b32hexencode)
+ def test_b32hexencode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'www.python.org'
+ self._common_test_wrapcol(base64.b32hexencode, b)
+ eq(base64.b32hexencode(b, wrapcol=16), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=')
+ eq(base64.b32hexencode(b, wrapcol=23), b'ETRNEBJGF5Q6GRRE\n5PNN4PO=')
+ eq(base64.b32hexencode(b, wrapcol=1), b'ETRNEBJG\nF5Q6GRRE\n5PNN4PO=')
+
def test_b32hexdecode(self):
test_cases = [
# to_decode, expected, casefold
self.check_other_types(base64.b32hexdecode, b'C5H66===', b'abc')
self.check_decode_type_errors(base64.b32hexdecode)
+ def test_b32hexdecode_ignorechars(self):
+ self._common_test_ignorechars(base64.b32hexdecode)
+ eq = self.assertEqual
+ eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=b' \n'), b'abcde')
+ eq(base64.b32hexdecode(b'C5H6\n 6P35\n', ignorechars=bytearray(b' \n')), b'abcde')
+ eq(base64.b32hexdecode(b'========C5H66P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C=======5H66P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5======H66P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H=====66P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H6====6P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H66===P35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H66P==35', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H66P3=5', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H66P35=', ignorechars=b'='), b'abcde')
+ eq(base64.b32hexdecode(b'C5H0======', ignorechars=b'='), b'ab')
+
+ eq(base64.b32hexdecode(b'c5h66p35cpjmg===', ignorechars=b'cghjmp'),
+ b')\x8c2')
+ eq(base64.b32hexdecode(b'c5h66p35cpjmg===', casefold=True,
+ ignorechars=b'cghjmp'),
+ b'abcdefgh')
+
def test_b32hexdecode_error(self):
tests = [b'abc', b'ABCDEF==', b'==ABCDEF', b'c4======']
prefixes = [b'M', b'ME', b'MFRA', b'MFRGG', b'MFRGGZA', b'MFRGGZDF']
b'0102ABCDEF')
self.check_encode_type_errors(base64.b16encode)
+ def test_b16encode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'\x01\x02\xab\xcd\xef'
+ self._common_test_wrapcol(base64.b16encode, b)
+ eq(base64.b16encode(b, wrapcol=4), b'0102\nABCD\nEF')
+ eq(base64.b16encode(b, wrapcol=5), b'0102\nABCD\nEF')
+ eq(base64.b16encode(b, wrapcol=1), b'01\n02\nAB\nCD\nEF')
+
def test_b16decode(self):
eq = self.assertEqual
eq(base64.b16decode(b'0102ABCDEF'), b'\x01\x02\xab\xcd\xef')
# Incorrect "padding"
self.assertRaises(binascii.Error, base64.b16decode, '010')
+ def test_b16decode_ignorechars(self):
+ self._common_test_ignorechars(base64.b16decode)
+ eq = self.assertEqual
+ eq(base64.b16decode(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd')
+ eq(base64.b16decode(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd')
+ eq(base64.b16decode(b'aBcD', ignorechars=b'ac'), b'\xbd')
+ eq(base64.b16decode(b'aBcD', casefold=True, ignorechars=b'ac'), b'\xab\xcd')
+
@hypothesis.given(
payload=hypothesis.strategies.binary(),
casefold=hypothesis.strategies.booleans())
def test_a85encode_wrapcol(self):
eq = self.assertEqual
b = b'www.python.org'
- eq(base64.a85encode(b, wrapcol=0), b'GB\\6`E-ZP=Df.1GEb>')
+ self._common_test_wrapcol(base64.a85encode, b)
eq(base64.a85encode(b, wrapcol=7), b'GB\\6`E-\nZP=Df.1\nGEb>')
eq(base64.a85encode(b"\0\0\0\0www.python.org", wrapcol=7),
b'zGB\\6`E\n-ZP=Df.\n1GEb>')
b'G\nB\n\\\n6\n`\nE\n-\nZ\nP\n=\nD\nf\n.\n1\nG\nE\nb\n>')
eq(base64.a85encode(b, wrapcol=1, adobe=True),
b'<~\nGB\n\\6\n`E\n-Z\nP=\nDf\n.1\nGE\nb>\n~>')
- eq(base64.a85encode(b, wrapcol=sys.maxsize), b'GB\\6`E-ZP=Df.1GEb>')
- if check_impl_detail():
- eq(base64.a85encode(b, wrapcol=sys.maxsize*2),
- b'GB\\6`E-ZP=Df.1GEb>')
- with self.assertRaises(OverflowError):
- base64.a85encode(b, wrapcol=2**1000)
- with self.assertRaises(ValueError):
- base64.a85encode(b, wrapcol=-7)
with self.assertRaises(ValueError):
base64.a85encode(b, wrapcol=-7, adobe=True)
- with self.assertRaises(TypeError):
- base64.a85encode(b, wrapcol=7.0)
- with self.assertRaises(TypeError):
- base64.a85encode(b, wrapcol='7')
- with self.assertRaises(TypeError):
- base64.a85encode(b, wrapcol=None)
- eq(base64.a85encode(b'', wrapcol=0), b'')
- eq(base64.a85encode(b'', wrapcol=7), b'')
eq(base64.a85encode(b'', wrapcol=1, adobe=True), b'<~\n~>')
eq(base64.a85encode(b'', wrapcol=3, adobe=True), b'<~\n~>')
eq(base64.a85encode(b'', wrapcol=4, adobe=True), b'<~~>')
self.check_other_types(base64.b85encode, b"www.python.org",
b'cXxL#aCvlSZ*DGca%T')
+ def test_b85encode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'www.python.org'
+ self._common_test_wrapcol(base64.b85encode, b)
+ eq(base64.b85encode(b, wrapcol=10), b'cXxL#aCvlS\nZ*DGca%T')
+ eq(base64.b85encode(b, wrapcol=14), b'cXxL#aCvlS\nZ*DGca%T')
+ eq(base64.b85encode(b, wrapcol=1), b'cXxL#\naCvlS\nZ*DGc\na%T')
+
def test_z85encode(self):
eq = self.assertEqual
self.check_other_types(base64.z85encode, b"www.python.org",
b'CxXl-AcVLsz/dgCA+t')
+ def test_z85encode_wrapcol(self):
+ eq = self.assertEqual
+ b = b'www.python.org'
+ self._common_test_wrapcol(base64.z85encode, b)
+ eq(base64.z85encode(b, wrapcol=10), b'CxXl-AcVLs\nz/dgCA+t')
+ eq(base64.z85encode(b, wrapcol=14), b'CxXl-AcVLs\nz/dgCA+t')
+ eq(base64.z85encode(b, wrapcol=1), b'CxXl-\nAcVLs\nz/dgC\nA+t')
+
def test_a85decode(self):
eq = self.assertEqual
self.assertEqual(base64.a85decode(b"a b\nc", ignorechars=b" \n"),
b'\xc9\x89')
- with self.assertRaises(ValueError):
- base64.a85decode(b"a b\nc", ignorechars=b"")
- with self.assertRaises(ValueError):
- base64.a85decode(b"a b\nc", ignorechars=b" ")
- with self.assertRaises(ValueError):
- base64.a85decode(b"a b\nc", ignorechars=b"\n")
- with self.assertRaises(TypeError):
- base64.a85decode(b"a b\nc", ignorechars=" \n")
- with self.assertRaises(TypeError):
- base64.a85decode(b"a b\nc", ignorechars=None)
+ self._common_test_ignorechars(base64.a85decode)
def test_b85decode_errors(self):
illegal = list(range(33)) + \
list(b'"\',./:[\\]') + \
list(range(128, 256))
for c in illegal:
- with self.assertRaises(ValueError, msg=bytes([c])):
- base64.b85decode(b'0000' + bytes([c]))
+ b = bytes([c])
+ with self.assertRaises(ValueError, msg=b):
+ base64.b85decode(b'0000' + b)
+ self.assertEqual(base64.b85decode(b'0000' + b, ignorechars=b),
+ b'\x00\x00\x00')
+
+ self._common_test_ignorechars(base64.b85decode)
self.assertRaises(ValueError, base64.b85decode, b'|')
self.assertRaises(ValueError, base64.b85decode, b'|N')
list(b'"\',;_`|\\~') + \
list(range(128, 256))
for c in illegal:
- with self.assertRaises(ValueError, msg=bytes([c])):
- base64.z85decode(b'0000' + bytes([c]))
+ b = bytes([c])
+ with self.assertRaises(ValueError, msg=b):
+ base64.z85decode(b'0000' + b)
+ self.assertEqual(base64.z85decode(b'0000' + b, ignorechars=b),
+ b'\x00\x00\x00')
+
+ self._common_test_ignorechars(base64.z85decode)
# b'\xff\xff\xff\xff' encodes to b'%nSc0', the following will overflow:
self.assertRaises(ValueError, base64.z85decode, b'%')
assertExcessPadding(b'abcd====efgh', b'i\xb7\x1dy\xf8!')
assertExcessPadding(b'abcd=====efgh', b'i\xb7\x1dy\xf8!')
+ def _common_test_ignorechars(self, func):
+ eq = self.assertEqual
+ empty = self.type2test(b'')
+ data = self.type2test(b'\n \n')
+ ignorechars = self.type2test(b' \n')
+ eq(func(empty, ignorechars=ignorechars), b'')
+ eq(func(empty, ignorechars=empty), b'')
+ eq(func(data, ignorechars=ignorechars), b'')
+ with self.assertRaises(binascii.Error):
+ func(data, ignorechars=empty)
+ with self.assertRaises(binascii.Error):
+ func(data, ignorechars=ignorechars[1:])
+ with self.assertRaises(binascii.Error):
+ func(data, ignorechars=ignorechars[:-1])
+ with self.assertRaises(TypeError):
+ func(empty, ignorechars='')
+ with self.assertRaises(TypeError):
+ func(empty, ignorechars=[])
+ with self.assertRaises(TypeError):
+ func(empty, ignorechars=None)
+
def test_base64_invalidchars(self):
# Test non-base64 data exceptions
+ self._common_test_ignorechars(binascii.a2b_base64)
def assertNonBase64Data(data, expected, ignorechars):
data = self.type2test(data)
assert_regex = r'(?i)Only base64 data'
assertNonBase64Data(b'a\nb==', b'i', ignorechars=bytearray(b'\n'))
assertNonBase64Data(b'a\nb==', b'i', ignorechars=memoryview(b'\n'))
+ self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_'),
+ b'\xf8\x0f\xc1')
+ self.assertEqual(binascii.a2b_base64(b'+A-/B_', ignorechars=b'+/-_',
+ alphabet=binascii.URLSAFE_BASE64_ALPHABET),
+ b'\x03\xe0\x7f')
+
# Same cell in the cache: '\r' >> 3 == '\n' >> 3.
data = self.type2test(b'\r\n')
with self.assertRaises(binascii.Error):
binascii.a2b_base64(data, ignorechars=b'*')
self.assertEqual(binascii.a2b_base64(data, ignorechars=b'*\n'), b'')
- data = self.type2test(b'a\nb==')
- with self.assertRaises(TypeError):
- binascii.a2b_base64(data, ignorechars='')
- with self.assertRaises(TypeError):
- binascii.a2b_base64(data, ignorechars=[])
- with self.assertRaises(TypeError):
- binascii.a2b_base64(data, ignorechars=None)
-
def test_base64_excess_data(self):
# Test excess data exceptions
def assertExcessData(data, expected):
assertInvalidChar(b"\tFCb", ignorechars=b"\n")
assertInvalidChar(b"xxxB\nP\thU'D v/F+", ignorechars=b" \n\tv")
+ def _common_test_wrapcol(self, func):
+ eq = self.assertEqual
+ data = self.data
+ expected = func(data)
+ eq(func(data, wrapcol=0), expected)
+ eq(func(data, wrapcol=8000), expected)
+ eq(func(b'', wrapcol=0), func(b''))
+ eq(func(b'', wrapcol=1), func(b''))
+ eq(func(data, wrapcol=sys.maxsize), expected)
+ if check_impl_detail():
+ eq(func(data, wrapcol=sys.maxsize*2), expected)
+ with self.assertRaises(OverflowError):
+ func(data, wrapcol=2**1000)
+ with self.assertRaises(ValueError):
+ func(data, wrapcol=-80)
+ with self.assertRaises(TypeError):
+ func(data, wrapcol=80.0)
+ with self.assertRaises(TypeError):
+ func(data, wrapcol='80')
+ with self.assertRaises(TypeError):
+ func(data, wrapcol=None)
+
def test_ascii85_wrapcol(self):
# Test Ascii85 splitting lines
+ self._common_test_wrapcol(binascii.b2a_ascii85)
+
def assertEncode(a_expected, data, n, adobe=False):
b = self.type2test(data)
a = binascii.b2a_ascii85(b, adobe=adobe, wrapcol=n)
assertOverflow(b"|NsC0~")
assertOverflow(b"|NsC0|NsC0|NsD0")
+ def test_base85_wrapcol(self):
+ self._common_test_wrapcol(binascii.b2a_base85)
+ b = self.type2test(b'www.python.org')
+ self.assertEqual(binascii.b2a_base85(b, wrapcol=10),
+ b'cXxL#aCvlS\nZ*DGca%T')
+ self.assertEqual(binascii.b2a_base85(b, wrapcol=14),
+ b'cXxL#aCvlS\nZ*DGca%T')
+ self.assertEqual(binascii.b2a_base85(b, wrapcol=1),
+ b'cXxL#\naCvlS\nZ*DGc\na%T')
+
def test_base85_pad(self):
# Test base85 with encode padding
rawdata = b"n1n3Tee\n ch@rAc\te\r$"
b_pad_expected = b + b"\0" * padding
self.assertEqual(b_pad, b_pad_expected)
+ def test_base85_ignorechars(self):
+ a2b_base85 = binascii.a2b_base85
+ self._common_test_ignorechars(a2b_base85)
+ eq = self.assertEqual
+ eq(a2b_base85(b'VPa\n !s\n', ignorechars=b' \n'), b'abcd')
+ eq(a2b_base85(b'VPa\n !s\n', ignorechars=bytearray(b' \n')), b'abcd')
+
+ eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~'), b'"1\xa3\x15')
+ eq(a2b_base85(b'A~[B];C', ignorechars=b';[]~',
+ alphabet=binascii.Z85_ALPHABET), b'r\xd8dv')
+
def test_base85_alphabet(self):
alphabet = (b'0123456789abcdefghijklmnopqrstuvwxyz'
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ.-:+=^!/*?&<>()[]{}@%$#')
assertInvalidLength(b"BEEFCA=K", b"\t\x08Q\x01")
assertInvalidLength(b"BEEFCA=====K", b"\t\x08Q\x01")
+ def test_base32_wrapcol(self):
+ self._common_test_wrapcol(binascii.b2a_base32)
+ b = self.type2test(b'www.python.org')
+ self.assertEqual(binascii.b2a_base32(b, wrapcol=16),
+ b'O53XOLTQPF2GQ33O\nFZXXEZY=')
+ self.assertEqual(binascii.b2a_base32(b, wrapcol=23),
+ b'O53XOLTQPF2GQ33O\nFZXXEZY=')
+ self.assertEqual(binascii.b2a_base32(b, wrapcol=1),
+ b'O53XOLTQ\nPF2GQ33O\nFZXXEZY=')
+
+ def test_base32_ignorechars(self):
+ a2b_base32 = binascii.a2b_base32
+ self._common_test_ignorechars(a2b_base32)
+ eq = self.assertEqual
+ eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=b' \n'), b'abcde')
+ eq(a2b_base32(b'MFRG\n GZDF\n', ignorechars=bytearray(b' \n')), b'abcde')
+ eq(a2b_base32(b'M=======FRGGZDF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MF======RGGZDF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFR=====GGZDF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRG====GZDF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRGG===ZDF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRGGZ==DF', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRGGZD=F', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRGGZDF=', ignorechars=b'='), b'abcde')
+ eq(a2b_base32(b'MFRA======', ignorechars=b'='), b'ab')
+
+ eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ'), b'\x00v.\xdb\xf9')
+ eq(a2b_base32(b'A1B3C5W7Z9', ignorechars=b'19WZ',
+ alphabet=binascii.BASE32HEX_ALPHABET), b'PV6\x14\xe9')
+
def test_base32_alphabet(self):
alphabet = b'0Aa1Bb2Cc3Dd4Ee5Ff6Gg7Hh8Ii9JjKk'
data = self.type2test(self.rawdata)
expected1 = s.hex(':').encode('ascii')
self.assertEqual(binascii.b2a_hex(self.type2test(s), ':'), expected1)
+ def test_hex_ignorechars(self):
+ a2b_hex = binascii.a2b_hex
+ self._common_test_ignorechars(a2b_hex)
+ self._common_test_ignorechars(binascii.unhexlify)
+ eq = self.assertEqual
+ eq(a2b_hex(b'A B\nC D\n', ignorechars=b' \n'), b'\xab\xcd')
+ eq(a2b_hex(b'A B\nC D\n', ignorechars=bytearray(b' \n')), b'\xab\xcd')
+ eq(a2b_hex(b'aBcD', ignorechars=b'ac'), b'\xab\xcd')
+
def test_qp(self):
type2test = self.type2test
a2b_qp = binascii.a2b_qp
self.assertEqual(binascii.b2a_base64(b, newline=False), b'')
def test_b2a_base64_wrapcol(self):
+ self._common_test_wrapcol(binascii.b2a_base64)
b = self.type2test(b'www.python.org')
- self.assertEqual(binascii.b2a_base64(b),
- b'd3d3LnB5dGhvbi5vcmc=\n')
- self.assertEqual(binascii.b2a_base64(b, wrapcol=0),
- b'd3d3LnB5dGhvbi5vcmc=\n')
self.assertEqual(binascii.b2a_base64(b, wrapcol=8),
b'd3d3LnB5\ndGhvbi5v\ncmc=\n')
self.assertEqual(binascii.b2a_base64(b, wrapcol=11),
b'd3d3LnB5\ndGhvbi5v\ncmc=\n')
- self.assertEqual(binascii.b2a_base64(b, wrapcol=76),
- b'd3d3LnB5dGhvbi5vcmc=\n')
self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False),
b'd3d3LnB5\ndGhvbi5v\ncmc=')
self.assertEqual(binascii.b2a_base64(b, wrapcol=1),
b'd3d3\nLnB5\ndGhv\nbi5v\ncmc=\n')
- self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize),
- b'd3d3LnB5dGhvbi5vcmc=\n')
- if check_impl_detail():
- self.assertEqual(binascii.b2a_base64(b, wrapcol=sys.maxsize*2),
- b'd3d3LnB5dGhvbi5vcmc=\n')
- with self.assertRaises(OverflowError):
- binascii.b2a_base64(b, wrapcol=2**1000)
- with self.assertRaises(ValueError):
- binascii.b2a_base64(b, wrapcol=-8)
- with self.assertRaises(TypeError):
- binascii.b2a_base64(b, wrapcol=8.0)
- with self.assertRaises(TypeError):
- binascii.b2a_base64(b, wrapcol='8')
b = self.type2test(b'')
- self.assertEqual(binascii.b2a_base64(b), b'\n')
- self.assertEqual(binascii.b2a_base64(b, wrapcol=0), b'\n')
- self.assertEqual(binascii.b2a_base64(b, wrapcol=8), b'\n')
self.assertEqual(binascii.b2a_base64(b, wrapcol=8, newline=False), b'')
@hypothesis.given(
--- /dev/null
+Add the *wrapcol* parameter to :mod:`base64` functions
+:func:`~base64.b16encode`, :func:`~base64.b32encode`,
+:func:`~base64.b32hexencode`, :func:`~base64.b85encode` and
+:func:`~base64.z85encode`, and :mod:`binascii` functions
+:func:`~binascii.b2a_base32` and :func:`~binascii.b2a_base85`. Add the
+*ignorechars* parameter to :mod:`base64` functions
+:func:`~base64.b16decode`, :func:`~base64.b32decode`,
+:func:`~base64.b32hexdecode`, :func:`~base64.b85decode` and
+:func:`~base64.z85decode`, and :mod:`binascii` functions
+:func:`~binascii.a2b_hex`, :func:`~binascii.unhexlify`,
+:func:`~binascii.a2b_base32` and :func:`~binascii.a2b_base85`.
if (quad_pos >= 2 && quad_pos + pads <= 4) {
continue;
}
- // See RFC 4648, section-3.3: "specifications MAY ignore the
+ // See RFC 4648, section 3.3: "specifications MAY ignore the
// pad character, "=", treating it as non-alphabet data, if
// it is present before the end of the encoded data" and
// "the excess pad characters MAY also be ignored."
unsigned char v = table_a2b[this_ch];
if (v >= 64) {
- // See RFC 4648, section-3.3.
+ // See RFC 4648, section 3.3.
if (strict_mode && !ignorechar(this_ch, ignorechars, ignorecache)) {
state = get_binascii_state(module);
if (state) {
}
// Characters that are not '=', in the middle of the padding, are
- // not allowed (except when they are). See RFC 4648, section-3.3.
+ // not allowed (except when they are). See RFC 4648, section 3.3.
if (pads && strict_mode &&
!ignorechar(BASE64_PAD, ignorechars, ignorecache))
{
/
*
alphabet: PyBytesObject(c_default="NULL") = BASE85_ALPHABET
+ ignorechars: Py_buffer = b''
+ A byte string containing characters to ignore from the input.
Decode a line of Base85 data.
[clinic start generated code]*/
static PyObject *
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data,
- PyBytesObject *alphabet)
-/*[clinic end generated code: output=3e114af53812e8ff input=0b6b83b38ad4497c]*/
+ PyBytesObject *alphabet, Py_buffer *ignorechars)
+/*[clinic end generated code: output=6a8d6eae798818d7 input=04d72a319712bdf3]*/
{
const unsigned char *ascii_data = data->buf;
Py_ssize_t ascii_len = data->len;
table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj);
}
+ if (ignorechars->len == 0) {
+ ignorechars = NULL;
+ }
+ ignorecache_t ignorecache;
+ if (ignorechars != NULL) {
+ memset(ignorecache, 0, sizeof(ignorecache));
+ }
+
assert(ascii_len >= 0);
/* Allocate output buffer. */
int group_pos = 0;
for (; ascii_len > 0 || group_pos != 0; ascii_len--, ascii_data++) {
/* Shift (in radix-85) data or padding into our buffer. */
+ unsigned char this_ch;
unsigned char this_digit;
if (ascii_len > 0) {
- unsigned char this_ch = *ascii_data;
+ this_ch = *ascii_data;
this_digit = table_a2b[this_ch];
}
else {
leftchar = leftchar * 85 + this_digit;
group_pos++;
}
- else {
+ else if (!ignorechar(this_ch, ignorechars, ignorecache)) {
state = get_binascii_state(module);
if (state != NULL) {
PyErr_Format(state->Error, "bad Base85 character at position %zd",
*
pad: bool = False
Pad input to a multiple of 4 before encoding.
+ wrapcol: size_t = 0
alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE85_ALPHABET
Base85-code line of data.
static PyObject *
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad,
- Py_buffer *alphabet)
-/*[clinic end generated code: output=a59f4f2ff6f0e69f input=30f545c6ff554db7]*/
+ size_t wrapcol, Py_buffer *alphabet)
+/*[clinic end generated code: output=98b962ed52c776a4 input=1b20b0bd6572691b]*/
{
const unsigned char *bin_data = data->buf;
Py_ssize_t bin_len = data->len;
if (!pad && (bin_len % 4)) {
out_len -= 4 - (bin_len % 4);
}
+ if (wrapcol && out_len) {
+ /* Each line should encode a whole number of bytes. */
+ wrapcol = wrapcol < 5 ? 5 : wrapcol / 5 * 5;
+ out_len += (out_len - 1u) / wrapcol;
+ }
if (out_len > PY_SSIZE_T_MAX) {
binascii_state *state = get_binascii_state(module);
if (state == NULL) {
ascii_data += group_len;
}
+ if (wrapcol && out_len) {
+ unsigned char *start = PyBytesWriter_GetData(writer);
+ ascii_data = start + wraplines(start, ascii_data - start, wrapcol);
+ }
+
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
}
/
*
alphabet: PyBytesObject(c_default="NULL") = BASE32_ALPHABET
+ ignorechars: Py_buffer = b''
+ A byte string containing characters to ignore from the input.
Decode a line of base32 data.
[clinic start generated code]*/
static PyObject *
binascii_a2b_base32_impl(PyObject *module, Py_buffer *data,
- PyBytesObject *alphabet)
-/*[clinic end generated code: output=12cb58bf547237e2 input=426055ea49ac147e]*/
+ PyBytesObject *alphabet, Py_buffer *ignorechars)
+/*[clinic end generated code: output=2cf7c8c9e6e98b88 input=b0333508aad1b3ac]*/
{
const unsigned char *ascii_data = data->buf;
Py_ssize_t ascii_len = data->len;
table_a2b = (const unsigned char *)PyBytes_AS_STRING(table_obj);
}
+ if (ignorechars->len == 0) {
+ ignorechars = NULL;
+ }
+ ignorecache_t ignorecache;
+ if (ignorechars != NULL) {
+ memset(ignorecache, 0, sizeof(ignorecache));
+ }
+
/* Allocate output buffer. */
size_t bin_len = ((size_t)ascii_len + 7) / 8 * 5;
PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
}
unsigned char *bin_data = PyBytesWriter_GetData(writer);
+fastpath:
/*
* Fast path: use optimized decoder for complete octas (groups of 8 bytes).
* The fast path stops at padding, invalid chars, or incomplete octas.
{
continue;
}
+ // See RFC 4648, section 3.3: "specifications MAY ignore the
+ // pad character, "=", treating it as non-alphabet data, if
+ // it is present before the end of the encoded data" and
+ // "the excess pad characters MAY also be ignored."
+ if (ignorechar(BASE32_PAD, ignorechars, ignorecache)) {
+ continue;
+ }
if (octa_pos == 1 || octa_pos == 3 || octa_pos == 6) {
/* Set an error below. */
break;
unsigned char v = table_a2b[this_ch];
if (v >= 32) {
- state = get_binascii_state(module);
- if (state) {
- PyErr_SetString(state->Error, "Only base32 data is allowed");
+ // See RFC 4648, section 3.3.
+ if (!ignorechar(this_ch, ignorechars, ignorecache)) {
+ state = get_binascii_state(module);
+ if (state) {
+ PyErr_SetString(state->Error, "Only base32 data is allowed");
+ }
+ goto error;
}
- goto error;
+ continue;
}
- /* Data in the middle of/after the padding is not allowed. */
- if (pads) {
+ // Characters that are not '=', in the middle of the padding, are
+ // not allowed (except when they are). See RFC 4648, section 3.3.
+ if (pads && !ignorechar(BASE32_PAD, ignorechars, ignorecache)) {
state = get_binascii_state(module);
if (state) {
PyErr_SetString(state->Error, (octa_pos + pads == 8)
octa_pos = 0;
*bin_data++ = (leftchar << 5) | v;
leftchar = 0;
+ ascii_data++;
+ ascii_len--;
+ goto fastpath;
}
}
goto error;
}
- if ((octa_pos != 0 && octa_pos + pads != 8)
- || (octa_pos == 0 && pads != 0))
- {
+ if (octa_pos != 0 && octa_pos + pads < 8) {
state = get_binascii_state(module);
if (state) {
PyErr_SetString(state->Error, "Incorrect padding");
data: Py_buffer
/
*
+ wrapcol: size_t = 0
alphabet: Py_buffer(c_default="{NULL, NULL}") = BASE32_ALPHABET
Base32-code line of data.
[clinic start generated code]*/
static PyObject *
-binascii_b2a_base32_impl(PyObject *module, Py_buffer *data,
+binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
Py_buffer *alphabet)
-/*[clinic end generated code: output=058d0d1aeb014d3b input=99cbe7194799d368]*/
+/*[clinic end generated code: output=d41fafbdaf29e280 input=a3d93b73836f2879]*/
{
const unsigned char *table_b2a = table_b2a_base32;
const unsigned char *bin_data = data->buf;
* Use unsigned integer arithmetic to avoid signed integer overflow.
*/
size_t ascii_len = ((size_t)bin_len + 4u) / 5u * 8u;
+ if (wrapcol && ascii_len) {
+ /* Each line should encode a whole number of bytes. */
+ wrapcol = wrapcol < 8 ? 8 : wrapcol / 8 * 8;
+ ascii_len += (ascii_len - 1u) / wrapcol;
+ }
if (ascii_len > PY_SSIZE_T_MAX) {
state = get_binascii_state(module);
if (state) {
*ascii_data++ = BASE32_PAD;
}
+ if (wrapcol && ascii_len) {
+ unsigned char *start = PyBytesWriter_GetData(writer);
+ ascii_data = start + wraplines(start, ascii_data - start, wrapcol);
+ }
+
return PyBytesWriter_FinishWithPointer(writer, ascii_data);
}
hexstr: ascii_buffer
/
+ *
+ ignorechars: Py_buffer = b''
+ A byte string containing characters to ignore from the input.
Binary data of hexadecimal representation.
[clinic start generated code]*/
static PyObject *
-binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr)
-/*[clinic end generated code: output=0cc1a139af0eeecb input=9e1e7f2f94db24fd]*/
+binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr,
+ Py_buffer *ignorechars)
+/*[clinic end generated code: output=021a7ed5a742cb20 input=6154b3f4e6e2c0c3]*/
{
- const char* argbuf;
- Py_ssize_t arglen;
- Py_ssize_t i, j;
- binascii_state *state;
-
- argbuf = hexstr->buf;
- arglen = hexstr->len;
-
- assert(arglen >= 0);
+ const unsigned char *ascii_data = hexstr->buf;
+ size_t ascii_len = hexstr->len;
+ binascii_state *state = NULL;
- /* XXX What should we do about strings with an odd length? Should
- * we add an implicit leading zero, or a trailing zero? For now,
- * raise an exception.
- */
- if (arglen % 2) {
- state = get_binascii_state(module);
- if (state == NULL) {
- return NULL;
- }
- PyErr_SetString(state->Error, "Odd-length string");
- return NULL;
+ if (ignorechars->len == 0) {
+ ignorechars = NULL;
+ }
+ ignorecache_t ignorecache;
+ if (ignorechars != NULL) {
+ memset(ignorecache, 0, sizeof(ignorecache));
}
- PyBytesWriter *writer = PyBytesWriter_Create(arglen/2);
+ /* Allocate the buffer */
+ Py_ssize_t bin_len = ascii_len/2;
+ PyBytesWriter *writer = PyBytesWriter_Create(bin_len);
if (writer == NULL) {
return NULL;
}
- char *retbuf = PyBytesWriter_GetData(writer);
+ unsigned char *bin_data = PyBytesWriter_GetData(writer);
- for (i=j=0; i < arglen; i += 2) {
- unsigned int top = _PyLong_DigitValue[Py_CHARMASK(argbuf[i])];
- unsigned int bot = _PyLong_DigitValue[Py_CHARMASK(argbuf[i+1])];
- if (top >= 16 || bot >= 16) {
- state = get_binascii_state(module);
- if (state == NULL) {
+ int pair_pos = 0;
+ unsigned char leftchar = 0;
+ for (; ascii_len; ascii_data++, ascii_len--) {
+ unsigned char this_ch = *ascii_data;
+
+ unsigned char this_digit = _PyLong_DigitValue[this_ch];
+ if (this_digit >= 16) {
+ // See RFC 4648, section 3.3.
+ if (!ignorechar(this_ch, ignorechars, ignorecache)) {
+ state = get_binascii_state(module);
+ if (state) {
+ PyErr_SetString(state->Error,
+ "Non-hexadecimal digit found");
+ }
goto error;
}
- PyErr_SetString(state->Error,
- "Non-hexadecimal digit found");
- goto error;
+ continue;
+ }
+
+ if (!pair_pos) {
+ pair_pos = 1;
+ leftchar = this_digit;
+ }
+ else {
+ pair_pos = 0;
+ *bin_data++ = (leftchar << 4) | this_digit;
}
- retbuf[j++] = (top << 4) + bot;
}
- return PyBytesWriter_Finish(writer);
+
+ if (pair_pos) {
+ state = get_binascii_state(module);
+ if (state) {
+ PyErr_SetString(state->Error, "Odd number of hexadecimal digits");
+ }
+ goto error;
+ }
+
+ return PyBytesWriter_FinishWithPointer(writer, bin_data);
error:
PyBytesWriter_Discard(writer);
[clinic start generated code]*/
static PyObject *
-binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr)
-/*[clinic end generated code: output=51a64c06c79629e3 input=dd8c012725f462da]*/
+binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr,
+ Py_buffer *ignorechars)
+/*[clinic end generated code: output=40e87f8a0ded5880 input=dd8c012725f462da]*/
{
- return binascii_a2b_hex_impl(module, hexstr);
+ return binascii_a2b_hex_impl(module, hexstr, ignorechars);
}
#define MAXLINESIZE 76
}
PyDoc_STRVAR(binascii_a2b_base85__doc__,
-"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET)\n"
+"a2b_base85($module, data, /, *, alphabet=BASE85_ALPHABET,\n"
+" ignorechars=b\'\')\n"
"--\n"
"\n"
-"Decode a line of Base85 data.");
+"Decode a line of Base85 data.\n"
+"\n"
+" ignorechars\n"
+" A byte string containing characters to ignore from the input.");
#define BINASCII_A2B_BASE85_METHODDEF \
{"a2b_base85", _PyCFunction_CAST(binascii_a2b_base85), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base85__doc__},
static PyObject *
binascii_a2b_base85_impl(PyObject *module, Py_buffer *data,
- PyBytesObject *alphabet);
+ PyBytesObject *alphabet, Py_buffer *ignorechars);
static PyObject *
binascii_a2b_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 1
+ #define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(alphabet), },
+ .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "alphabet", NULL};
+ static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "a2b_base85",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
PyBytesObject *alphabet = NULL;
+ Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0};
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (!PyBytes_Check(args[1])) {
- _PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]);
+ if (args[1]) {
+ if (!PyBytes_Check(args[1])) {
+ _PyArg_BadArgument("a2b_base85", "argument 'alphabet'", "bytes", args[1]);
+ goto exit;
+ }
+ alphabet = (PyBytesObject *)args[1];
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) {
goto exit;
}
- alphabet = (PyBytesObject *)args[1];
skip_optional_kwonly:
- return_value = binascii_a2b_base85_impl(module, &data, alphabet);
+ return_value = binascii_a2b_base85_impl(module, &data, alphabet, &ignorechars);
exit:
/* Cleanup for data */
if (data.obj)
PyBuffer_Release(&data);
+ /* Cleanup for ignorechars */
+ if (ignorechars.obj) {
+ PyBuffer_Release(&ignorechars);
+ }
return return_value;
}
PyDoc_STRVAR(binascii_b2a_base85__doc__,
-"b2a_base85($module, data, /, *, pad=False, alphabet=BASE85_ALPHABET)\n"
+"b2a_base85($module, data, /, *, pad=False, wrapcol=0,\n"
+" alphabet=BASE85_ALPHABET)\n"
"--\n"
"\n"
"Base85-code line of data.\n"
static PyObject *
binascii_b2a_base85_impl(PyObject *module, Py_buffer *data, int pad,
- Py_buffer *alphabet);
+ size_t wrapcol, Py_buffer *alphabet);
static PyObject *
binascii_b2a_base85(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 2
+ #define NUM_KEYWORDS 3
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(pad), &_Py_ID(alphabet), },
+ .ob_item = { &_Py_ID(pad), &_Py_ID(wrapcol), &_Py_ID(alphabet), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "pad", "alphabet", NULL};
+ static const char * const _keywords[] = {"", "pad", "wrapcol", "alphabet", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "b2a_base85",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[3];
+ PyObject *argsbuf[4];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
int pad = 0;
+ size_t wrapcol = 0;
Py_buffer alphabet = {NULL, NULL};
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
goto skip_optional_kwonly;
}
}
- if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) {
+ if (args[2]) {
+ if (!_PyLong_Size_t_Converter(args[2], &wrapcol)) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ if (PyObject_GetBuffer(args[3], &alphabet, PyBUF_SIMPLE) != 0) {
goto exit;
}
skip_optional_kwonly:
- return_value = binascii_b2a_base85_impl(module, &data, pad, &alphabet);
+ return_value = binascii_b2a_base85_impl(module, &data, pad, wrapcol, &alphabet);
exit:
/* Cleanup for data */
}
PyDoc_STRVAR(binascii_a2b_base32__doc__,
-"a2b_base32($module, data, /, *, alphabet=BASE32_ALPHABET)\n"
+"a2b_base32($module, data, /, *, alphabet=BASE32_ALPHABET,\n"
+" ignorechars=b\'\')\n"
"--\n"
"\n"
-"Decode a line of base32 data.");
+"Decode a line of base32 data.\n"
+"\n"
+" ignorechars\n"
+" A byte string containing characters to ignore from the input.");
#define BINASCII_A2B_BASE32_METHODDEF \
{"a2b_base32", _PyCFunction_CAST(binascii_a2b_base32), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_base32__doc__},
static PyObject *
binascii_a2b_base32_impl(PyObject *module, Py_buffer *data,
- PyBytesObject *alphabet);
+ PyBytesObject *alphabet, Py_buffer *ignorechars);
static PyObject *
binascii_a2b_base32(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 1
+ #define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(alphabet), },
+ .ob_item = { &_Py_ID(alphabet), &_Py_ID(ignorechars), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "alphabet", NULL};
+ static const char * const _keywords[] = {"", "alphabet", "ignorechars", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "a2b_base32",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
PyBytesObject *alphabet = NULL;
+ Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0};
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
/*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (!PyBytes_Check(args[1])) {
- _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[1]);
+ if (args[1]) {
+ if (!PyBytes_Check(args[1])) {
+ _PyArg_BadArgument("a2b_base32", "argument 'alphabet'", "bytes", args[1]);
+ goto exit;
+ }
+ alphabet = (PyBytesObject *)args[1];
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ if (PyObject_GetBuffer(args[2], &ignorechars, PyBUF_SIMPLE) != 0) {
goto exit;
}
- alphabet = (PyBytesObject *)args[1];
skip_optional_kwonly:
- return_value = binascii_a2b_base32_impl(module, &data, alphabet);
+ return_value = binascii_a2b_base32_impl(module, &data, alphabet, &ignorechars);
exit:
/* Cleanup for data */
if (data.obj)
PyBuffer_Release(&data);
+ /* Cleanup for ignorechars */
+ if (ignorechars.obj) {
+ PyBuffer_Release(&ignorechars);
+ }
return return_value;
}
PyDoc_STRVAR(binascii_b2a_base32__doc__,
-"b2a_base32($module, data, /, *, alphabet=BASE32_ALPHABET)\n"
+"b2a_base32($module, data, /, *, wrapcol=0, alphabet=BASE32_ALPHABET)\n"
"--\n"
"\n"
"Base32-code line of data.");
{"b2a_base32", _PyCFunction_CAST(binascii_b2a_base32), METH_FASTCALL|METH_KEYWORDS, binascii_b2a_base32__doc__},
static PyObject *
-binascii_b2a_base32_impl(PyObject *module, Py_buffer *data,
+binascii_b2a_base32_impl(PyObject *module, Py_buffer *data, size_t wrapcol,
Py_buffer *alphabet);
static PyObject *
PyObject *return_value = NULL;
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
- #define NUM_KEYWORDS 1
+ #define NUM_KEYWORDS 2
static struct {
PyGC_Head _this_is_not_used;
PyObject_VAR_HEAD
} _kwtuple = {
.ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
.ob_hash = -1,
- .ob_item = { &_Py_ID(alphabet), },
+ .ob_item = { &_Py_ID(wrapcol), &_Py_ID(alphabet), },
};
#undef NUM_KEYWORDS
#define KWTUPLE (&_kwtuple.ob_base.ob_base)
# define KWTUPLE NULL
#endif // !Py_BUILD_CORE
- static const char * const _keywords[] = {"", "alphabet", NULL};
+ static const char * const _keywords[] = {"", "wrapcol", "alphabet", NULL};
static _PyArg_Parser _parser = {
.keywords = _keywords,
.fname = "b2a_base32",
.kwtuple = KWTUPLE,
};
#undef KWTUPLE
- PyObject *argsbuf[2];
+ PyObject *argsbuf[3];
Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer data = {NULL, NULL};
+ size_t wrapcol = 0;
Py_buffer alphabet = {NULL, NULL};
args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
if (!noptargs) {
goto skip_optional_kwonly;
}
- if (PyObject_GetBuffer(args[1], &alphabet, PyBUF_SIMPLE) != 0) {
+ if (args[1]) {
+ if (!_PyLong_Size_t_Converter(args[1], &wrapcol)) {
+ goto exit;
+ }
+ if (!--noptargs) {
+ goto skip_optional_kwonly;
+ }
+ }
+ if (PyObject_GetBuffer(args[2], &alphabet, PyBUF_SIMPLE) != 0) {
goto exit;
}
skip_optional_kwonly:
- return_value = binascii_b2a_base32_impl(module, &data, &alphabet);
+ return_value = binascii_b2a_base32_impl(module, &data, wrapcol, &alphabet);
exit:
/* Cleanup for data */
}
PyDoc_STRVAR(binascii_a2b_hex__doc__,
-"a2b_hex($module, hexstr, /)\n"
+"a2b_hex($module, hexstr, /, *, ignorechars=b\'\')\n"
"--\n"
"\n"
"Binary data of hexadecimal representation.\n"
"\n"
+" ignorechars\n"
+" A byte string containing characters to ignore from the input.\n"
+"\n"
"hexstr must contain an even number of hex digits (upper or lower case).\n"
"This function is also available as \"unhexlify()\".");
#define BINASCII_A2B_HEX_METHODDEF \
- {"a2b_hex", (PyCFunction)binascii_a2b_hex, METH_O, binascii_a2b_hex__doc__},
+ {"a2b_hex", _PyCFunction_CAST(binascii_a2b_hex), METH_FASTCALL|METH_KEYWORDS, binascii_a2b_hex__doc__},
static PyObject *
-binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr);
+binascii_a2b_hex_impl(PyObject *module, Py_buffer *hexstr,
+ Py_buffer *ignorechars);
static PyObject *
-binascii_a2b_hex(PyObject *module, PyObject *arg)
+binascii_a2b_hex(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(ignorechars), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "ignorechars", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "a2b_hex",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer hexstr = {NULL, NULL};
+ Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0};
- if (!ascii_buffer_converter(arg, &hexstr)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ if (!ascii_buffer_converter(args[0], &hexstr)) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) {
goto exit;
}
- return_value = binascii_a2b_hex_impl(module, &hexstr);
+skip_optional_kwonly:
+ return_value = binascii_a2b_hex_impl(module, &hexstr, &ignorechars);
exit:
/* Cleanup for hexstr */
if (hexstr.obj)
PyBuffer_Release(&hexstr);
+ /* Cleanup for ignorechars */
+ if (ignorechars.obj) {
+ PyBuffer_Release(&ignorechars);
+ }
return return_value;
}
PyDoc_STRVAR(binascii_unhexlify__doc__,
-"unhexlify($module, hexstr, /)\n"
+"unhexlify($module, hexstr, /, *, ignorechars=b\'\')\n"
"--\n"
"\n"
"Binary data of hexadecimal representation.\n"
"\n"
+" ignorechars\n"
+" A byte string containing characters to ignore from the input.\n"
+"\n"
"hexstr must contain an even number of hex digits (upper or lower case).");
#define BINASCII_UNHEXLIFY_METHODDEF \
- {"unhexlify", (PyCFunction)binascii_unhexlify, METH_O, binascii_unhexlify__doc__},
+ {"unhexlify", _PyCFunction_CAST(binascii_unhexlify), METH_FASTCALL|METH_KEYWORDS, binascii_unhexlify__doc__},
static PyObject *
-binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr);
+binascii_unhexlify_impl(PyObject *module, Py_buffer *hexstr,
+ Py_buffer *ignorechars);
static PyObject *
-binascii_unhexlify(PyObject *module, PyObject *arg)
+binascii_unhexlify(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 1
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(ignorechars), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"", "ignorechars", NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "unhexlify",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[2];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 1;
Py_buffer hexstr = {NULL, NULL};
+ Py_buffer ignorechars = {.buf = "", .obj = NULL, .len = 0};
- if (!ascii_buffer_converter(arg, &hexstr)) {
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 1, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
goto exit;
}
- return_value = binascii_unhexlify_impl(module, &hexstr);
+ if (!ascii_buffer_converter(args[0], &hexstr)) {
+ goto exit;
+ }
+ if (!noptargs) {
+ goto skip_optional_kwonly;
+ }
+ if (PyObject_GetBuffer(args[1], &ignorechars, PyBUF_SIMPLE) != 0) {
+ goto exit;
+ }
+skip_optional_kwonly:
+ return_value = binascii_unhexlify_impl(module, &hexstr, &ignorechars);
exit:
/* Cleanup for hexstr */
if (hexstr.obj)
PyBuffer_Release(&hexstr);
+ /* Cleanup for ignorechars */
+ if (ignorechars.obj) {
+ PyBuffer_Release(&ignorechars);
+ }
return return_value;
}
return return_value;
}
-/*[clinic end generated code: output=242c0c56b918bd33 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=7afd570a9d5a3627 input=a9049054013a1b77]*/