Skip to content

Commit aa92a7c

Browse files
authored
bpo-39305: Update nntplib to merge nntplib.NNTP and nntplib._NNTPBase (GH-19817)
1 parent 372fa3e commit aa92a7c

File tree

3 files changed

+56
-60
lines changed

3 files changed

+56
-60
lines changed

Lib/nntplib.py

+40-58
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ def _encrypt_on(sock, context, hostname):
293293

294294

295295
# The classes themselves
296-
class _NNTPBase:
296+
class NNTP:
297297
# UTF-8 is the character set for all NNTP commands and responses: they
298298
# are automatically encoded (when sending) and decoded (and receiving)
299299
# by this class.
@@ -309,13 +309,18 @@ class _NNTPBase:
309309
encoding = 'utf-8'
310310
errors = 'surrogateescape'
311311

312-
def __init__(self, file, host,
313-
readermode=None, timeout=_GLOBAL_DEFAULT_TIMEOUT):
312+
def __init__(self, host, port=NNTP_PORT, user=None, password=None,
313+
readermode=None, usenetrc=False,
314+
timeout=_GLOBAL_DEFAULT_TIMEOUT):
314315
"""Initialize an instance. Arguments:
315-
- file: file-like object (open for read/write in binary mode)
316-
- host: hostname of the server
316+
- host: hostname to connect to
317+
- port: port to connect to (default the standard NNTP port)
318+
- user: username to authenticate with
319+
- password: password to use with username
317320
- readermode: if true, send 'mode reader' command after
318321
connecting.
322+
- usenetrc: allow loading username and password from ~/.netrc file
323+
if not specified explicitly
319324
- timeout: timeout (in seconds) used for socket connections
320325
321326
readermode is sometimes necessary if you are connecting to an
@@ -325,7 +330,24 @@ def __init__(self, file, host,
325330
readermode.
326331
"""
327332
self.host = host
328-
self.file = file
333+
self.port = port
334+
self.sock = self._create_socket(timeout)
335+
self.file = None
336+
try:
337+
self.file = self.sock.makefile("rwb")
338+
self._base_init(readermode)
339+
if user or usenetrc:
340+
self.login(user, password, usenetrc)
341+
except:
342+
if self.file:
343+
self.file.close()
344+
self.sock.close()
345+
raise
346+
347+
def _base_init(self, readermode):
348+
"""Partial initialization for the NNTP protocol.
349+
This instance method is extracted for supporting the test code.
350+
"""
329351
self.debugging = 0
330352
self.welcome = self._getresp()
331353

@@ -370,6 +392,12 @@ def __exit__(self, *args):
370392
if is_connected():
371393
self._close()
372394

395+
def _create_socket(self, timeout):
396+
if timeout is not None and not timeout:
397+
raise ValueError('Non-blocking socket (timeout=0) is not supported')
398+
sys.audit("nntplib.connect", self, self.host, self.port)
399+
return socket.create_connection((self.host, self.port), timeout)
400+
373401
def getwelcome(self):
374402
"""Get the welcome message from the server
375403
(this is read and squirreled away by __init__()).
@@ -888,8 +916,12 @@ def ihave(self, message_id, data):
888916
return self._post('IHAVE {0}'.format(message_id), data)
889917

890918
def _close(self):
891-
self.file.close()
892-
del self.file
919+
try:
920+
if self.file:
921+
self.file.close()
922+
del self.file
923+
finally:
924+
self.sock.close()
893925

894926
def quit(self):
895927
"""Process a QUIT command and close the socket. Returns:
@@ -979,56 +1011,6 @@ def starttls(self, context=None):
9791011
raise NNTPError("TLS failed to start.")
9801012

9811013

982-
class NNTP(_NNTPBase):
983-
984-
def __init__(self, host, port=NNTP_PORT, user=None, password=None,
985-
readermode=None, usenetrc=False,
986-
timeout=_GLOBAL_DEFAULT_TIMEOUT):
987-
"""Initialize an instance. Arguments:
988-
- host: hostname to connect to
989-
- port: port to connect to (default the standard NNTP port)
990-
- user: username to authenticate with
991-
- password: password to use with username
992-
- readermode: if true, send 'mode reader' command after
993-
connecting.
994-
- usenetrc: allow loading username and password from ~/.netrc file
995-
if not specified explicitly
996-
- timeout: timeout (in seconds) used for socket connections
997-
998-
readermode is sometimes necessary if you are connecting to an
999-
NNTP server on the local machine and intend to call
1000-
reader-specific commands, such as `group'. If you get
1001-
unexpected NNTPPermanentErrors, you might need to set
1002-
readermode.
1003-
"""
1004-
self.host = host
1005-
self.port = port
1006-
self.sock = self._create_socket(timeout)
1007-
file = None
1008-
try:
1009-
file = self.sock.makefile("rwb")
1010-
super().__init__(file, host, readermode, timeout)
1011-
if user or usenetrc:
1012-
self.login(user, password, usenetrc)
1013-
except:
1014-
if file:
1015-
file.close()
1016-
self.sock.close()
1017-
raise
1018-
1019-
def _create_socket(self, timeout):
1020-
if timeout is not None and not timeout:
1021-
raise ValueError('Non-blocking socket (timeout=0) is not supported')
1022-
sys.audit("nntplib.connect", self, self.host, self.port)
1023-
return socket.create_connection((self.host, self.port), timeout)
1024-
1025-
def _close(self):
1026-
try:
1027-
super()._close()
1028-
finally:
1029-
self.sock.close()
1030-
1031-
10321014
if _have_ssl:
10331015
class NNTP_SSL(NNTP):
10341016

Lib/test/test_nntplib.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import unittest
66
import functools
77
import contextlib
8+
import nntplib
89
import os.path
910
import re
1011
import threading
1112

1213
from test import support
1314
from test.support import socket_helper
1415
from nntplib import NNTP, GroupInfo
15-
import nntplib
1616
from unittest.mock import patch
1717
try:
1818
import ssl
@@ -411,6 +411,18 @@ def make_mock_file(handler):
411411
return (sio, file)
412412

413413

414+
class NNTPServer(nntplib.NNTP):
415+
416+
def __init__(self, f, host, readermode=None):
417+
self.file = f
418+
self.host = host
419+
self._base_init(readermode)
420+
421+
def _close(self):
422+
self.file.close()
423+
del self.file
424+
425+
414426
class MockedNNTPTestsMixin:
415427
# Override in derived classes
416428
handler_class = None
@@ -426,7 +438,7 @@ def tearDown(self):
426438
def make_server(self, *args, **kwargs):
427439
self.handler = self.handler_class()
428440
self.sio, file = make_mock_file(self.handler)
429-
self.server = nntplib._NNTPBase(file, 'test.server', *args, **kwargs)
441+
self.server = NNTPServer(file, 'test.server', *args, **kwargs)
430442
return self.server
431443

432444

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Update :mod:`nntplib` to merge :class:`nntplib.NNTP` and
2+
:class:`nntplib._NNTPBase`. Patch by Dong-hee Na.

0 commit comments

Comments
 (0)