diff options
author | Xiang Zhang <angwerzx@126.com> | 2017-05-03 03:16:21 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-03 03:16:21 (GMT) |
commit | 13f1f423fac39f8f14a3ce919dd236975517d5c6 (patch) | |
tree | 674546ddbbbfaf930c0087eeb1621fab11e25d5f /Lib | |
parent | 0360a9d015ddbc4e3d58e3ab4b433da27bf1db3a (diff) | |
download | cpython-13f1f423fac39f8f14a3ce919dd236975517d5c6.zip cpython-13f1f423fac39f8f14a3ce919dd236975517d5c6.tar.gz cpython-13f1f423fac39f8f14a3ce919dd236975517d5c6.tar.bz2 |
bpo-30103: Allow Uuencode in Python using backtick as zero instead of space (#1326)
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_binascii.py | 36 | ||||
-rw-r--r-- | Lib/test/test_uu.py | 83 | ||||
-rwxr-xr-x | Lib/uu.py | 13 |
3 files changed, 81 insertions, 51 deletions
diff --git a/Lib/test/test_binascii.py b/Lib/test/test_binascii.py index 6b3e437..8fa57cd 100644 --- a/Lib/test/test_binascii.py +++ b/Lib/test/test_binascii.py @@ -112,29 +112,41 @@ class BinASCIITest(unittest.TestCase): def test_uu(self): MAX_UU = 45 - lines = [] - for i in range(0, len(self.data), MAX_UU): - b = self.type2test(self.rawdata[i:i+MAX_UU]) - a = binascii.b2a_uu(b) - lines.append(a) - res = bytes() - for line in lines: - a = self.type2test(line) - b = binascii.a2b_uu(a) - res += b - self.assertEqual(res, self.rawdata) + for backtick in (True, False): + lines = [] + for i in range(0, len(self.data), MAX_UU): + b = self.type2test(self.rawdata[i:i+MAX_UU]) + a = binascii.b2a_uu(b, backtick=backtick) + lines.append(a) + res = bytes() + for line in lines: + a = self.type2test(line) + b = binascii.a2b_uu(a) + res += b + self.assertEqual(res, self.rawdata) self.assertEqual(binascii.a2b_uu(b"\x7f"), b"\x00"*31) self.assertEqual(binascii.a2b_uu(b"\x80"), b"\x00"*32) self.assertEqual(binascii.a2b_uu(b"\xff"), b"\x00"*31) self.assertRaises(binascii.Error, binascii.a2b_uu, b"\xff\x00") self.assertRaises(binascii.Error, binascii.a2b_uu, b"!!!!") - self.assertRaises(binascii.Error, binascii.b2a_uu, 46*b"!") # Issue #7701 (crash on a pydebug build) self.assertEqual(binascii.b2a_uu(b'x'), b'!> \n') + self.assertEqual(binascii.b2a_uu(b''), b' \n') + self.assertEqual(binascii.b2a_uu(b'', backtick=True), b'`\n') + self.assertEqual(binascii.a2b_uu(b' \n'), b'') + self.assertEqual(binascii.a2b_uu(b'`\n'), b'') + self.assertEqual(binascii.b2a_uu(b'\x00Cat'), b'$ $-A= \n') + self.assertEqual(binascii.b2a_uu(b'\x00Cat', backtick=True), + b'$`$-A=```\n') + self.assertEqual(binascii.a2b_uu(b'$`$-A=```\n'), + binascii.a2b_uu(b'$ $-A= \n')) + with self.assertRaises(TypeError): + binascii.b2a_uu(b"", True) + 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) diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py index ad2f2c5..11bd08c 100644 --- a/Lib/test/test_uu.py +++ b/Lib/test/test_uu.py @@ -10,11 +10,11 @@ import sys, os import uu import io -plaintext = b"The smooth-scaled python crept over the sleeping dog\n" +plaintext = b"The symbols on top of your keyboard are !@#$%^&*()_+|~\n" encodedtext = b"""\ -M5&AE('-M;V]T:\"US8V%L960@<'ET:&]N(&-R97!T(&]V97(@=&AE('-L965P -(:6YG(&1O9PH """ +M5&AE('-Y;6)O;',@;VX@=&]P(&]F('EO=7(@:V5Y8F]A<F0@87)E("% (R0E +*7B8J*"E?*WQ^"@ """ # Stolen from io.py class FakeIO(io.TextIOWrapper): @@ -44,9 +44,14 @@ class FakeIO(io.TextIOWrapper): return self.buffer.getvalue().decode(self._encoding, self._errors) -def encodedtextwrapped(mode, filename): - return (bytes("begin %03o %s\n" % (mode, filename), "ascii") + - encodedtext + b"\n \nend\n") +def encodedtextwrapped(mode, filename, backtick=False): + if backtick: + res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") + + encodedtext.replace(b' ', b'`') + b"\n`\nend\n") + else: + res = (bytes("begin %03o %s\n" % (mode, filename), "ascii") + + encodedtext + b"\n \nend\n") + return res class UUTest(unittest.TestCase): @@ -59,20 +64,27 @@ class UUTest(unittest.TestCase): out = io.BytesIO() uu.encode(inp, out, "t1", 0o644) self.assertEqual(out.getvalue(), encodedtextwrapped(0o644, "t1")) + inp = io.BytesIO(plaintext) + out = io.BytesIO() + uu.encode(inp, out, "t1", backtick=True) + self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1", True)) + with self.assertRaises(TypeError): + uu.encode(inp, out, "t1", 0o644, True) def test_decode(self): - inp = io.BytesIO(encodedtextwrapped(0o666, "t1")) - out = io.BytesIO() - uu.decode(inp, out) - self.assertEqual(out.getvalue(), plaintext) - inp = io.BytesIO( - b"UUencoded files may contain many lines,\n" + - b"even some that have 'begin' in them.\n" + - encodedtextwrapped(0o666, "t1") - ) - out = io.BytesIO() - uu.decode(inp, out) - self.assertEqual(out.getvalue(), plaintext) + for backtick in True, False: + inp = io.BytesIO(encodedtextwrapped(0o666, "t1", backtick=backtick)) + out = io.BytesIO() + uu.decode(inp, out) + self.assertEqual(out.getvalue(), plaintext) + inp = io.BytesIO( + b"UUencoded files may contain many lines,\n" + + b"even some that have 'begin' in them.\n" + + encodedtextwrapped(0o666, "t1", backtick=backtick) + ) + out = io.BytesIO() + uu.decode(inp, out) + self.assertEqual(out.getvalue(), plaintext) def test_truncatedinput(self): inp = io.BytesIO(b"begin 644 t1\n" + encodedtext) @@ -94,25 +106,33 @@ class UUTest(unittest.TestCase): def test_garbage_padding(self): # Issue #22406 - encodedtext = ( + encodedtext1 = ( b"begin 644 file\n" # length 1; bits 001100 111111 111111 111111 b"\x21\x2C\x5F\x5F\x5F\n" b"\x20\n" b"end\n" ) + encodedtext2 = ( + b"begin 644 file\n" + # length 1; bits 001100 111111 111111 111111 + b"\x21\x2C\x5F\x5F\x5F\n" + b"\x60\n" + b"end\n" + ) plaintext = b"\x33" # 00110011 - with self.subTest("uu.decode()"): - inp = io.BytesIO(encodedtext) - out = io.BytesIO() - uu.decode(inp, out, quiet=True) - self.assertEqual(out.getvalue(), plaintext) + for encodedtext in encodedtext1, encodedtext2: + with self.subTest("uu.decode()"): + inp = io.BytesIO(encodedtext) + out = io.BytesIO() + uu.decode(inp, out, quiet=True) + self.assertEqual(out.getvalue(), plaintext) - with self.subTest("uu_codec"): - import codecs - decoded = codecs.decode(encodedtext, "uu_codec") - self.assertEqual(decoded, plaintext) + with self.subTest("uu_codec"): + import codecs + decoded = codecs.decode(encodedtext, "uu_codec") + self.assertEqual(decoded, plaintext) class UUStdIOTest(unittest.TestCase): @@ -250,11 +270,6 @@ class UUFileTest(unittest.TestCase): finally: self._kill(f) -def test_main(): - support.run_unittest(UUTest, - UUStdIOTest, - UUFileTest, - ) if __name__=="__main__": - test_main() + unittest.main() @@ -26,8 +26,8 @@ """Implementation of the UUencode and UUdecode functions. -encode(in_file, out_file [,name, mode]) -decode(in_file [, out_file, mode]) +encode(in_file, out_file [,name, mode], *, backtick=False) +decode(in_file [, out_file, mode, quiet]) """ import binascii @@ -39,7 +39,7 @@ __all__ = ["Error", "encode", "decode"] class Error(Exception): pass -def encode(in_file, out_file, name=None, mode=None): +def encode(in_file, out_file, name=None, mode=None, *, backtick=False): """Uuencode file""" # # If in_file is a pathname open it and change defaults @@ -79,9 +79,12 @@ def encode(in_file, out_file, name=None, mode=None): out_file.write(('begin %o %s\n' % ((mode & 0o777), name)).encode("ascii")) data = in_file.read(45) while len(data) > 0: - out_file.write(binascii.b2a_uu(data)) + out_file.write(binascii.b2a_uu(data, backtick=backtick)) data = in_file.read(45) - out_file.write(b' \nend\n') + if backtick: + out_file.write(b'`\nend\n') + else: + out_file.write(b' \nend\n') finally: for f in opened_files: f.close() |