]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39353: Deprecate the binhex module (GH-18025)
authorVictor Stinner <vstinner@python.org>
Wed, 22 Jan 2020 19:44:22 +0000 (20:44 +0100)
committerGitHub <noreply@github.com>
Wed, 22 Jan 2020 19:44:22 +0000 (20:44 +0100)
Deprecate binhex4 and hexbin4 standards. Deprecate the binhex module
and the following binascii functions:

* b2a_hqx(), a2b_hqx()
* rlecode_hqx(), rledecode_hqx()
* crc_hqx()

Doc/library/binascii.rst
Doc/library/binhex.rst
Doc/whatsnew/3.9.rst
Lib/binhex.py
Lib/test/test_binascii.py
Lib/test/test_binhex.py
Misc/NEWS.d/next/Library/2020-01-16-10-21-48.bpo-39353.ntp7Ql.rst [new file with mode: 0644]
Modules/binascii.c
Modules/clinic/binascii.c.h

index 98d8679fa3dcda3d359101f0a8edf59470522c89..aa2a27084c34c521b6fa92d175526e62c75adb15 100644 (file)
@@ -92,6 +92,8 @@ The :mod:`binascii` module defines the following functions:
    The string should contain a complete number of binary bytes, or (in case of the
    last portion of the binhex4 data) have the remaining bits zero.
 
+   .. deprecated:: 3.9
+
 
 .. function:: rledecode_hqx(data)
 
@@ -104,11 +106,15 @@ The :mod:`binascii` module defines the following functions:
    .. versionchanged:: 3.2
       Accept only bytestring or bytearray objects as input.
 
+   .. deprecated:: 3.9
+
 
 .. function:: rlecode_hqx(data)
 
    Perform binhex4 style RLE-compression on *data* and return the result.
 
+   .. deprecated:: 3.9
+
 
 .. function:: b2a_hqx(data)
 
@@ -116,6 +122,8 @@ The :mod:`binascii` module defines the following functions:
    argument should already be RLE-coded, and have a length divisible by 3 (except
    possibly the last fragment).
 
+   .. deprecated:: 3.9
+
 
 .. function:: crc_hqx(data, value)
 
@@ -124,6 +132,8 @@ The :mod:`binascii` module defines the following functions:
    *x*:sup:`16` + *x*:sup:`12` + *x*:sup:`5` + 1, often represented as
    0x1021.  This CRC is used in the binhex4 format.
 
+   .. deprecated:: 3.9
+
 
 .. function:: crc32(data[, value])
 
index 2966e0dbfbcfe8750f537eee6ac3bfd0f4dd6919..7de6a663762f0c019422a67bc66a2b29f7ae891b 100644 (file)
@@ -6,6 +6,8 @@
 
 **Source code:** :source:`Lib/binhex.py`
 
+.. deprecated:: 3.9
+
 --------------
 
 This module encodes and decodes files in binhex4 format, a format allowing
index 00341ef8019e710f68e252bccd547363eb12837f..0e82ff0695d3ee020ff7e5131b6ee2f73ba174cd 100644 (file)
@@ -353,6 +353,16 @@ Deprecated
   deprecated and will be removed in version 3.11.
   (Contributed by Yury Selivanov and Kyle Stanley in :issue:`34790`.)
 
+* binhex4 and hexbin4 standards are now deprecated. The :`binhex` module
+  and the following :mod:`binascii` functions are now deprecated:
+
+  * :func:`~binascii.b2a_hqx`, :func:`~binascii.a2b_hqx`
+  * :func:`~binascii.rlecode_hqx`, :func:`~binascii.rledecode_hqx`
+  * :func:`~binascii.crc_hqx`
+
+  (Contributed by Victor Stinner in :issue:`39353`.)
+
+
 Removed
 =======
 
index 56b5f852c0038ac3320c34bd976925e2ee140c06..6ff38dd8229c8b9934867007d1f781ddd7d2a404 100644 (file)
@@ -21,10 +21,16 @@ hexbin(inputfilename, outputfilename)
 # 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 @@ class openrsrc:
     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 @@ class _Hqxcoderengine:
         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 @@ class _Hqxcoderengine:
 
     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 @@ class _Rlecoderengine:
         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 @@ class BinHex:
         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 @@ class _Hqxdecoderengine:
             #
             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 @@ class _Rledecoderengine:
     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 @@ class _Rledecoderengine:
         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 @@ class HexBin:
 
     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):
index 08de5c9fc7cc39935498574daf20b95a171cc8e2..649edbe2954134319a38ab3bda0376298a32c290 100644 (file)
@@ -4,6 +4,7 @@ import unittest
 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 @@ class BinASCIITest(unittest.TestCase):
             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 @@ class BinASCIITest(unittest.TestCase):
         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 @@ class BinASCIITest(unittest.TestCase):
 
         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 @@ class BinASCIITest(unittest.TestCase):
         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 @@ class BinASCIITest(unittest.TestCase):
         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 @@ class BinASCIITest(unittest.TestCase):
         # 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 @@ class BinASCIITest(unittest.TestCase):
         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):
index 2f3d53afbd1321345e6c26dfe4acd0fd3c890c89..86ca37ce1b99a7a4be13f121700b714f23e99912 100644 (file)
@@ -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):
 
diff --git a/Misc/NEWS.d/next/Library/2020-01-16-10-21-48.bpo-39353.ntp7Ql.rst b/Misc/NEWS.d/next/Library/2020-01-16-10-21-48.bpo-39353.ntp7Ql.rst
new file mode 100644 (file)
index 0000000..c0d4583
--- /dev/null
@@ -0,0 +1,4 @@
+Deprecate binhex4 and hexbin4 standards. Deprecate the :mod:`binhex` module and
+the following :mod:`binascii` functions: :func:`~binascii.b2a_hqx`,
+:func:`~binascii.a2b_hqx`, :func:`~binascii.rlecode_hqx`,
+:func:`~binascii.rledecode_hqx`, :func:`~binascii.crc_hqx`.
index 94b0732c12c8319a4eed9f965f08173f1006aa6e..c6da3e0a635bcafe5373d90a64f01a0a03dc4083 100644 (file)
@@ -613,6 +613,11 @@ static PyObject *
 binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data)
 /*[clinic end generated code: output=4d6d8c54d54ea1c1 input=0d914c680e0eed55]*/
 {
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                     "binascii.a2b_hqx() is deprecated", 1) < 0) {
+        return NULL;
+    }
+
     const unsigned char *ascii_data;
     unsigned char *bin_data;
     int leftbits = 0;
@@ -701,6 +706,11 @@ static PyObject *
 binascii_rlecode_hqx_impl(PyObject *module, Py_buffer *data)
 /*[clinic end generated code: output=393d79338f5f5629 input=e1f1712447a82b09]*/
 {
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                     "binascii.rlecode_hqx() is deprecated", 1) < 0) {
+        return NULL;
+    }
+
     const unsigned char *in_data;
     unsigned char *out_data;
     unsigned char ch;
@@ -763,6 +773,11 @@ static PyObject *
 binascii_b2a_hqx_impl(PyObject *module, Py_buffer *data)
 /*[clinic end generated code: output=d0aa5a704bc9f7de input=9596ebe019fe12ba]*/
 {
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                     "binascii.b2a_hqx() is deprecated", 1) < 0) {
+        return NULL;
+    }
+
     unsigned char *ascii_data;
     const unsigned char *bin_data;
     int leftbits = 0;
@@ -818,6 +833,11 @@ static PyObject *
 binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
 /*[clinic end generated code: output=9826619565de1c6c input=54cdd49fc014402c]*/
 {
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                     "binascii.rledecode_hqx() is deprecated", 1) < 0) {
+        return NULL;
+    }
+
     const unsigned char *in_data;
     unsigned char *out_data;
     unsigned char in_byte, in_repeat;
@@ -932,7 +952,7 @@ error:
 
 
 /*[clinic input]
-binascii.crc_hqx -> unsigned_int
+binascii.crc_hqx
 
     data: Py_buffer
     crc: unsigned_int(bitwise=True)
@@ -941,10 +961,15 @@ binascii.crc_hqx -> unsigned_int
 Compute CRC-CCITT incrementally.
 [clinic start generated code]*/
 
-static unsigned int
+static PyObject *
 binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc)
-/*[clinic end generated code: output=8ec2a78590d19170 input=f18240ff8c705b79]*/
+/*[clinic end generated code: output=2fde213d0f547a98 input=56237755370a951c]*/
 {
+    if (PyErr_WarnEx(PyExc_DeprecationWarning,
+                     "binascii.crc_hqx() is deprecated", 1) < 0) {
+        return NULL;
+    }
+
     const unsigned char *bin_data;
     Py_ssize_t len;
 
@@ -956,7 +981,7 @@ binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc)
         crc = ((crc<<8)&0xff00) ^ crctab_hqx[(crc>>8)^*bin_data++];
     }
 
-    return crc;
+    return PyLong_FromUnsignedLong(crc);
 }
 
 #ifndef USE_ZLIB_CRC32
index 82942f08a68681fe98f4b8d7735ab9247373c061..4d02c72c472e1d89a7fd59cc4129169cc2034a42 100644 (file)
@@ -328,7 +328,7 @@ PyDoc_STRVAR(binascii_crc_hqx__doc__,
 #define BINASCII_CRC_HQX_METHODDEF    \
     {"crc_hqx", (PyCFunction)(void(*)(void))binascii_crc_hqx, METH_FASTCALL, binascii_crc_hqx__doc__},
 
-static unsigned int
+static PyObject *
 binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc);
 
 static PyObject *
@@ -337,7 +337,6 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     PyObject *return_value = NULL;
     Py_buffer data = {NULL, NULL};
     unsigned int crc;
-    unsigned int _return_value;
 
     if (!_PyArg_CheckPositional("crc_hqx", nargs, 2, 2)) {
         goto exit;
@@ -358,11 +357,7 @@ binascii_crc_hqx(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
     if (crc == (unsigned int)-1 && PyErr_Occurred()) {
         goto exit;
     }
-    _return_value = binascii_crc_hqx_impl(module, &data, crc);
-    if ((_return_value == (unsigned int)-1) && PyErr_Occurred()) {
-        goto exit;
-    }
-    return_value = PyLong_FromUnsignedLong((unsigned long)_return_value);
+    return_value = binascii_crc_hqx_impl(module, &data, crc);
 
 exit:
     /* Cleanup for data */
@@ -801,4 +796,4 @@ exit:
 
     return return_value;
 }
-/*[clinic end generated code: output=ec26d03c2007eaac input=a9049054013a1b77]*/
+/*[clinic end generated code: output=a1e878d3963b615e input=a9049054013a1b77]*/