[Python-checkins] bpo-39305: Update nntplib to merge nntplib.NNTP and nntplib._NNTPBase (GH-19817)

Dong-hee Na webhook-mailer at python.org
Sat May 16 06:31:58 EDT 2020


https://github.com/python/cpython/commit/aa92a7cf210c98ad94229f282221136d846942db
commit: aa92a7cf210c98ad94229f282221136d846942db
branch: master
author: Dong-hee Na <donghee.na92 at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-05-16T19:31:54+09:00
summary:

bpo-39305: Update nntplib to merge nntplib.NNTP and nntplib._NNTPBase (GH-19817)

files:
A Misc/NEWS.d/next/Library/2020-05-01-00-22-58.bpo-39305.Cuwu_H.rst
M Lib/nntplib.py
M Lib/test/test_nntplib.py

diff --git a/Lib/nntplib.py b/Lib/nntplib.py
index aa9b46a8aaa39..f6e746e7c95c5 100644
--- a/Lib/nntplib.py
+++ b/Lib/nntplib.py
@@ -293,7 +293,7 @@ def _encrypt_on(sock, context, hostname):
 
 
 # The classes themselves
-class _NNTPBase:
+class NNTP:
     # UTF-8 is the character set for all NNTP commands and responses: they
     # are automatically encoded (when sending) and decoded (and receiving)
     # by this class.
@@ -309,13 +309,18 @@ class _NNTPBase:
     encoding = 'utf-8'
     errors = 'surrogateescape'
 
-    def __init__(self, file, host,
-                 readermode=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
+    def __init__(self, host, port=NNTP_PORT, user=None, password=None,
+                 readermode=None, usenetrc=False,
+                 timeout=_GLOBAL_DEFAULT_TIMEOUT):
         """Initialize an instance.  Arguments:
-        - file: file-like object (open for read/write in binary mode)
-        - host: hostname of the server
+        - host: hostname to connect to
+        - port: port to connect to (default the standard NNTP port)
+        - user: username to authenticate with
+        - password: password to use with username
         - readermode: if true, send 'mode reader' command after
                       connecting.
+        - usenetrc: allow loading username and password from ~/.netrc file
+                    if not specified explicitly
         - timeout: timeout (in seconds) used for socket connections
 
         readermode is sometimes necessary if you are connecting to an
@@ -325,7 +330,24 @@ def __init__(self, file, host,
         readermode.
         """
         self.host = host
-        self.file = file
+        self.port = port
+        self.sock = self._create_socket(timeout)
+        self.file = None
+        try:
+            self.file = self.sock.makefile("rwb")
+            self._base_init(readermode)
+            if user or usenetrc:
+                self.login(user, password, usenetrc)
+        except:
+            if self.file:
+                self.file.close()
+            self.sock.close()
+            raise
+
+    def _base_init(self, readermode):
+        """Partial initialization for the NNTP protocol.
+        This instance method is extracted for supporting the test code.
+        """
         self.debugging = 0
         self.welcome = self._getresp()
 
@@ -370,6 +392,12 @@ def __exit__(self, *args):
                 if is_connected():
                     self._close()
 
+    def _create_socket(self, timeout):
+        if timeout is not None and not timeout:
+            raise ValueError('Non-blocking socket (timeout=0) is not supported')
+        sys.audit("nntplib.connect", self, self.host, self.port)
+        return socket.create_connection((self.host, self.port), timeout)
+
     def getwelcome(self):
         """Get the welcome message from the server
         (this is read and squirreled away by __init__()).
@@ -888,8 +916,12 @@ def ihave(self, message_id, data):
         return self._post('IHAVE {0}'.format(message_id), data)
 
     def _close(self):
-        self.file.close()
-        del self.file
+        try:
+            if self.file:
+                self.file.close()
+                del self.file
+        finally:
+            self.sock.close()
 
     def quit(self):
         """Process a QUIT command and close the socket.  Returns:
@@ -979,56 +1011,6 @@ def starttls(self, context=None):
                 raise NNTPError("TLS failed to start.")
 
 
-class NNTP(_NNTPBase):
-
-    def __init__(self, host, port=NNTP_PORT, user=None, password=None,
-                 readermode=None, usenetrc=False,
-                 timeout=_GLOBAL_DEFAULT_TIMEOUT):
-        """Initialize an instance.  Arguments:
-        - host: hostname to connect to
-        - port: port to connect to (default the standard NNTP port)
-        - user: username to authenticate with
-        - password: password to use with username
-        - readermode: if true, send 'mode reader' command after
-                      connecting.
-        - usenetrc: allow loading username and password from ~/.netrc file
-                    if not specified explicitly
-        - timeout: timeout (in seconds) used for socket connections
-
-        readermode is sometimes necessary if you are connecting to an
-        NNTP server on the local machine and intend to call
-        reader-specific commands, such as `group'.  If you get
-        unexpected NNTPPermanentErrors, you might need to set
-        readermode.
-        """
-        self.host = host
-        self.port = port
-        self.sock = self._create_socket(timeout)
-        file = None
-        try:
-            file = self.sock.makefile("rwb")
-            super().__init__(file, host, readermode, timeout)
-            if user or usenetrc:
-                self.login(user, password, usenetrc)
-        except:
-            if file:
-                file.close()
-            self.sock.close()
-            raise
-
-    def _create_socket(self, timeout):
-        if timeout is not None and not timeout:
-            raise ValueError('Non-blocking socket (timeout=0) is not supported')
-        sys.audit("nntplib.connect", self, self.host, self.port)
-        return socket.create_connection((self.host, self.port), timeout)
-
-    def _close(self):
-        try:
-            super()._close()
-        finally:
-            self.sock.close()
-
-
 if _have_ssl:
     class NNTP_SSL(NNTP):
 
diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
index 8d296818e64f1..1df64fa7c6b00 100644
--- a/Lib/test/test_nntplib.py
+++ b/Lib/test/test_nntplib.py
@@ -5,6 +5,7 @@
 import unittest
 import functools
 import contextlib
+import nntplib
 import os.path
 import re
 import threading
@@ -12,7 +13,6 @@
 from test import support
 from test.support import socket_helper
 from nntplib import NNTP, GroupInfo
-import nntplib
 from unittest.mock import patch
 try:
     import ssl
@@ -411,6 +411,18 @@ def make_mock_file(handler):
     return (sio, file)
 
 
+class NNTPServer(nntplib.NNTP):
+
+    def __init__(self, f, host, readermode=None):
+        self.file = f
+        self.host = host
+        self._base_init(readermode)
+
+    def _close(self):
+        self.file.close()
+        del self.file
+
+
 class MockedNNTPTestsMixin:
     # Override in derived classes
     handler_class = None
@@ -426,7 +438,7 @@ def tearDown(self):
     def make_server(self, *args, **kwargs):
         self.handler = self.handler_class()
         self.sio, file = make_mock_file(self.handler)
-        self.server = nntplib._NNTPBase(file, 'test.server', *args, **kwargs)
+        self.server = NNTPServer(file, 'test.server', *args, **kwargs)
         return self.server
 
 
diff --git a/Misc/NEWS.d/next/Library/2020-05-01-00-22-58.bpo-39305.Cuwu_H.rst b/Misc/NEWS.d/next/Library/2020-05-01-00-22-58.bpo-39305.Cuwu_H.rst
new file mode 100644
index 0000000000000..7c6fdb3ede1c6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-05-01-00-22-58.bpo-39305.Cuwu_H.rst
@@ -0,0 +1,2 @@
+Update :mod:`nntplib` to merge :class:`nntplib.NNTP` and
+:class:`nntplib._NNTPBase`. Patch by Dong-hee Na.



More information about the Python-checkins mailing list