bpo-39305: Update nntplib to merge nntplib.NNTP and nntplib._NNTPBase (GH-19817)
This commit is contained in:
parent
372fa3ead5
commit
aa92a7cf21
|
@ -293,7 +293,7 @@ if _have_ssl:
|
||||||
|
|
||||||
|
|
||||||
# The classes themselves
|
# The classes themselves
|
||||||
class _NNTPBase:
|
class NNTP:
|
||||||
# UTF-8 is the character set for all NNTP commands and responses: they
|
# UTF-8 is the character set for all NNTP commands and responses: they
|
||||||
# are automatically encoded (when sending) and decoded (and receiving)
|
# are automatically encoded (when sending) and decoded (and receiving)
|
||||||
# by this class.
|
# by this class.
|
||||||
|
@ -309,13 +309,18 @@ class _NNTPBase:
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
errors = 'surrogateescape'
|
errors = 'surrogateescape'
|
||||||
|
|
||||||
def __init__(self, file, host,
|
def __init__(self, host, port=NNTP_PORT, user=None, password=None,
|
||||||
readermode=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
|
readermode=None, usenetrc=False,
|
||||||
|
timeout=_GLOBAL_DEFAULT_TIMEOUT):
|
||||||
"""Initialize an instance. Arguments:
|
"""Initialize an instance. Arguments:
|
||||||
- file: file-like object (open for read/write in binary mode)
|
- host: hostname to connect to
|
||||||
- host: hostname of the server
|
- 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
|
- readermode: if true, send 'mode reader' command after
|
||||||
connecting.
|
connecting.
|
||||||
|
- usenetrc: allow loading username and password from ~/.netrc file
|
||||||
|
if not specified explicitly
|
||||||
- timeout: timeout (in seconds) used for socket connections
|
- timeout: timeout (in seconds) used for socket connections
|
||||||
|
|
||||||
readermode is sometimes necessary if you are connecting to an
|
readermode is sometimes necessary if you are connecting to an
|
||||||
|
@ -325,7 +330,24 @@ class _NNTPBase:
|
||||||
readermode.
|
readermode.
|
||||||
"""
|
"""
|
||||||
self.host = host
|
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.debugging = 0
|
||||||
self.welcome = self._getresp()
|
self.welcome = self._getresp()
|
||||||
|
|
||||||
|
@ -370,6 +392,12 @@ class _NNTPBase:
|
||||||
if is_connected():
|
if is_connected():
|
||||||
self._close()
|
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):
|
def getwelcome(self):
|
||||||
"""Get the welcome message from the server
|
"""Get the welcome message from the server
|
||||||
(this is read and squirreled away by __init__()).
|
(this is read and squirreled away by __init__()).
|
||||||
|
@ -888,8 +916,12 @@ class _NNTPBase:
|
||||||
return self._post('IHAVE {0}'.format(message_id), data)
|
return self._post('IHAVE {0}'.format(message_id), data)
|
||||||
|
|
||||||
def _close(self):
|
def _close(self):
|
||||||
self.file.close()
|
try:
|
||||||
del self.file
|
if self.file:
|
||||||
|
self.file.close()
|
||||||
|
del self.file
|
||||||
|
finally:
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
def quit(self):
|
def quit(self):
|
||||||
"""Process a QUIT command and close the socket. Returns:
|
"""Process a QUIT command and close the socket. Returns:
|
||||||
|
@ -979,56 +1011,6 @@ class _NNTPBase:
|
||||||
raise NNTPError("TLS failed to start.")
|
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:
|
if _have_ssl:
|
||||||
class NNTP_SSL(NNTP):
|
class NNTP_SSL(NNTP):
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import textwrap
|
||||||
import unittest
|
import unittest
|
||||||
import functools
|
import functools
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import nntplib
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
|
@ -12,7 +13,6 @@ import threading
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
from nntplib import NNTP, GroupInfo
|
from nntplib import NNTP, GroupInfo
|
||||||
import nntplib
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
try:
|
try:
|
||||||
import ssl
|
import ssl
|
||||||
|
@ -411,6 +411,18 @@ def make_mock_file(handler):
|
||||||
return (sio, file)
|
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:
|
class MockedNNTPTestsMixin:
|
||||||
# Override in derived classes
|
# Override in derived classes
|
||||||
handler_class = None
|
handler_class = None
|
||||||
|
@ -426,7 +438,7 @@ class MockedNNTPTestsMixin:
|
||||||
def make_server(self, *args, **kwargs):
|
def make_server(self, *args, **kwargs):
|
||||||
self.handler = self.handler_class()
|
self.handler = self.handler_class()
|
||||||
self.sio, file = make_mock_file(self.handler)
|
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
|
return self.server
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Update :mod:`nntplib` to merge :class:`nntplib.NNTP` and
|
||||||
|
:class:`nntplib._NNTPBase`. Patch by Dong-hee Na.
|
Loading…
Reference in New Issue