bpo-39353: Deprecate the binhex module (GH-18025)
Deprecate binhex4 and hexbin4 standards. Deprecate the binhex module
and the following binascii functions:
* b2a_hqx(), a2b_hqx()
* rlecode_hqx(), rledecode_hqx()
* crc_hqx()
diff --git a/Lib/binhex.py b/Lib/binhex.py
index 56b5f85..6ff38dd 100644
--- a/Lib/binhex.py
+++ b/Lib/binhex.py
@@ -21,10 +21,16 @@
# input. The resulting code (xx 90 90) would appear to be interpreted as an
# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety...
#
+import binascii
+import contextlib
import io
import os
import struct
-import binascii
+import warnings
+
+warnings.warn('the binhex module is deprecated', DeprecationWarning,
+ stacklevel=2)
+
__all__ = ["binhex","hexbin","Error"]
@@ -76,6 +82,16 @@
def close(self):
pass
+
+# DeprecationWarning is already emitted on "import binhex". There is no need
+# to repeat the warning at each call to deprecated binascii functions.
+@contextlib.contextmanager
+def _ignore_deprecation_warning():
+ with warnings.catch_warnings():
+ warnings.filterwarnings('ignore', '', DeprecationWarning)
+ yield
+
+
class _Hqxcoderengine:
"""Write data to the coder in 3-byte chunks"""
@@ -93,7 +109,8 @@
self.data = self.data[todo:]
if not data:
return
- self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
+ with _ignore_deprecation_warning():
+ self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
self._flush(0)
def _flush(self, force):
@@ -109,7 +126,8 @@
def close(self):
if self.data:
- self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data)
+ with _ignore_deprecation_warning():
+ self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data)
self._flush(1)
self.ofp.close()
del self.ofp
@@ -125,13 +143,15 @@
self.data = self.data + data
if len(self.data) < REASONABLY_LARGE:
return
- rledata = binascii.rlecode_hqx(self.data)
+ with _ignore_deprecation_warning():
+ rledata = binascii.rlecode_hqx(self.data)
self.ofp.write(rledata)
self.data = b''
def close(self):
if self.data:
- rledata = binascii.rlecode_hqx(self.data)
+ with _ignore_deprecation_warning():
+ rledata = binascii.rlecode_hqx(self.data)
self.ofp.write(rledata)
self.ofp.close()
del self.ofp
@@ -180,7 +200,8 @@
self._writecrc()
def _write(self, data):
- self.crc = binascii.crc_hqx(data, self.crc)
+ with _ignore_deprecation_warning():
+ self.crc = binascii.crc_hqx(data, self.crc)
self.ofp.write(data)
def _writecrc(self):
@@ -276,7 +297,8 @@
#
while True:
try:
- decdatacur, self.eof = binascii.a2b_hqx(data)
+ with _ignore_deprecation_warning():
+ decdatacur, self.eof = binascii.a2b_hqx(data)
break
except binascii.Incomplete:
pass
@@ -312,8 +334,9 @@
def _fill(self, wtd):
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd + 4)
if self.ifp.eof:
- self.post_buffer = self.post_buffer + \
- binascii.rledecode_hqx(self.pre_buffer)
+ with _ignore_deprecation_warning():
+ self.post_buffer = self.post_buffer + \
+ binascii.rledecode_hqx(self.pre_buffer)
self.pre_buffer = b''
return
@@ -340,8 +363,9 @@
else:
mark = mark - 1
- self.post_buffer = self.post_buffer + \
- binascii.rledecode_hqx(self.pre_buffer[:mark])
+ with _ignore_deprecation_warning():
+ self.post_buffer = self.post_buffer + \
+ binascii.rledecode_hqx(self.pre_buffer[:mark])
self.pre_buffer = self.pre_buffer[mark:]
def close(self):
@@ -372,7 +396,8 @@
def _read(self, len):
data = self.ifp.read(len)
- self.crc = binascii.crc_hqx(data, self.crc)
+ with _ignore_deprecation_warning():
+ self.crc = binascii.crc_hqx(data, self.crc)
return data
def _checkcrc(self):
diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py
index 08de5c9..649edbe 100644
--- a/Lib/test/test_binascii.py
+++ b/Lib/test/test_binascii.py
@@ -4,6 +4,7 @@
import binascii
import array
import re
+from test import support
# Note: "*_hex" functions are aliases for "(un)hexlify"
b2a_functions = ['b2a_base64', 'b2a_hex', 'b2a_hqx', 'b2a_qp', 'b2a_uu',
@@ -36,6 +37,7 @@
self.assertTrue(hasattr(getattr(binascii, name), '__call__'))
self.assertRaises(TypeError, getattr(binascii, name))
+ @support.ignore_warnings(category=DeprecationWarning)
def test_returned_value(self):
# Limit to the minimum of all limits (b2a_uu)
MAX_ALL = 45
@@ -179,6 +181,7 @@
with self.assertRaises(TypeError):
binascii.b2a_uu(b"", True)
+ @support.ignore_warnings(category=DeprecationWarning)
def test_crc_hqx(self):
crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0)
crc = binascii.crc_hqx(self.type2test(b" this string."), crc)
@@ -198,6 +201,7 @@
self.assertRaises(TypeError, binascii.crc32)
+ @support.ignore_warnings(category=DeprecationWarning)
def test_hqx(self):
# Perform binhex4 style RLE-compression
# Then calculate the hexbin4 binary-to-ASCII translation
@@ -208,6 +212,7 @@
res = binascii.rledecode_hqx(b)
self.assertEqual(res, self.rawdata)
+ @support.ignore_warnings(category=DeprecationWarning)
def test_rle(self):
# test repetition with a repetition longer than the limit of 255
data = (b'a' * 100 + b'b' + b'c' * 300)
@@ -354,6 +359,7 @@
self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n')
self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E')
+ @support.ignore_warnings(category=DeprecationWarning)
def test_empty_string(self):
# A test for SF bug #1022953. Make sure SystemError is not raised.
empty = self.type2test(b'')
@@ -378,6 +384,7 @@
# crc_hqx needs 2 arguments
self.assertRaises(TypeError, binascii.crc_hqx, "test", 0)
+ @support.ignore_warnings(category=DeprecationWarning)
def test_unicode_a2b(self):
# Unicode strings are accepted by a2b_* functions.
MAX_ALL = 45
@@ -416,6 +423,21 @@
self.assertEqual(binascii.b2a_base64(b, newline=False),
b'aGVsbG8=')
+ def test_deprecated_warnings(self):
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(binascii.b2a_hqx(b'abc'), b'B@*M')
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(binascii.a2b_hqx(b'B@*M'), (b'abc', 0))
+
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(binascii.rlecode_hqx(b'a' * 10), b'a\x90\n')
+
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(binascii.rledecode_hqx(b'a\x90\n'), b'a' * 10)
+
+ with self.assertWarns(DeprecationWarning):
+ self.assertEqual(binascii.crc_hqx(b'abc', 0), 40406)
+
class ArrayBinASCIITest(BinASCIITest):
def type2test(self, s):
diff --git a/Lib/test/test_binhex.py b/Lib/test/test_binhex.py
index 2f3d53a..86ca37c 100644
--- a/Lib/test/test_binhex.py
+++ b/Lib/test/test_binhex.py
@@ -3,10 +3,12 @@
Uses the mechanism of the python binhex module
Based on an original test by Roger E. Masse.
"""
-import binhex
import unittest
from test import support
+with support.check_warnings(('', DeprecationWarning)):
+ import binhex
+
class BinHexTestCase(unittest.TestCase):