Skip to content

Commit beea26b

Browse files
authored
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()
1 parent 14d80d0 commit beea26b

File tree

9 files changed

+120
-25
lines changed

9 files changed

+120
-25
lines changed

Doc/library/binascii.rst

+10
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ The :mod:`binascii` module defines the following functions:
9292
The string should contain a complete number of binary bytes, or (in case of the
9393
last portion of the binhex4 data) have the remaining bits zero.
9494

95+
.. deprecated:: 3.9
96+
9597

9698
.. function:: rledecode_hqx(data)
9799

@@ -104,18 +106,24 @@ The :mod:`binascii` module defines the following functions:
104106
.. versionchanged:: 3.2
105107
Accept only bytestring or bytearray objects as input.
106108

109+
.. deprecated:: 3.9
110+
107111

108112
.. function:: rlecode_hqx(data)
109113

110114
Perform binhex4 style RLE-compression on *data* and return the result.
111115

116+
.. deprecated:: 3.9
117+
112118

113119
.. function:: b2a_hqx(data)
114120

115121
Perform hexbin4 binary-to-ASCII translation and return the resulting string. The
116122
argument should already be RLE-coded, and have a length divisible by 3 (except
117123
possibly the last fragment).
118124

125+
.. deprecated:: 3.9
126+
119127

120128
.. function:: crc_hqx(data, value)
121129

@@ -124,6 +132,8 @@ The :mod:`binascii` module defines the following functions:
124132
*x*:sup:`16` + *x*:sup:`12` + *x*:sup:`5` + 1, often represented as
125133
0x1021. This CRC is used in the binhex4 format.
126134

135+
.. deprecated:: 3.9
136+
127137

128138
.. function:: crc32(data[, value])
129139

Doc/library/binhex.rst

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
**Source code:** :source:`Lib/binhex.py`
88

9+
.. deprecated:: 3.9
10+
911
--------------
1012

1113
This module encodes and decodes files in binhex4 format, a format allowing

Doc/whatsnew/3.9.rst

+10
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,16 @@ Deprecated
353353
deprecated and will be removed in version 3.11.
354354
(Contributed by Yury Selivanov and Kyle Stanley in :issue:`34790`.)
355355

356+
* binhex4 and hexbin4 standards are now deprecated. The :`binhex` module
357+
and the following :mod:`binascii` functions are now deprecated:
358+
359+
* :func:`~binascii.b2a_hqx`, :func:`~binascii.a2b_hqx`
360+
* :func:`~binascii.rlecode_hqx`, :func:`~binascii.rledecode_hqx`
361+
* :func:`~binascii.crc_hqx`
362+
363+
(Contributed by Victor Stinner in :issue:`39353`.)
364+
365+
356366
Removed
357367
=======
358368

Lib/binhex.py

+37-12
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@
2121
# input. The resulting code (xx 90 90) would appear to be interpreted as an
2222
# escaped *value* of 0x90. All coders I've seen appear to ignore this nicety...
2323
#
24+
import binascii
25+
import contextlib
2426
import io
2527
import os
2628
import struct
27-
import binascii
29+
import warnings
30+
31+
warnings.warn('the binhex module is deprecated', DeprecationWarning,
32+
stacklevel=2)
33+
2834

2935
__all__ = ["binhex","hexbin","Error"]
3036

@@ -76,6 +82,16 @@ def write(self, *args):
7682
def close(self):
7783
pass
7884

85+
86+
# DeprecationWarning is already emitted on "import binhex". There is no need
87+
# to repeat the warning at each call to deprecated binascii functions.
88+
@contextlib.contextmanager
89+
def _ignore_deprecation_warning():
90+
with warnings.catch_warnings():
91+
warnings.filterwarnings('ignore', '', DeprecationWarning)
92+
yield
93+
94+
7995
class _Hqxcoderengine:
8096
"""Write data to the coder in 3-byte chunks"""
8197

@@ -93,7 +109,8 @@ def write(self, data):
93109
self.data = self.data[todo:]
94110
if not data:
95111
return
96-
self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
112+
with _ignore_deprecation_warning():
113+
self.hqxdata = self.hqxdata + binascii.b2a_hqx(data)
97114
self._flush(0)
98115

99116
def _flush(self, force):
@@ -109,7 +126,8 @@ def _flush(self, force):
109126

110127
def close(self):
111128
if self.data:
112-
self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data)
129+
with _ignore_deprecation_warning():
130+
self.hqxdata = self.hqxdata + binascii.b2a_hqx(self.data)
113131
self._flush(1)
114132
self.ofp.close()
115133
del self.ofp
@@ -125,13 +143,15 @@ def write(self, data):
125143
self.data = self.data + data
126144
if len(self.data) < REASONABLY_LARGE:
127145
return
128-
rledata = binascii.rlecode_hqx(self.data)
146+
with _ignore_deprecation_warning():
147+
rledata = binascii.rlecode_hqx(self.data)
129148
self.ofp.write(rledata)
130149
self.data = b''
131150

132151
def close(self):
133152
if self.data:
134-
rledata = binascii.rlecode_hqx(self.data)
153+
with _ignore_deprecation_warning():
154+
rledata = binascii.rlecode_hqx(self.data)
135155
self.ofp.write(rledata)
136156
self.ofp.close()
137157
del self.ofp
@@ -180,7 +200,8 @@ def _writeinfo(self, name, finfo):
180200
self._writecrc()
181201

182202
def _write(self, data):
183-
self.crc = binascii.crc_hqx(data, self.crc)
203+
with _ignore_deprecation_warning():
204+
self.crc = binascii.crc_hqx(data, self.crc)
184205
self.ofp.write(data)
185206

186207
def _writecrc(self):
@@ -276,7 +297,8 @@ def read(self, totalwtd):
276297
#
277298
while True:
278299
try:
279-
decdatacur, self.eof = binascii.a2b_hqx(data)
300+
with _ignore_deprecation_warning():
301+
decdatacur, self.eof = binascii.a2b_hqx(data)
280302
break
281303
except binascii.Incomplete:
282304
pass
@@ -312,8 +334,9 @@ def read(self, wtd):
312334
def _fill(self, wtd):
313335
self.pre_buffer = self.pre_buffer + self.ifp.read(wtd + 4)
314336
if self.ifp.eof:
315-
self.post_buffer = self.post_buffer + \
316-
binascii.rledecode_hqx(self.pre_buffer)
337+
with _ignore_deprecation_warning():
338+
self.post_buffer = self.post_buffer + \
339+
binascii.rledecode_hqx(self.pre_buffer)
317340
self.pre_buffer = b''
318341
return
319342

@@ -340,8 +363,9 @@ def _fill(self, wtd):
340363
else:
341364
mark = mark - 1
342365

343-
self.post_buffer = self.post_buffer + \
344-
binascii.rledecode_hqx(self.pre_buffer[:mark])
366+
with _ignore_deprecation_warning():
367+
self.post_buffer = self.post_buffer + \
368+
binascii.rledecode_hqx(self.pre_buffer[:mark])
345369
self.pre_buffer = self.pre_buffer[mark:]
346370

347371
def close(self):
@@ -372,7 +396,8 @@ def __init__(self, ifp):
372396

373397
def _read(self, len):
374398
data = self.ifp.read(len)
375-
self.crc = binascii.crc_hqx(data, self.crc)
399+
with _ignore_deprecation_warning():
400+
self.crc = binascii.crc_hqx(data, self.crc)
376401
return data
377402

378403
def _checkcrc(self):

Lib/test/test_binascii.py

+22
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import binascii
55
import array
66
import re
7+
from test import support
78

89
# Note: "*_hex" functions are aliases for "(un)hexlify"
910
b2a_functions = ['b2a_base64', 'b2a_hex', 'b2a_hqx', 'b2a_qp', 'b2a_uu',
@@ -36,6 +37,7 @@ def test_functions(self):
3637
self.assertTrue(hasattr(getattr(binascii, name), '__call__'))
3738
self.assertRaises(TypeError, getattr(binascii, name))
3839

40+
@support.ignore_warnings(category=DeprecationWarning)
3941
def test_returned_value(self):
4042
# Limit to the minimum of all limits (b2a_uu)
4143
MAX_ALL = 45
@@ -179,6 +181,7 @@ def test_uu(self):
179181
with self.assertRaises(TypeError):
180182
binascii.b2a_uu(b"", True)
181183

184+
@support.ignore_warnings(category=DeprecationWarning)
182185
def test_crc_hqx(self):
183186
crc = binascii.crc_hqx(self.type2test(b"Test the CRC-32 of"), 0)
184187
crc = binascii.crc_hqx(self.type2test(b" this string."), crc)
@@ -198,6 +201,7 @@ def test_crc32(self):
198201

199202
self.assertRaises(TypeError, binascii.crc32)
200203

204+
@support.ignore_warnings(category=DeprecationWarning)
201205
def test_hqx(self):
202206
# Perform binhex4 style RLE-compression
203207
# Then calculate the hexbin4 binary-to-ASCII translation
@@ -208,6 +212,7 @@ def test_hqx(self):
208212
res = binascii.rledecode_hqx(b)
209213
self.assertEqual(res, self.rawdata)
210214

215+
@support.ignore_warnings(category=DeprecationWarning)
211216
def test_rle(self):
212217
# test repetition with a repetition longer than the limit of 255
213218
data = (b'a' * 100 + b'b' + b'c' * 300)
@@ -354,6 +359,7 @@ def test_qp(self):
354359
self.assertEqual(b2a_qp(type2test(b'a.\n')), b'a.\n')
355360
self.assertEqual(b2a_qp(type2test(b'.a')[:-1]), b'=2E')
356361

362+
@support.ignore_warnings(category=DeprecationWarning)
357363
def test_empty_string(self):
358364
# A test for SF bug #1022953. Make sure SystemError is not raised.
359365
empty = self.type2test(b'')
@@ -378,6 +384,7 @@ def test_unicode_b2a(self):
378384
# crc_hqx needs 2 arguments
379385
self.assertRaises(TypeError, binascii.crc_hqx, "test", 0)
380386

387+
@support.ignore_warnings(category=DeprecationWarning)
381388
def test_unicode_a2b(self):
382389
# Unicode strings are accepted by a2b_* functions.
383390
MAX_ALL = 45
@@ -416,6 +423,21 @@ def test_b2a_base64_newline(self):
416423
self.assertEqual(binascii.b2a_base64(b, newline=False),
417424
b'aGVsbG8=')
418425

426+
def test_deprecated_warnings(self):
427+
with self.assertWarns(DeprecationWarning):
428+
self.assertEqual(binascii.b2a_hqx(b'abc'), b'B@*M')
429+
with self.assertWarns(DeprecationWarning):
430+
self.assertEqual(binascii.a2b_hqx(b'B@*M'), (b'abc', 0))
431+
432+
with self.assertWarns(DeprecationWarning):
433+
self.assertEqual(binascii.rlecode_hqx(b'a' * 10), b'a\x90\n')
434+
435+
with self.assertWarns(DeprecationWarning):
436+
self.assertEqual(binascii.rledecode_hqx(b'a\x90\n'), b'a' * 10)
437+
438+
with self.assertWarns(DeprecationWarning):
439+
self.assertEqual(binascii.crc_hqx(b'abc', 0), 40406)
440+
419441

420442
class ArrayBinASCIITest(BinASCIITest):
421443
def type2test(self, s):

Lib/test/test_binhex.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
Uses the mechanism of the python binhex module
44
Based on an original test by Roger E. Masse.
55
"""
6-
import binhex
76
import unittest
87
from test import support
98

9+
with support.check_warnings(('', DeprecationWarning)):
10+
import binhex
11+
1012

1113
class BinHexTestCase(unittest.TestCase):
1214

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Deprecate binhex4 and hexbin4 standards. Deprecate the :mod:`binhex` module and
2+
the following :mod:`binascii` functions: :func:`~binascii.b2a_hqx`,
3+
:func:`~binascii.a2b_hqx`, :func:`~binascii.rlecode_hqx`,
4+
:func:`~binascii.rledecode_hqx`, :func:`~binascii.crc_hqx`.

Modules/binascii.c

+29-4
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,11 @@ static PyObject *
613613
binascii_a2b_hqx_impl(PyObject *module, Py_buffer *data)
614614
/*[clinic end generated code: output=4d6d8c54d54ea1c1 input=0d914c680e0eed55]*/
615615
{
616+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
617+
"binascii.a2b_hqx() is deprecated", 1) < 0) {
618+
return NULL;
619+
}
620+
616621
const unsigned char *ascii_data;
617622
unsigned char *bin_data;
618623
int leftbits = 0;
@@ -701,6 +706,11 @@ static PyObject *
701706
binascii_rlecode_hqx_impl(PyObject *module, Py_buffer *data)
702707
/*[clinic end generated code: output=393d79338f5f5629 input=e1f1712447a82b09]*/
703708
{
709+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
710+
"binascii.rlecode_hqx() is deprecated", 1) < 0) {
711+
return NULL;
712+
}
713+
704714
const unsigned char *in_data;
705715
unsigned char *out_data;
706716
unsigned char ch;
@@ -763,6 +773,11 @@ static PyObject *
763773
binascii_b2a_hqx_impl(PyObject *module, Py_buffer *data)
764774
/*[clinic end generated code: output=d0aa5a704bc9f7de input=9596ebe019fe12ba]*/
765775
{
776+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
777+
"binascii.b2a_hqx() is deprecated", 1) < 0) {
778+
return NULL;
779+
}
780+
766781
unsigned char *ascii_data;
767782
const unsigned char *bin_data;
768783
int leftbits = 0;
@@ -818,6 +833,11 @@ static PyObject *
818833
binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
819834
/*[clinic end generated code: output=9826619565de1c6c input=54cdd49fc014402c]*/
820835
{
836+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
837+
"binascii.rledecode_hqx() is deprecated", 1) < 0) {
838+
return NULL;
839+
}
840+
821841
const unsigned char *in_data;
822842
unsigned char *out_data;
823843
unsigned char in_byte, in_repeat;
@@ -932,7 +952,7 @@ binascii_rledecode_hqx_impl(PyObject *module, Py_buffer *data)
932952

933953

934954
/*[clinic input]
935-
binascii.crc_hqx -> unsigned_int
955+
binascii.crc_hqx
936956
937957
data: Py_buffer
938958
crc: unsigned_int(bitwise=True)
@@ -941,10 +961,15 @@ binascii.crc_hqx -> unsigned_int
941961
Compute CRC-CCITT incrementally.
942962
[clinic start generated code]*/
943963

944-
static unsigned int
964+
static PyObject *
945965
binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc)
946-
/*[clinic end generated code: output=8ec2a78590d19170 input=f18240ff8c705b79]*/
966+
/*[clinic end generated code: output=2fde213d0f547a98 input=56237755370a951c]*/
947967
{
968+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
969+
"binascii.crc_hqx() is deprecated", 1) < 0) {
970+
return NULL;
971+
}
972+
948973
const unsigned char *bin_data;
949974
Py_ssize_t len;
950975

@@ -956,7 +981,7 @@ binascii_crc_hqx_impl(PyObject *module, Py_buffer *data, unsigned int crc)
956981
crc = ((crc<<8)&0xff00) ^ crctab_hqx[(crc>>8)^*bin_data++];
957982
}
958983

959-
return crc;
984+
return PyLong_FromUnsignedLong(crc);
960985
}
961986

962987
#ifndef USE_ZLIB_CRC32

0 commit comments

Comments
 (0)