[Python-checkins] gh-104773: PEP 594: Remove the uu module (#104932)

vstinner webhook-mailer at python.org
Thu May 25 10:25:34 EDT 2023


https://github.com/python/cpython/commit/dbc8216f4c00ea40b0c2d3ca487e5afeb4b0e0b1
commit: dbc8216f4c00ea40b0c2d3ca487e5afeb4b0e0b1
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2023-05-25T16:25:27+02:00
summary:

gh-104773: PEP 594: Remove the uu module (#104932)

Doc/license.rst: Keep the UUencode and UUdecode license since it's
also used by the uu codec.

files:
A Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst
D Doc/library/uu.rst
D Lib/test/test_uu.py
D Lib/uu.py
M Doc/library/binascii.rst
M Doc/library/superseded.rst
M Doc/license.rst
M Doc/whatsnew/3.11.rst
M Doc/whatsnew/3.12.rst
M Doc/whatsnew/3.13.rst
M Doc/whatsnew/3.7.rst
M Misc/NEWS.d/3.12.0b1.rst
M Python/stdlib_module_names.h
M Tools/wasm/wasm_assets.py

diff --git a/Doc/library/binascii.rst b/Doc/library/binascii.rst
index 21960cb7972e..e9f6f0e09de2 100644
--- a/Doc/library/binascii.rst
+++ b/Doc/library/binascii.rst
@@ -6,14 +6,13 @@
               representations.
 
 .. index::
-   pair: module; uu
    pair: module; base64
 
 --------------
 
 The :mod:`binascii` module contains a number of methods to convert between
 binary and various ASCII-encoded binary representations. Normally, you will not
-use these functions directly but use wrapper modules like :mod:`uu` or
+use these functions directly but use wrapper modules like
 :mod:`base64` instead. The :mod:`binascii` module contains
 low-level functions written in C for greater speed that are used by the
 higher-level modules.
@@ -179,8 +178,5 @@ The :mod:`binascii` module defines the following functions:
       Support for RFC compliant base64-style encoding in base 16, 32, 64,
       and 85.
 
-   Module :mod:`uu`
-      Support for UU encoding used on Unix.
-
    Module :mod:`quopri`
       Support for quoted-printable encoding used in MIME email messages.
diff --git a/Doc/library/superseded.rst b/Doc/library/superseded.rst
index 284716e8845d..7e05f0edf4b1 100644
--- a/Doc/library/superseded.rst
+++ b/Doc/library/superseded.rst
@@ -15,4 +15,3 @@ backwards compatibility. They have been superseded by other modules.
    chunk.rst
    imghdr.rst
    optparse.rst
-   uu.rst
diff --git a/Doc/library/uu.rst b/Doc/library/uu.rst
deleted file mode 100644
index 83c4aec47bbe..000000000000
--- a/Doc/library/uu.rst
+++ /dev/null
@@ -1,72 +0,0 @@
-:mod:`uu` --- Encode and decode uuencode files
-==============================================
-
-.. module:: uu
-   :synopsis: Encode and decode files in uuencode format.
-   :deprecated:
-
-.. moduleauthor:: Lance Ellinghouse
-
-**Source code:** :source:`Lib/uu.py`
-
-.. deprecated-removed:: 3.11 3.13
-   The :mod:`uu` module is deprecated
-   (see :pep:`PEP 594 <594#uu-and-the-uu-encoding>` for details).
-   :mod:`base64` is a modern alternative.
-
---------------
-
-This module encodes and decodes files in uuencode format, allowing arbitrary
-binary data to be transferred over ASCII-only connections. Wherever a file
-argument is expected, the methods accept a file-like object.  For backwards
-compatibility, a string containing a pathname is also accepted, and the
-corresponding file will be opened for reading and writing; the pathname ``'-'``
-is understood to mean the standard input or output.  However, this interface is
-deprecated; it's better for the caller to open the file itself, and be sure
-that, when required, the mode is ``'rb'`` or ``'wb'`` on Windows.
-
-.. index::
-   single: Jansen, Jack
-   single: Ellinghouse, Lance
-
-This code was contributed by Lance Ellinghouse, and modified by Jack Jansen.
-
-The :mod:`uu` module defines the following functions:
-
-
-.. function:: encode(in_file, out_file, name=None, mode=None, *, backtick=False)
-
-   Uuencode file *in_file* into file *out_file*.  The uuencoded file will have
-   the header specifying *name* and *mode* as the defaults for the results of
-   decoding the file. The default defaults are taken from *in_file*, or ``'-'``
-   and ``0o666`` respectively.  If *backtick* is true, zeros are represented by
-   ``'`'`` instead of spaces.
-
-   .. versionchanged:: 3.7
-      Added the *backtick* parameter.
-
-
-.. function:: decode(in_file, out_file=None, mode=None, quiet=False)
-
-   This call decodes uuencoded file *in_file* placing the result on file
-   *out_file*. If *out_file* is a pathname, *mode* is used to set the permission
-   bits if the file must be created. Defaults for *out_file* and *mode* are taken
-   from the uuencode header.  However, if the file specified in the header already
-   exists, a :exc:`uu.Error` is raised.
-
-   :func:`decode` may print a warning to standard error if the input was produced
-   by an incorrect uuencoder and Python could recover from that error.  Setting
-   *quiet* to a true value silences this warning.
-
-
-.. exception:: Error()
-
-   Subclass of :exc:`Exception`, this can be raised by :func:`uu.decode` under
-   various situations, such as described above, but also including a badly
-   formatted header, or truncated input file.
-
-
-.. seealso::
-
-   Module :mod:`binascii`
-      Support module containing ASCII-to-binary and binary-to-ASCII conversions.
diff --git a/Doc/license.rst b/Doc/license.rst
index 947a9b1a8c5a..4b7113bdcf6d 100644
--- a/Doc/license.rst
+++ b/Doc/license.rst
@@ -476,7 +476,7 @@ The :mod:`trace` module contains the following notice::
 UUencode and UUdecode functions
 -------------------------------
 
-The :mod:`uu` module contains the following notice::
+The ``uu`` codec contains the following notice::
 
    Copyright 1994 by Lance Ellinghouse
    Cathedral City, California Republic, United States of America.
diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst
index efff13211c79..ece273c7d090 100644
--- a/Doc/whatsnew/3.11.rst
+++ b/Doc/whatsnew/3.11.rst
@@ -1733,7 +1733,7 @@ Modules
   +---------------------+---------------------+---------------------+---------------------+---------------------+
   | :mod:`aifc`         | :mod:`chunk`        | :mod:`!msilib`      | :mod:`!pipes`       | :mod:`!telnetlib`   |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
-  | :mod:`audioop`      | :mod:`!crypt`       | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`uu`           |
+  | :mod:`audioop`      | :mod:`!crypt`       | :mod:`!nis`         | :mod:`!sndhdr`      | :mod:`!uu`          |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
   | :mod:`!cgi`         | :mod:`imghdr`       | :mod:`!nntplib`     | :mod:`!spwd`        | :mod:`!xdrlib`      |
   +---------------------+---------------------+---------------------+---------------------+---------------------+
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index f01cc27f7062..7c184063fba5 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -935,7 +935,7 @@ Modules (see :pep:`594`):
 * :mod:`!spwd`
 * :mod:`!sunau`
 * :mod:`!telnetlib`
-* :mod:`uu`
+* :mod:`!uu`
 * :mod:`!xdrlib`
 
 APIs:
diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst
index f570e0354daf..38526e1df87a 100644
--- a/Doc/whatsnew/3.13.rst
+++ b/Doc/whatsnew/3.13.rst
@@ -217,6 +217,10 @@ Removed
 
   (Contributed by Victor Stinner in :gh:`104773`.)
 
+* :pep:`594`: Remove the :mod:`!uu` module, deprecated in Python 3.11:
+  the :mod:`base64` module is a modern alternative.
+  (Contributed by Victor Stinner in :gh:`104773`.)
+
 
 Porting to Python 3.13
 ======================
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index 93915b2030e1..fa89b7db9736 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -1547,7 +1547,7 @@ adding ``~`` to the set of characters that are never quoted by default.
 uu
 --
 
-The :func:`uu.encode` function now accepts an optional *backtick*
+The :func:`!uu.encode` function now accepts an optional *backtick*
 keyword argument.  When it's true, zeros are represented by ``'`'``
 instead of spaces.  (Contributed by Xiang Zhang in :issue:`30103`.)
 
diff --git a/Lib/test/test_uu.py b/Lib/test/test_uu.py
deleted file mode 100644
index a189d6bc4b05..000000000000
--- a/Lib/test/test_uu.py
+++ /dev/null
@@ -1,287 +0,0 @@
-"""
-Tests for uu module.
-Nick Mathewson
-"""
-
-import unittest
-from test.support import os_helper, warnings_helper
-
-uu = warnings_helper.import_deprecated("uu")
-
-import os
-import stat
-import sys
-import io
-
-plaintext = b"The symbols on top of your keyboard are !@#$%^&*()_+|~\n"
-
-encodedtext = b"""\
-M5&AE('-Y;6)O;',@;VX@=&]P(&]F('EO=7(@:V5Y8F]A<F0 at 87)E("% (R0E
-*7B8J*"E?*WQ^"@  """
-
-# Stolen from io.py
-class FakeIO(io.TextIOWrapper):
-    """Text I/O implementation using an in-memory buffer.
-
-    Can be a used as a drop-in replacement for sys.stdin and sys.stdout.
-    """
-
-    # XXX This is really slow, but fully functional
-
-    def __init__(self, initial_value="", encoding="utf-8",
-                 errors="strict", newline="\n"):
-        super(FakeIO, self).__init__(io.BytesIO(),
-                                     encoding=encoding,
-                                     errors=errors,
-                                     newline=newline)
-        self._encoding = encoding
-        self._errors = errors
-        if initial_value:
-            if not isinstance(initial_value, str):
-                initial_value = str(initial_value)
-            self.write(initial_value)
-            self.seek(0)
-
-    def getvalue(self):
-        self.flush()
-        return self.buffer.getvalue().decode(self._encoding, self._errors)
-
-
-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):
-
-    def test_encode(self):
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        uu.encode(inp, out, "t1")
-        self.assertEqual(out.getvalue(), encodedtextwrapped(0o666, "t1"))
-        inp = io.BytesIO(plaintext)
-        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)
-
-    @os_helper.skip_unless_working_chmod
-    def test_decode(self):
-        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)
-        out = io.BytesIO()
-        try:
-            uu.decode(inp, out)
-            self.fail("No exception raised")
-        except uu.Error as e:
-            self.assertEqual(str(e), "Truncated input file")
-
-    def test_missingbegin(self):
-        inp = io.BytesIO(b"")
-        out = io.BytesIO()
-        try:
-            uu.decode(inp, out)
-            self.fail("No exception raised")
-        except uu.Error as e:
-            self.assertEqual(str(e), "No valid begin line found in input file")
-
-    def test_garbage_padding(self):
-        # Issue #22406
-        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
-
-        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)
-
-    def test_newlines_escaped(self):
-        # Test newlines are escaped with uu.encode
-        inp = io.BytesIO(plaintext)
-        out = io.BytesIO()
-        filename = "test.txt\n\roverflow.txt"
-        safefilename = b"test.txt\\n\\roverflow.txt"
-        uu.encode(inp, out, filename)
-        self.assertIn(safefilename, out.getvalue())
-
-    def test_no_directory_traversal(self):
-        relative_bad = b"""\
-begin 644 ../../../../../../../../tmp/test1
-$86)C"@``
-`
-end
-"""
-        with self.assertRaisesRegex(uu.Error, 'directory'):
-            uu.decode(io.BytesIO(relative_bad))
-        if os.altsep:
-            relative_bad_bs = relative_bad.replace(b'/', b'\\')
-            with self.assertRaisesRegex(uu.Error, 'directory'):
-                uu.decode(io.BytesIO(relative_bad_bs))
-
-        absolute_bad = b"""\
-begin 644 /tmp/test2
-$86)C"@``
-`
-end
-"""
-        with self.assertRaisesRegex(uu.Error, 'directory'):
-            uu.decode(io.BytesIO(absolute_bad))
-        if os.altsep:
-            absolute_bad_bs = absolute_bad.replace(b'/', b'\\')
-            with self.assertRaisesRegex(uu.Error, 'directory'):
-                uu.decode(io.BytesIO(absolute_bad_bs))
-
-
-class UUStdIOTest(unittest.TestCase):
-
-    def setUp(self):
-        self.stdin = sys.stdin
-        self.stdout = sys.stdout
-
-    def tearDown(self):
-        sys.stdin = self.stdin
-        sys.stdout = self.stdout
-
-    def test_encode(self):
-        sys.stdin = FakeIO(plaintext.decode("ascii"))
-        sys.stdout = FakeIO()
-        uu.encode("-", "-", "t1", 0o666)
-        self.assertEqual(sys.stdout.getvalue(),
-                         encodedtextwrapped(0o666, "t1").decode("ascii"))
-
-    def test_decode(self):
-        sys.stdin = FakeIO(encodedtextwrapped(0o666, "t1").decode("ascii"))
-        sys.stdout = FakeIO()
-        uu.decode("-", "-")
-        stdout = sys.stdout
-        sys.stdout = self.stdout
-        sys.stdin = self.stdin
-        self.assertEqual(stdout.getvalue(), plaintext.decode("ascii"))
-
-class UUFileTest(unittest.TestCase):
-
-    def setUp(self):
-        # uu.encode() supports only ASCII file names
-        self.tmpin  = os_helper.TESTFN_ASCII + "i"
-        self.tmpout = os_helper.TESTFN_ASCII + "o"
-        self.addCleanup(os_helper.unlink, self.tmpin)
-        self.addCleanup(os_helper.unlink, self.tmpout)
-
-    def test_encode(self):
-        with open(self.tmpin, 'wb') as fin:
-            fin.write(plaintext)
-
-        with open(self.tmpin, 'rb') as fin:
-            with open(self.tmpout, 'wb') as fout:
-                uu.encode(fin, fout, self.tmpin, mode=0o644)
-
-        with open(self.tmpout, 'rb') as fout:
-            s = fout.read()
-        self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
-
-        # in_file and out_file as filenames
-        uu.encode(self.tmpin, self.tmpout, self.tmpin, mode=0o644)
-        with open(self.tmpout, 'rb') as fout:
-            s = fout.read()
-        self.assertEqual(s, encodedtextwrapped(0o644, self.tmpin))
-
-    # decode() calls chmod()
-    @os_helper.skip_unless_working_chmod
-    def test_decode(self):
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        with open(self.tmpout, 'rb') as f:
-            s = f.read()
-        self.assertEqual(s, plaintext)
-        # XXX is there an xp way to verify the mode?
-
-    @os_helper.skip_unless_working_chmod
-    def test_decode_filename(self):
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-
-        uu.decode(self.tmpin)
-
-        with open(self.tmpout, 'rb') as f:
-            s = f.read()
-        self.assertEqual(s, plaintext)
-
-    @os_helper.skip_unless_working_chmod
-    def test_decodetwice(self):
-        # Verify that decode() will refuse to overwrite an existing file
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(0o644, self.tmpout))
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        with open(self.tmpin, 'rb') as f:
-            self.assertRaises(uu.Error, uu.decode, f)
-
-    @os_helper.skip_unless_working_chmod
-    def test_decode_mode(self):
-        # Verify that decode() will set the given mode for the out_file
-        expected_mode = 0o444
-        with open(self.tmpin, 'wb') as f:
-            f.write(encodedtextwrapped(expected_mode, self.tmpout))
-
-        # make file writable again, so it can be removed (Windows only)
-        self.addCleanup(os.chmod, self.tmpout, expected_mode | stat.S_IWRITE)
-
-        with open(self.tmpin, 'rb') as f:
-            uu.decode(f)
-
-        self.assertEqual(
-            stat.S_IMODE(os.stat(self.tmpout).st_mode),
-            expected_mode
-        )
-
-
-if __name__=="__main__":
-    unittest.main()
diff --git a/Lib/uu.py b/Lib/uu.py
deleted file mode 100644
index 26bb59ae073e..000000000000
--- a/Lib/uu.py
+++ /dev/null
@@ -1,216 +0,0 @@
-#! /usr/bin/env python3
-
-# Copyright 1994 by Lance Ellinghouse
-# Cathedral City, California Republic, United States of America.
-#                        All Rights Reserved
-# Permission to use, copy, modify, and distribute this software and its
-# documentation for any purpose and without fee is hereby granted,
-# provided that the above copyright notice appear in all copies and that
-# both that copyright notice and this permission notice appear in
-# supporting documentation, and that the name of Lance Ellinghouse
-# not be used in advertising or publicity pertaining to distribution
-# of the software without specific, written prior permission.
-# LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
-# THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-# FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
-# FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-#
-# Modified by Jack Jansen, CWI, July 1995:
-# - Use binascii module to do the actual line-by-line conversion
-#   between ascii and binary. This results in a 1000-fold speedup. The C
-#   version is still 5 times faster, though.
-# - Arguments more compliant with python standard
-
-"""Implementation of the UUencode and UUdecode functions.
-
-encode(in_file, out_file [,name, mode], *, backtick=False)
-decode(in_file [, out_file, mode, quiet])
-"""
-
-import binascii
-import os
-import sys
-import warnings
-
-warnings._deprecated(__name__, remove=(3, 13))
-
-__all__ = ["Error", "encode", "decode"]
-
-class Error(Exception):
-    pass
-
-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
-    #
-    opened_files = []
-    try:
-        if in_file == '-':
-            in_file = sys.stdin.buffer
-        elif isinstance(in_file, str):
-            if name is None:
-                name = os.path.basename(in_file)
-            if mode is None:
-                try:
-                    mode = os.stat(in_file).st_mode
-                except AttributeError:
-                    pass
-            in_file = open(in_file, 'rb')
-            opened_files.append(in_file)
-        #
-        # Open out_file if it is a pathname
-        #
-        if out_file == '-':
-            out_file = sys.stdout.buffer
-        elif isinstance(out_file, str):
-            out_file = open(out_file, 'wb')
-            opened_files.append(out_file)
-        #
-        # Set defaults for name and mode
-        #
-        if name is None:
-            name = '-'
-        if mode is None:
-            mode = 0o666
-
-        #
-        # Remove newline chars from name
-        #
-        name = name.replace('\n','\\n')
-        name = name.replace('\r','\\r')
-
-        #
-        # Write the data
-        #
-        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, backtick=backtick))
-            data = in_file.read(45)
-        if backtick:
-            out_file.write(b'`\nend\n')
-        else:
-            out_file.write(b' \nend\n')
-    finally:
-        for f in opened_files:
-            f.close()
-
-
-def decode(in_file, out_file=None, mode=None, quiet=False):
-    """Decode uuencoded file"""
-    #
-    # Open the input file, if needed.
-    #
-    opened_files = []
-    if in_file == '-':
-        in_file = sys.stdin.buffer
-    elif isinstance(in_file, str):
-        in_file = open(in_file, 'rb')
-        opened_files.append(in_file)
-
-    try:
-        #
-        # Read until a begin is encountered or we've exhausted the file
-        #
-        while True:
-            hdr = in_file.readline()
-            if not hdr:
-                raise Error('No valid begin line found in input file')
-            if not hdr.startswith(b'begin'):
-                continue
-            hdrfields = hdr.split(b' ', 2)
-            if len(hdrfields) == 3 and hdrfields[0] == b'begin':
-                try:
-                    int(hdrfields[1], 8)
-                    break
-                except ValueError:
-                    pass
-        if out_file is None:
-            # If the filename isn't ASCII, what's up with that?!?
-            out_file = hdrfields[2].rstrip(b' \t\r\n\f').decode("ascii")
-            if os.path.exists(out_file):
-                raise Error(f'Cannot overwrite existing file: {out_file}')
-            if (out_file.startswith(os.sep) or
-                f'..{os.sep}' in out_file or (
-                    os.altsep and
-                    (out_file.startswith(os.altsep) or
-                     f'..{os.altsep}' in out_file))
-               ):
-                raise Error(f'Refusing to write to {out_file} due to directory traversal')
-        if mode is None:
-            mode = int(hdrfields[1], 8)
-        #
-        # Open the output file
-        #
-        if out_file == '-':
-            out_file = sys.stdout.buffer
-        elif isinstance(out_file, str):
-            fp = open(out_file, 'wb')
-            os.chmod(out_file, mode)
-            out_file = fp
-            opened_files.append(out_file)
-        #
-        # Main decoding loop
-        #
-        s = in_file.readline()
-        while s and s.strip(b' \t\r\n\f') != b'end':
-            try:
-                data = binascii.a2b_uu(s)
-            except binascii.Error as v:
-                # Workaround for broken uuencoders by /Fredrik Lundh
-                nbytes = (((s[0]-32) & 63) * 4 + 5) // 3
-                data = binascii.a2b_uu(s[:nbytes])
-                if not quiet:
-                    sys.stderr.write("Warning: %s\n" % v)
-            out_file.write(data)
-            s = in_file.readline()
-        if not s:
-            raise Error('Truncated input file')
-    finally:
-        for f in opened_files:
-            f.close()
-
-def test():
-    """uuencode/uudecode main program"""
-
-    import optparse
-    parser = optparse.OptionParser(usage='usage: %prog [-d] [-t] [input [output]]')
-    parser.add_option('-d', '--decode', dest='decode', help='Decode (instead of encode)?', default=False, action='store_true')
-    parser.add_option('-t', '--text', dest='text', help='data is text, encoded format unix-compatible text?', default=False, action='store_true')
-
-    (options, args) = parser.parse_args()
-    if len(args) > 2:
-        parser.error('incorrect number of arguments')
-        sys.exit(1)
-
-    # Use the binary streams underlying stdin/stdout
-    input = sys.stdin.buffer
-    output = sys.stdout.buffer
-    if len(args) > 0:
-        input = args[0]
-    if len(args) > 1:
-        output = args[1]
-
-    if options.decode:
-        if options.text:
-            if isinstance(output, str):
-                output = open(output, 'wb')
-            else:
-                print(sys.argv[0], ': cannot do -t to stdout')
-                sys.exit(1)
-        decode(input, output)
-    else:
-        if options.text:
-            if isinstance(input, str):
-                input = open(input, 'rb')
-            else:
-                print(sys.argv[0], ': cannot do -t from stdin')
-                sys.exit(1)
-        encode(input, output)
-
-if __name__ == '__main__':
-    test()
diff --git a/Misc/NEWS.d/3.12.0b1.rst b/Misc/NEWS.d/3.12.0b1.rst
index a1ea082b3a21..96d76f89fa9c 100644
--- a/Misc/NEWS.d/3.12.0b1.rst
+++ b/Misc/NEWS.d/3.12.0b1.rst
@@ -4,7 +4,7 @@
 .. release date: 2023-05-22
 .. section: Security
 
-Fixed a security in flaw in :func:`uu.decode` that could allow for directory
+Fixed a security in flaw in :func:`!uu.decode` that could allow for directory
 traversal based on the input if no ``out_file`` was specified.
 
 ..
diff --git a/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst b/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst
new file mode 100644
index 000000000000..522e259992de
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-05-25-15-54-02.gh-issue-104773.nW-5MI.rst
@@ -0,0 +1,2 @@
+:pep:`594`: Remove the :mod:`!uu` module, deprecated in Python 3.11. Patch
+by Victor Stinner.
diff --git a/Python/stdlib_module_names.h b/Python/stdlib_module_names.h
index 00742b39a327..db574febd20f 100644
--- a/Python/stdlib_module_names.h
+++ b/Python/stdlib_module_names.h
@@ -268,7 +268,6 @@ static const char* _Py_stdlib_module_names[] = {
 "unicodedata",
 "unittest",
 "urllib",
-"uu",
 "uuid",
 "venv",
 "warnings",
diff --git a/Tools/wasm/wasm_assets.py b/Tools/wasm/wasm_assets.py
index 5e59ee7ef375..2cf5ac515a4d 100755
--- a/Tools/wasm/wasm_assets.py
+++ b/Tools/wasm/wasm_assets.py
@@ -41,8 +41,6 @@
     # package management
     "ensurepip/",
     "venv/",
-    # deprecated
-    "uu.py",
     # other platforms
     "_aix_support.py",
     "_osx_support.py",



More information about the Python-checkins mailing list