From bc7ee0b5b64fb6c0ad759431d1efb87395c0c955 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Thu, 2 Aug 2018 23:52:13 +0530 Subject: [PATCH 01/14] bpo-24255: Replace debug level-related logic in http client with logging --- Lib/http/client.py | 137 ++++++++++++------ .../2018-08-02-23-51-44.bpo-24255.IZcKUO.rst | 2 + 2 files changed, 92 insertions(+), 47 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst diff --git a/Lib/http/client.py b/Lib/http/client.py index 5aa178d7b127d9..0a390b15a1bdd7 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -72,6 +72,7 @@ import email.message import http import io +import logging import re import socket import collections.abc @@ -144,6 +145,8 @@ # servers will otherwise respond with a 411 _METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'} +_log = logging.getLogger(__name__) + def _encode(data, name='data'): """Call data.encode("latin-1") but show a better error message.""" @@ -190,6 +193,7 @@ def getallmatchingheaders(self, name): lst.append(line) return lst + def parse_headers(fp, _class=HTTPMessage): """Parses only RFC2822 headers from a file pointer. @@ -244,7 +248,7 @@ def __init__(self, sock, debuglevel=0, method=None, url=None): self.headers = self.msg = None # from the Status-Line of the response - self.version = _UNKNOWN # HTTP-Version + self.version = _UNKNOWN # HTTP-Version self.status = _UNKNOWN # Status-Code self.reason = _UNKNOWN # Reason-Phrase @@ -257,8 +261,6 @@ def _read_status(self): line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") if len(line) > _MAXLINE: raise LineTooLong("status line") - if self.debuglevel > 0: - print("reply:", repr(line)) if not line: # Presumably, the server closed the connection before # sending a valid response. @@ -284,6 +286,7 @@ def _read_status(self): raise BadStatusLine(line) except ValueError: raise BadStatusLine(line) + _log.info('Received response: %s %s', status, reason.strip()) return version, status, reason def begin(self): @@ -304,8 +307,6 @@ def begin(self): skip = skip.strip() if not skip: break - if self.debuglevel > 0: - print("header:", skip) self.code = self.status = status self.reason = reason.strip() @@ -319,9 +320,9 @@ def begin(self): self.headers = self.msg = parse_headers(self.fp) - if self.debuglevel > 0: + if _log.isEnabledFor(logging.DEBUG): for hdr in self.headers: - print("header:", hdr + ":", self.headers.get(hdr)) + _log.debug("Received header: ('%s': '%s')", hdr, self.headers[hdr]) # are we using the chunked-style of transfer encoding? tr_enc = self.headers.get("transfer-encoding") @@ -339,7 +340,7 @@ def begin(self): self.length = None length = self.headers.get("content-length") - # are we using the chunked-style of transfer encoding? + # are we using the chunked-style of transfer encoding? tr_enc = self.headers.get("transfer-encoding") if length and not self.chunked: try: @@ -354,16 +355,14 @@ def begin(self): # does the body have a fixed length? (of zero) if (status == NO_CONTENT or status == NOT_MODIFIED or - 100 <= status < 200 or # 1xx codes - self._method == "HEAD"): + 100 <= status < 200 or # 1xx codes + self._method == "HEAD"): self.length = 0 # if the connection remains open, and we aren't using chunked, and # a content-length was not provided, then assume that the connection # WILL close. - if (not self.will_close and - not self.chunked and - self.length is None): + if (not self.will_close and not self.chunked and self.length is None): self.will_close = True def _check_close(self): @@ -402,7 +401,7 @@ def _close_conn(self): def close(self): try: - super().close() # set "closed" flag + super().close() # set "closed" flag finally: if self.fp: self._close_conn() @@ -463,6 +462,7 @@ def read(self, amt=None): raise self.length = 0 self._close_conn() # we read everything + self._log_bytes_read(len(s)) return s def readinto(self, b): @@ -497,6 +497,7 @@ def readinto(self, b): self.length -= n if not self.length: self._close_conn() + self._log_bytes_read(n) return n def _read_next_chunk_size(self): @@ -506,7 +507,7 @@ def _read_next_chunk_size(self): raise LineTooLong("chunk size") i = line.find(b";") if i >= 0: - line = line[:i] # strip chunk-extensions + line = line[:i] # strip chunk-extensions try: return int(line, 16) except ValueError: @@ -517,7 +518,7 @@ def _read_next_chunk_size(self): def _read_and_discard_trailer(self): # read and discard trailer up to the CRLF terminator - ### note: we shouldn't have any trailers! + # note: we shouldn't have any trailers! while True: line = self.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: @@ -536,7 +537,7 @@ def _get_chunk_left(self): # This function returns non-zero or None if the last chunk has # been read. chunk_left = self.chunk_left - if not chunk_left: # Can be 0 or None + if not chunk_left: # Can be 0 or None if chunk_left is not None: # We are at the end of chunk, discard chunk end self._safe_read(2) # toss the CRLF at the end of the chunk @@ -563,6 +564,11 @@ def _readall_chunked(self): break value.append(self._safe_read(chunk_left)) self.chunk_left = 0 + if _log.isEnabledFor(logging.DEBUG): + total_read = 0 + for chunk in value: + total_read += len(chunk) + self._log_bytes_read(total_read) return b''.join(value) except IncompleteRead: raise IncompleteRead(b''.join(value)) @@ -575,11 +581,13 @@ def _readinto_chunked(self, b): while True: chunk_left = self._get_chunk_left() if chunk_left is None: + self._log_bytes_read(total_bytes) return total_bytes if len(mvb) <= chunk_left: n = self._safe_readinto(mvb) self.chunk_left = chunk_left - n + self._log_bytes_read(total_bytes + n) return total_bytes + n temp_mvb = mvb[:chunk_left] @@ -678,7 +686,7 @@ def _read1_chunked(self, n): if chunk_left is None or n == 0: return b'' if not (0 <= n <= chunk_left): - n = chunk_left # if n is negative or larger than chunk_left + n = chunk_left # if n is negative or larger than chunk_left read = self.fp.read1(n) self.chunk_left -= len(read) if not read: @@ -691,9 +699,9 @@ def _peek_chunked(self, n): try: chunk_left = self._get_chunk_left() except IncompleteRead: - return b'' # peek doesn't worry about protocol + return b'' # peek doesn't worry about protocol if chunk_left is None: - return b'' # eof + return b'' # eof # peek is allowed to return more than requested. Just request the # entire chunk, and truncate what we get. return self.fp.peek(chunk_left)[:chunk_left] @@ -776,6 +784,11 @@ def getcode(self): ''' return self.status + def _log_bytes_read(self, bytes_read): + _log.debug('Read %d byte%s of response data', bytes_read, + '' if bytes_read == 1 else 's') + + class HTTPConnection: _http_vsn = 11 @@ -834,6 +847,7 @@ def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, self.__response = None self.__state = _CS_IDLE self._method = None + self._url = None self._tunnel_host = None self._tunnel_port = None self._tunnel_headers = {} @@ -874,12 +888,12 @@ def _get_hostport(self, host, port): j = host.rfind(']') # ipv6 addresses have [...] if i > j: try: - port = int(host[i+1:]) + port = int(host[i + 1:]) except ValueError: - if host[i+1:] == "": # http://foo.com:/ == http://foo.com/ + if host[i + 1:] == "": # http://foo.com:/ == http://foo.com/ port = self.default_port else: - raise InvalidURL("nonnumeric port: '%s'" % host[i+1:]) + raise InvalidURL("nonnumeric port: '%s'" % host[i + 1:]) host = host[:i] else: port = self.default_port @@ -892,8 +906,10 @@ def set_debuglevel(self, level): self.debuglevel = level def _tunnel(self): - connect_str = "CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host, - self._tunnel_port) + _log.info('Tunneling through %s:%s', self._tunnel_host, self._tunnel_port) + connect_str = "CONNECT %s:%d HTTP/1.0\r\n" % ( + self._tunnel_host, self._tunnel_port + ) connect_bytes = connect_str.encode("ascii") self.send(connect_bytes) for header, value in self._tunnel_headers.items(): @@ -909,6 +925,9 @@ def _tunnel(self): self.close() raise OSError("Tunnel connection failed: %d %s" % (code, message.strip())) + _log.debug('Connection to tunnel host %s:%s succeeded', + self._tunnel_host, + self._tunnel_port) while True: line = response.fp.readline(_MAXLINE + 1) if len(line) > _MAXLINE: @@ -919,13 +938,13 @@ def _tunnel(self): if line in (b'\r\n', b'\n', b''): break - if self.debuglevel > 0: - print('header:', line.decode()) - def connect(self): """Connect to the host and port specified in __init__.""" + _log.debug('Opening socket to %s:%s', self.host, self.port) + self.sock = self._create_connection( - (self.host,self.port), self.timeout, self.source_address) + (self.host, self.port), self.timeout, self.source_address + ) self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) if self._tunnel_host: @@ -944,6 +963,7 @@ def close(self): if response: self.__response = None response.close() + _log.info('Closed connection to %s:%s', self.host, self.port) def send(self, data): """Send `data' to the server. @@ -957,11 +977,7 @@ def send(self, data): else: raise NotConnected() - if self.debuglevel > 0: - print("send:", repr(data)) - if hasattr(data, "read") : - if self.debuglevel > 0: - print("sendIng a read()able") + if hasattr(data, "read"): encode = self._is_textIO(data) if encode and self.debuglevel > 0: print("encoding file using iso-8859-1") @@ -982,6 +998,8 @@ def send(self, data): else: raise TypeError("data should be a bytes-like object " "or an iterable, got %r" % type(data)) + else: + self._log_bytes_sent(len(data)) def _output(self, s): """Add a line of output to the current request buffer. @@ -992,10 +1010,10 @@ def _output(self, s): def _read_readable(self, readable): if self.debuglevel > 0: - print("sendIng a read()able") + _log.debug('sendIng a read()able') encode = self._is_textIO(readable) if encode and self.debuglevel > 0: - print("encoding file using iso-8859-1") + _log.debug('Encoding data using iso-8859-1') while True: datablock = readable.read(self.blocksize) if not datablock: @@ -1013,6 +1031,8 @@ def _send_output(self, message_body=None, encode_chunked=False): self._buffer.extend((b"", b"")) msg = b"\r\n".join(self._buffer) del self._buffer[:] + _log.info('Sending %s request to %s:%s for %s', self._method.upper(), + self.host, self.port, self._url) self.send(msg) if message_body is not None: @@ -1073,7 +1093,6 @@ def putrequest(self, method, url, skip_host=False, if self.__response and self.__response.isclosed(): self.__response = None - # in certain cases, we cannot issue another request on this connection. # this occurs when: # 1) we are in the process of sending a request. (_CS_REQ_STARTED) @@ -1097,11 +1116,15 @@ def putrequest(self, method, url, skip_host=False, else: raise CannotSendRequest(self.__state) + _log.debug('Preparing to send %s request to %s:%s for %s', + method.upper(), self.host, self.port, url) + # Save the method we use, we need it later in the response phase self._method = method if not url: url = '/' request = '%s %s %s' % (method, url, self._http_vsn_str) + self._url = url # Non-ASCII characters should have been eliminated earlier self._output(request.encode('ascii')) @@ -1172,11 +1195,11 @@ def putrequest(self, method, url, skip_host=False, # we can accept "chunked" Transfer-Encodings, but no others # NOTE: no TE header implies *only* "chunked" - #self.putheader('TE', 'chunked') + # self.putheader('TE', 'chunked') # if TE is supplied in the header, then it must appear in a # Connection header. - #self.putheader('Connection', 'TE') + # self.putheader('Connection', 'TE') else: # For HTTP/1.0, the server will assume "not chunked" @@ -1206,6 +1229,7 @@ def putheader(self, header, *values): if _is_illegal_header_value(values[i]): raise ValueError('Invalid header value %r' % (values[i],)) + _log.debug('Appending header: (%s: %s)', header, values) value = b'\r\n\t'.join(values) header = header + b': ' + value self._output(header) @@ -1258,7 +1282,7 @@ def _send_request(self, method, url, body, headers, encode_chunked): if content_length is None: if body is not None: if self.debuglevel > 0: - print('Unable to determine size of %r' % body) + _log.error('Unable to determine size of %r', body) encode_chunked = True self.putheader('Transfer-Encoding', 'chunked') else: @@ -1310,11 +1334,7 @@ def getresponse(self): if self.__state != _CS_REQ_SENT or self.__response: raise ResponseNotReady(self.__state) - if self.debuglevel > 0: - response = self.response_class(self.sock, self.debuglevel, - method=self._method) - else: - response = self.response_class(self.sock, method=self._method) + response = self.response_class(self.sock, method=self._method) try: try: @@ -1333,10 +1353,15 @@ def getresponse(self): self.__response = response return response - except: + except Exception: response.close() raise + def _log_bytes_sent(self, bytes_sent): + _log.debug('Sent %s byte%s to %s:%s', bytes_sent, + '' if bytes_sent == 1 else 's', self.host, self.port) + + try: import ssl except ImportError: @@ -1357,7 +1382,7 @@ def __init__(self, host, port=None, key_file=None, cert_file=None, source_address, blocksize=blocksize) if (key_file is not None or cert_file is not None or - check_hostname is not None): + check_hostname is not None): import warnings warnings.warn("key_file, cert_file and check_hostname are " "deprecated, use a custom context instead.", @@ -1381,6 +1406,7 @@ def __init__(self, host, port=None, key_file=None, cert_file=None, def connect(self): "Connect to a host on a given (SSL) port." + _log.info('Connecting via SSL to %s:%s', self.host, self.port) super().connect() if self._tunnel_host: @@ -1393,33 +1419,41 @@ def connect(self): __all__.append("HTTPSConnection") + class HTTPException(Exception): # Subclasses that define an __init__ must call Exception.__init__ # or define self.args. Otherwise, str() will fail. pass + class NotConnected(HTTPException): pass + class InvalidURL(HTTPException): pass + class UnknownProtocol(HTTPException): def __init__(self, version): self.args = version, self.version = version + class UnknownTransferEncoding(HTTPException): pass + class UnimplementedFileMode(HTTPException): pass + class IncompleteRead(HTTPException): def __init__(self, partial, expected=None): self.args = partial, self.partial = partial self.expected = expected + def __repr__(self): if self.expected is not None: e = ', %i more expected' % self.expected @@ -1427,21 +1461,27 @@ def __repr__(self): e = '' return '%s(%i bytes read%s)' % (self.__class__.__name__, len(self.partial), e) + def __str__(self): return repr(self) + class ImproperConnectionState(HTTPException): pass + class CannotSendRequest(ImproperConnectionState): pass + class CannotSendHeader(ImproperConnectionState): pass + class ResponseNotReady(ImproperConnectionState): pass + class BadStatusLine(HTTPException): def __init__(self, line): if not line: @@ -1449,15 +1489,18 @@ def __init__(self, line): self.args = line, self.line = line + class LineTooLong(HTTPException): def __init__(self, line_type): HTTPException.__init__(self, "got more than %d bytes when reading %s" % (_MAXLINE, line_type)) + class RemoteDisconnected(ConnectionResetError, BadStatusLine): def __init__(self, *pos, **kw): BadStatusLine.__init__(self, "") ConnectionResetError.__init__(self, *pos, **kw) + # for backwards compatibility error = HTTPException diff --git a/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst b/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst new file mode 100644 index 00000000000000..b7dbc56244877d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst @@ -0,0 +1,2 @@ +Replaces debug level logic in http client with logging. Original patch by +Eryn Wells. Enhanced by Sanyam Khurana. From 5f63c20e185b0ddc60dac0f4cde734092e00941a Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Tue, 7 Aug 2018 23:47:30 +0530 Subject: [PATCH 02/14] fix(test_logging): Fix linting errors --- Lib/test/test_logging.py | 833 +++++++++++++++++++++------------------ 1 file changed, 446 insertions(+), 387 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index f7232f67eee730..58842ccebdc121 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -56,7 +56,9 @@ ThreadingTCPServer, StreamRequestHandler) try: - import win32evtlog, win32evtlogutil, pywintypes + import win32evtlog + import win32evtlogutil + import pywintypes except ImportError: win32evtlog = win32evtlogutil = pywintypes = None @@ -65,6 +67,7 @@ except ImportError: pass + class BaseTest(unittest.TestCase): """Base class for logging tests.""" @@ -160,8 +163,9 @@ def assert_log_lines(self, expected_values, stream=None, pat=None): for actual, expected in zip(actual_lines, expected_values): match = pat.search(actual) if not match: - self.fail("Log line does not match expected pattern:\n" + - actual) + self.fail( + "Log line does not match expected pattern:\n" + actual + ) self.assertEqual(tuple(match.groups()), expected) s = stream.read() if s: @@ -230,7 +234,7 @@ def test_nested_explicit(self): INF = logging.getLogger("INF") INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") + INF_ERR = logging.getLogger("INF.ERR") INF_ERR.setLevel(logging.ERROR) # These should log. @@ -253,7 +257,7 @@ def test_nested_inherited(self): INF = logging.getLogger("INF") INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") + INF_ERR = logging.getLogger("INF.ERR") INF_ERR.setLevel(logging.ERROR) INF_UNDEF = logging.getLogger("INF.UNDEF") INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF") @@ -331,6 +335,7 @@ def test_regression_29220(self): self.assertEqual(logging.getLevelName(logging.NOTSET), 'NOTSET') self.assertEqual(logging.getLevelName('NOTSET'), logging.NOTSET) + class BasicFilterTest(BaseTest): """Test the bundled Filter class.""" @@ -395,22 +400,24 @@ def test_empty_filter(self): # # First, we define our levels. There can be as many as you want - the only -# limitations are that they should be integers, the lowest should be > 0 and +# limitations are that they should be integers, the lowest should be > 0 and # larger values mean less information being logged. If you need specific # level values which do not fit into these limitations, you can use a # mapping dictionary to convert between your application levels and the # logging system. # -SILENT = 120 -TACITURN = 119 -TERSE = 118 -EFFUSIVE = 117 -SOCIABLE = 116 -VERBOSE = 115 -TALKATIVE = 114 -GARRULOUS = 113 -CHATTERBOX = 112 -BORING = 111 + + +SILENT = 120 +TACITURN = 119 +TERSE = 118 +EFFUSIVE = 117 +SOCIABLE = 116 +VERBOSE = 115 +TALKATIVE = 114 +GARRULOUS = 113 +CHATTERBOX = 112 +BORING = 111 LEVEL_RANGE = range(BORING, SILENT + 1) @@ -419,18 +426,19 @@ def test_empty_filter(self): # case the system will use "Level n" to denote the text for the level. # my_logging_levels = { - SILENT : 'Silent', - TACITURN : 'Taciturn', - TERSE : 'Terse', - EFFUSIVE : 'Effusive', - SOCIABLE : 'Sociable', - VERBOSE : 'Verbose', - TALKATIVE : 'Talkative', - GARRULOUS : 'Garrulous', - CHATTERBOX : 'Chatterbox', - BORING : 'Boring', + SILENT: 'Silent', + TACITURN: 'Taciturn', + TERSE: 'Terse', + EFFUSIVE: 'Effusive', + SOCIABLE: 'Sociable', + VERBOSE: 'Verbose', + TALKATIVE: 'Talkative', + GARRULOUS: 'Garrulous', + CHATTERBOX: 'Chatterbox', + BORING: 'Boring', } + class GarrulousFilter(logging.Filter): """A filter which blocks garrulous messages.""" @@ -438,6 +446,7 @@ class GarrulousFilter(logging.Filter): def filter(self, record): return record.levelno != GARRULOUS + class VerySpecificFilter(logging.Filter): """A filter which blocks sociable and taciturn messages.""" @@ -528,7 +537,7 @@ def test_specific_filters(self): ('Effusive', '17'), ('Terse', '18'), ('Silent', '20'), - ]) + ]) finally: if specific_filter: self.root_logger.removeFilter(specific_filter) @@ -581,7 +590,7 @@ def test_builtin_handlers(self): self.assertEqual(h.facility, h.LOG_USER) self.assertTrue(h.unixsocket) h.close() - except OSError: # syslogd might not be available + except OSError: # syslogd might not be available pass for method in ('GET', 'POST', 'PUT'): if method == 'PUT': @@ -609,10 +618,10 @@ def test_path_objects(self): os.unlink(fn) pfn = pathlib.Path(fn) cases = ( - (logging.FileHandler, (pfn, 'w')), - (logging.handlers.RotatingFileHandler, (pfn, 'a')), - (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), - ) + (logging.FileHandler, (pfn, 'w')), + (logging.handlers.RotatingFileHandler, (pfn, 'a')), + (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), + ) if sys.platform in ('linux', 'darwin'): cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),) for cls, args in cases: @@ -651,7 +660,7 @@ def remove_loop(fname, tries): try: for _ in range(log_count): time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing' }) + r = logging.makeLogRecord({'msg': 'testing'}) try: self.handle_time = time.time() h.handle(r) @@ -671,10 +680,12 @@ class BadStream(object): def write(self, data): raise RuntimeError('deliberate mistake') + class TestStreamHandler(logging.StreamHandler): def handleError(self, record): self.error_record = record + class StreamHandlerTest(BaseTest): def test_error_handling(self): h = TestStreamHandler(BadStream()) @@ -715,6 +726,7 @@ def test_stream_setting(self): # -- The following section could be moved into a server_helper.py module # -- if it proves to be of wider utility than just test_logging + class TestSMTPServer(smtpd.SMTPServer): """ This class implements a test SMTP server. @@ -842,6 +854,7 @@ def stop(self, timeout=None): self.server_close() self.ready.clear() + class TestHTTPServer(ControlMixin, HTTPServer): """ An HTTP server which is controllable using :class:`ControlMixin`. @@ -883,6 +896,7 @@ def get_request(self): raise return sock, addr + class TestTCPServer(ControlMixin, ThreadingTCPServer): """ A TCP server which is controllable using :class:`ControlMixin`. @@ -914,6 +928,7 @@ def server_bind(self): super(TestTCPServer, self).server_bind() self.port = self.socket.getsockname()[1] + class TestUDPServer(ControlMixin, ThreadingUDPServer): """ A UDP server which is controllable using :class:`ControlMixin`. @@ -961,6 +976,7 @@ def server_close(self): super(TestUDPServer, self).server_close() self._closed = True + if hasattr(socket, "AF_UNIX"): class TestUnixStreamServer(TestTCPServer): address_family = socket.AF_UNIX @@ -970,6 +986,7 @@ class TestUnixDatagramServer(TestUDPServer): # - end of server_helper section + class SMTPHandlerTest(BaseTest): # bpo-14314, bpo-19665, bpo-34092: don't wait forever, timeout of 1 minute TIMEOUT = 60.0 @@ -1002,6 +1019,7 @@ def process_message(self, *args): self.messages.append(args) self.handled.set() + class MemoryHandlerTest(BaseTest): """Tests for the MemoryHandler.""" @@ -1411,8 +1429,10 @@ def test_config4_ok(self): except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual(output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n") + self.assertEqual( + output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n" + ) # Original logger output is empty self.assert_log_lines([]) @@ -1630,6 +1650,7 @@ def test_noserver(self): time.sleep(self.sock_hdlr.retryTime - now + 0.001) self.root_logger.error('Nor this') + def _get_temp_domain_socket(): fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.sock') os.close(fd) @@ -1638,6 +1659,7 @@ def _get_temp_domain_socket(): os.remove(fn) return fn + @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixSocketHandlerTest(SocketHandlerTest): @@ -1655,6 +1677,7 @@ def tearDown(self): SocketHandlerTest.tearDown(self) support.unlink(self.address) + class DatagramHandlerTest(BaseTest): """Test for DatagramHandler.""" @@ -1700,7 +1723,7 @@ def tearDown(self): BaseTest.tearDown(self) def handle_datagram(self, request): - slen = struct.pack('>L', 0) # length of prefix + slen = struct.pack('>L', 0) # length of prefix packet = request.packet[len(slen):] obj = pickle.loads(packet) record = logging.makeLogRecord(obj) @@ -1719,6 +1742,7 @@ def test_output(self): self.handled.wait() self.assertEqual(self.log_output, "spam\neggs\n") + @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixDatagramHandlerTest(DatagramHandlerTest): @@ -1736,6 +1760,7 @@ def tearDown(self): DatagramHandlerTest.tearDown(self) support.unlink(self.address) + class SysLogHandlerTest(BaseTest): """Test for SysLogHandler using UDP.""" @@ -1803,6 +1828,7 @@ def test_output(self): self.handled.wait() self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m') + @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixSysLogHandlerTest(SysLogHandlerTest): @@ -1820,6 +1846,7 @@ def tearDown(self): SysLogHandlerTest.tearDown(self) support.unlink(self.address) + @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 support required for this test.') class IPv6SysLogHandlerTest(SysLogHandlerTest): @@ -1837,6 +1864,7 @@ def tearDown(self): self.server_class.address_family = socket.AF_INET super(IPv6SysLogHandlerTest, self).tearDown() + class HTTPHandlerTest(BaseTest): """Test for HTTPHandler.""" @@ -1853,7 +1881,7 @@ def handle_request(self, request): try: rlen = int(request.headers['Content-Length']) self.post_data = request.rfile.read(rlen) - except: + except Exception: self.post_data = None request.send_response(200) request.end_headers() @@ -1881,8 +1909,9 @@ def test_output(self): else: sslctx = None context = None - self.server = server = TestHTTPServer(addr, self.handle_request, - 0.01, sslctx=sslctx) + self.server = server = TestHTTPServer( + addr, self.handle_request, 0.01, sslctx=sslctx + ) server.start() server.ready.wait() host = 'localhost:%d' % server.server_port @@ -1914,6 +1943,7 @@ def test_output(self): self.root_logger.removeHandler(self.h_hdlr) self.h_hdlr.close() + class MemoryTest(BaseTest): """Test memory persistence of logger objects.""" @@ -1939,8 +1969,10 @@ def _assertTruesurvival(self): if ref() is None: dead.append(repr_) if dead: - self.fail("%d objects should have survived " - "but have been destroyed: %s" % (len(dead), ", ".join(dead))) + self.fail( + "%d objects should have survived but have been destroyed: %s" + % (len(dead), ", ".join(dead)) + ) def test_persistent_loggers(self): # Logger objects are persistent and retain their configuration, even @@ -2038,8 +2070,9 @@ def test_warnings(self): a_file, "Dummy line") s = a_file.getvalue() a_file.close() - self.assertEqual(s, - "dummy.py:42: UserWarning: Explicit\n Dummy line\n") + self.assertEqual( + s, "dummy.py:42: UserWarning: Explicit\n Dummy line\n" + ) def test_warnings_no_handlers(self): with warnings.catch_warnings(): @@ -2058,12 +2091,15 @@ def test_warnings_no_handlers(self): def formatFunc(format, datefmt=None): return logging.Formatter(format, datefmt) + def handlerFunc(): return logging.StreamHandler() + class CustomHandler(logging.StreamHandler): pass + class ConfigDictTest(BaseTest): """Reading logging config from a dictionary.""" @@ -2075,21 +2111,21 @@ class ConfigDictTest(BaseTest): config0 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } @@ -2097,26 +2133,26 @@ class ConfigDictTest(BaseTest): config1 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2124,26 +2160,26 @@ class ConfigDictTest(BaseTest): config1a = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', }, }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } @@ -2151,26 +2187,26 @@ class ConfigDictTest(BaseTest): config2 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdbout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdbout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2178,54 +2214,53 @@ class ConfigDictTest(BaseTest): config2a = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NTOSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NTOSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } - # As config1 but with a misspelt level on a logger config2b = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WRANING', + 'root': { + 'level': 'WRANING', }, } @@ -2233,26 +2268,26 @@ class ConfigDictTest(BaseTest): config3 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'misspelled_name', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'misspelled_name', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2260,22 +2295,22 @@ class ConfigDictTest(BaseTest): config4 = { 'version': 1, 'formatters': { - 'form1' : { - '()' : __name__ + '.ExceptionFormatter', - 'format' : '%(levelname)s:%(name)s:%(message)s', + 'form1': { + '()': __name__ + '.ExceptionFormatter', + 'format': '%(levelname)s:%(name)s:%(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'root' : { - 'level' : 'NOTSET', - 'handlers' : ['hand1'], + 'root': { + 'level': 'NOTSET', + 'handlers': ['hand1'], }, } @@ -2283,33 +2318,33 @@ class ConfigDictTest(BaseTest): config4a = { 'version': 1, 'formatters': { - 'form1' : { - '()' : ExceptionFormatter, - 'format' : '%(levelname)s:%(name)s:%(message)s', + 'form1': { + '()': ExceptionFormatter, + 'format': '%(levelname)s:%(name)s:%(message)s', }, - 'form2' : { - '()' : __name__ + '.formatFunc', - 'format' : '%(levelname)s:%(name)s:%(message)s', + 'form2': { + '()': __name__ + '.formatFunc', + 'format': '%(levelname)s:%(name)s:%(message)s', }, - 'form3' : { - '()' : formatFunc, - 'format' : '%(levelname)s:%(name)s:%(message)s', + 'form3': { + '()': formatFunc, + 'format': '%(levelname)s:%(name)s:%(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, - 'hand2' : { - '()' : handlerFunc, + 'hand2': { + '()': handlerFunc, }, }, - 'root' : { - 'level' : 'NOTSET', - 'handlers' : ['hand1'], + 'root': { + 'level': 'NOTSET', + 'handlers': ['hand1'], }, } @@ -2317,26 +2352,26 @@ class ConfigDictTest(BaseTest): config5 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : __name__ + '.CustomHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': __name__ + '.CustomHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2345,27 +2380,27 @@ class ConfigDictTest(BaseTest): config6 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : __name__ + '.CustomHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', - '9' : 'invalid parameter name', + 'handlers': { + 'hand1': { + 'class': __name__ + '.CustomHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', + '9': 'invalid parameter name', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2374,26 +2409,26 @@ class ConfigDictTest(BaseTest): config7 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.lexer' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.lexer': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2402,115 +2437,115 @@ class ConfigDictTest(BaseTest): # compiler is defined) config8 = { 'version': 1, - 'disable_existing_loggers' : False, + 'disable_existing_loggers': False, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, - 'compiler.lexer' : { + 'compiler.lexer': { }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } # config8a disables existing loggers config8a = { 'version': 1, - 'disable_existing_loggers' : True, + 'disable_existing_loggers': True, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, - 'compiler.lexer' : { + 'compiler.lexer': { }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } config9 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'WARNING', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'WARNING', + 'stream': 'ext://sys.stdout', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'NOTSET', + 'root': { + 'level': 'NOTSET', }, } config9a = { 'version': 1, - 'incremental' : True, - 'handlers' : { - 'hand1' : { - 'level' : 'WARNING', + 'incremental': True, + 'handlers': { + 'hand1': { + 'level': 'WARNING', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'INFO', + 'loggers': { + 'compiler.parser': { + 'level': 'INFO', }, }, } config9b = { 'version': 1, - 'incremental' : True, - 'handlers' : { - 'hand1' : { - 'level' : 'INFO', + 'incremental': True, + 'handlers': { + 'hand1': { + 'level': 'INFO', }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'INFO', + 'loggers': { + 'compiler.parser': { + 'level': 'INFO', }, }, } @@ -2519,33 +2554,33 @@ class ConfigDictTest(BaseTest): config10 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'filters' : { - 'filt1' : { - 'name' : 'compiler.parser', + 'filters': { + 'filt1': { + 'name': 'compiler.parser', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', - 'filters' : ['filt1'], + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', + 'filters': ['filt1'], }, }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'filters' : ['filt1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'filters': ['filt1'], }, }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } @@ -2553,60 +2588,60 @@ class ConfigDictTest(BaseTest): config11 = { 'version': 1, 'true_formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'formatters' : 'cfg://true_formatters', - 'handlers' : { - 'hand1' : 'cfg://handler_configs[hand1]', + 'formatters': 'cfg://true_formatters', + 'handlers': { + 'hand1': 'cfg://handler_configs[hand1]', }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } # As config11 but missing the version key config12 = { 'true_formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'formatters' : 'cfg://true_formatters', - 'handlers' : { - 'hand1' : 'cfg://handler_configs[hand1]', + 'formatters': 'cfg://true_formatters', + 'handlers': { + 'hand1': 'cfg://handler_configs[hand1]', }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2614,30 +2649,30 @@ class ConfigDictTest(BaseTest): config13 = { 'version': 2, 'true_formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', }, }, - 'formatters' : 'cfg://true_formatters', - 'handlers' : { - 'hand1' : 'cfg://handler_configs[hand1]', + 'formatters': 'cfg://true_formatters', + 'handlers': { + 'hand1': 'cfg://handler_configs[hand1]', }, - 'loggers' : { - 'compiler.parser' : { - 'level' : 'DEBUG', - 'handlers' : ['hand1'], + 'loggers': { + 'compiler.parser': { + 'level': 'DEBUG', + 'handlers': ['hand1'], }, }, - 'root' : { - 'level' : 'WARNING', + 'root': { + 'level': 'WARNING', }, } @@ -2645,25 +2680,25 @@ class ConfigDictTest(BaseTest): config14 = { 'version': 1, 'formatters': { - 'form1' : { - 'format' : '%(levelname)s ++ %(message)s', + 'form1': { + 'format': '%(levelname)s ++ %(message)s', }, }, - 'handlers' : { - 'hand1' : { - 'class' : 'logging.StreamHandler', - 'formatter' : 'form1', - 'level' : 'NOTSET', - 'stream' : 'ext://sys.stdout', + 'handlers': { + 'hand1': { + 'class': 'logging.StreamHandler', + 'formatter': 'form1', + 'level': 'NOTSET', + 'stream': 'ext://sys.stdout', '.': { 'foo': 'bar', 'terminator': '!\n', } }, }, - 'root' : { - 'level' : 'WARNING', - 'handlers' : ['hand1'], + 'root': { + 'level': 'WARNING', + 'handlers': ['hand1'], }, } @@ -2687,7 +2722,7 @@ class ConfigDictTest(BaseTest): "formatter": "mySimpleFormatter", "target": "fileGlobal", "level": "DEBUG" - } + } }, "loggers": { "mymodule": { @@ -2751,14 +2786,16 @@ def test_config4_ok(self): # A config specifying a custom formatter class. with support.captured_stdout() as output: self.apply_config(self.config4) - #logger = logging.getLogger() + # logger = logging.getLogger() try: raise RuntimeError() except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual(output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n") + self.assertEqual( + output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n" + ) # Original logger output is empty self.assert_log_lines([]) @@ -2766,14 +2803,16 @@ def test_config4a_ok(self): # A config specifying a custom formatter class. with support.captured_stdout() as output: self.apply_config(self.config4a) - #logger = logging.getLogger() + # logger = logging.getLogger() try: raise RuntimeError() except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual(output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n") + self.assertEqual( + output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n" + ) # Original logger output is empty self.assert_log_lines([]) @@ -3106,7 +3145,7 @@ def test_baseconfig(self): d = { 'atuple': (1, 2, 3), 'alist': ['a', 'b', 'c'], - 'adict': {'d': 'e', 'f': 3 }, + 'adict': {'d': 'e', 'f': 3}, 'nest1': ('g', ('h', 'i'), 'j'), 'nest2': ['k', ['l', 'm'], 'n'], 'nest3': ['o', 'cfg://alist', 'p'], @@ -3124,6 +3163,7 @@ def test_baseconfig(self): self.assertRaises(ValueError, bc.convert, 'cfg://!') self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]') + class ManagerTest(BaseTest): def test_manager_loggerclass(self): logged = [] @@ -3147,6 +3187,7 @@ def test_set_log_record_factory(self): man.setLogRecordFactory(expected) self.assertEqual(man.logRecordFactory, expected) + class ChildLoggerTest(BaseTest): def test_child_loggers(self): r = logging.getLogger() @@ -3167,6 +3208,7 @@ def test_child_loggers(self): class DerivedLogRecord(logging.LogRecord): pass + class LogRecordFactoryTest(BaseTest): def setUp(self): @@ -3177,8 +3219,8 @@ def __init__(self, cls): def filter(self, record): t = type(record) if t is not self.cls: - msg = 'Unexpected LogRecord type %s, expected %s' % (t, - self.cls) + msg = 'Unexpected LogRecord type %s, expected %s' % ( + t, self.cls) raise TypeError(msg) return True @@ -3198,7 +3240,7 @@ def test_logrecord_class(self): logging.setLogRecordFactory(DerivedLogRecord) self.root_logger.error(self.next_message()) self.assert_log_lines([ - ('root', 'ERROR', '2'), + ('root', 'ERROR', '2'), ]) @@ -3279,6 +3321,7 @@ def test_queue_listener(self): self.assertFalse(handler.matches(levelno=logging.ERROR, message='5')) self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6')) + if hasattr(logging.handlers, 'QueueListener'): import multiprocessing from unittest.mock import patch @@ -3356,21 +3399,25 @@ def test_no_messages_in_queue_after_stop(self): support.import_module('multiprocessing.synchronize') for i in range(self.repeat): queue = multiprocessing.Queue() - self.setup_and_log(queue, '%s_%s' %(self.id(), i)) + self.setup_and_log(queue, '%s_%s' % (self.id(), i)) # time.sleep(1) items = list(self.get_all_from_queue(queue)) queue.close() queue.join_thread() expected = [[], [logging.handlers.QueueListener._sentinel]] - self.assertIn(items, expected, - 'Found unexpected messages in queue: %s' % ( - [m.msg if isinstance(m, logging.LogRecord) - else m for m in items])) + self.assertIn( + items, expected, 'Found unexpected messages in queue: %s' + '' % ([ + m.msg if isinstance(m, logging.LogRecord) + else m for m in items] + ) + ) ZERO = datetime.timedelta(0) + class UTC(datetime.tzinfo): def utcoffset(self, dt): return ZERO @@ -3380,8 +3427,10 @@ def utcoffset(self, dt): def tzname(self, dt): return 'UTC' + utc = UTC() + class FormatterTest(unittest.TestCase): def setUp(self): self.common = { @@ -3471,6 +3520,7 @@ def test_time(self): f.format(r) self.assertEqual(r.asctime, '1993-04-21 08:03:00,123') + class TestBufferingFormatter(logging.BufferingFormatter): def formatHeader(self, records): return '[(%d)' % len(records) @@ -3478,6 +3528,7 @@ def formatHeader(self, records): def formatFooter(self, records): return '(%d)]' % len(records) + class BufferingFormatterTest(unittest.TestCase): def setUp(self): self.records = [ @@ -3497,6 +3548,7 @@ def test_custom(self): f = TestBufferingFormatter(lf) self.assertEqual('[(2)(2)]', f.format(self.records)) + class ExceptionTest(BaseTest): def test_formatting(self): r = self.root_logger @@ -3504,7 +3556,7 @@ def test_formatting(self): r.addHandler(h) try: raise RuntimeError('deliberate mistake') - except: + except Exception: logging.exception('failed', stack_info=True) r.removeHandler(h) h.close() @@ -3514,9 +3566,9 @@ def test_formatting(self): self.assertTrue(r.exc_text.endswith('\nRuntimeError: ' 'deliberate mistake')) self.assertTrue(r.stack_info.startswith('Stack (most recent ' - 'call last):\n')) + 'call last):\n')) self.assertTrue(r.stack_info.endswith('logging.exception(\'failed\', ' - 'stack_info=True)')) + 'stack_info=True)')) class LastResortTest(BaseTest): @@ -3771,7 +3823,7 @@ def test_dict_arg(self): h = RecordingHandler() r = logging.getLogger() r.addHandler(h) - d = {'less' : 'more' } + d = {'less': 'more'} logging.warning('less is %(less)s', d) self.assertIs(h.records[0].args, d) self.assertEqual(h.records[0].message, 'less is more') @@ -3813,6 +3865,7 @@ def test_optional(self): logging.logProcesses = log_processes logging.logMultiprocessing = log_multiprocessing + class BasicConfigTest(unittest.TestCase): """Test suite for logging.basicConfig.""" @@ -3864,16 +3917,18 @@ def test_strformatstyle(self): logging.basicConfig(stream=sys.stdout, style="{") logging.error("Log an error") sys.stdout.seek(0) - self.assertEqual(output.getvalue().strip(), - "ERROR:root:Log an error") + self.assertEqual( + output.getvalue().strip(), "ERROR:root:Log an error" + ) def test_stringtemplatestyle(self): with support.captured_stdout() as output: logging.basicConfig(stream=sys.stdout, style="$") logging.error("Log an error") sys.stdout.seek(0) - self.assertEqual(output.getvalue().strip(), - "ERROR:root:Log an error") + self.assertEqual( + output.getvalue().strip(), "ERROR:root:Log an error" + ) def test_filename(self): @@ -3950,11 +4005,11 @@ def test_incompatible(self): handlers = [logging.StreamHandler()] stream = sys.stderr assertRaises(ValueError, logging.basicConfig, filename='test.log', - stream=stream) + stream=stream) assertRaises(ValueError, logging.basicConfig, filename='test.log', - handlers=handlers) + handlers=handlers) assertRaises(ValueError, logging.basicConfig, stream=stream, - handlers=handlers) + handlers=handlers) # Issue 23207: test for invalid kwargs assertRaises(ValueError, logging.basicConfig, loglevel=logging.INFO) # Should pop both filename and filemode even if filename is None @@ -4003,6 +4058,7 @@ def _test_log(self, method, level=None): called = [] old_basic_config = logging.basicConfig + def my_basic_config(*a, **kw): old_basic_config() old_level = logging.root.level @@ -4479,6 +4535,7 @@ def rotator(source, dest): self.assertFalse(os.path.exists(namer(self.fn + ".3"))) rh.close() + class TimedRotatingFileHandlerTest(BaseFileTest): # other test methods added below def test_rollover(self): @@ -4501,7 +4558,7 @@ def test_rollover(self): # could of course still fail, but the chances are lower. found = False now = datetime.datetime.now() - GO_BACK = 5 * 60 # seconds + GO_BACK = 5 * 60 # seconds for secs in range(GO_BACK): prev = now - datetime.timedelta(seconds=secs) fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S") @@ -4547,7 +4604,7 @@ def test_compute_rollover_daily_attime(self): finally: rh.close() - #@unittest.skipIf(True, 'Temporarily skipped while failures investigated.') + # @unittest.skipIf(True, 'Temporarily skipped while failures investigated.') def test_compute_rollover_weekly_attime(self): currentTime = int(time.time()) today = currentTime - currentTime % 86400 @@ -4592,6 +4649,7 @@ def test_compute_rollover_weekly_attime(self): def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) + for when, exp in (('S', 1), ('M', 60), ('H', 60 * 60), @@ -4599,7 +4657,7 @@ def secs(**kw): ('MIDNIGHT', 60 * 60 * 24), # current time (epoch start) is a Thursday, W0 means Monday ('W0', secs(days=4, hours=24)), - ): + ): def test_compute_rollover(self, when=when, exp=exp): rh = logging.handlers.TimedRotatingFileHandler( self.fn, when=when, interval=1, backupCount=0, utc=True) @@ -4619,9 +4677,9 @@ def test_compute_rollover(self, when=when, exp=exp): currentMinute = t[4] currentSecond = t[5] # r is the number of seconds left between now and midnight - r = logging.handlers._MIDNIGHT - ((currentHour * 60 + - currentMinute) * 60 + - currentSecond) + r = logging.handlers._MIDNIGHT - ( + (currentHour * 60 + currentMinute) * 60 + currentSecond + ) result = currentTime + r print('t: %s (%s)' % (t, rh.utc), file=sys.stderr) print('currentHour: %s' % currentHour, file=sys.stderr) @@ -4656,7 +4714,7 @@ def test_basic(self): # Now see if the event is recorded self.assertLess(num_recs, win32evtlog.GetNumberOfEventLogRecords(elh)) flags = win32evtlog.EVENTLOG_BACKWARDS_READ | \ - win32evtlog.EVENTLOG_SEQUENTIAL_READ + win32evtlog.EVENTLOG_SEQUENTIAL_READ found = False GO_BACK = 100 events = win32evtlog.ReadEventLog(elh, flags, GO_BACK) @@ -4695,7 +4753,7 @@ def test_main(): StreamHandlerTest, LogRecordFactoryTest, ChildLoggerTest, QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest, LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest, - RotatingFileHandlerTest, LastResortTest, LogRecordTest, + RotatingFileHandlerTest, LastResortTest, LogRecordTest, ExceptionTest, SysLogHandlerTest, IPv6SysLogHandlerTest, HTTPHandlerTest, NTEventLogHandlerTest, TimedRotatingFileHandlerTest, UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest, @@ -4705,5 +4763,6 @@ def test_main(): tests.append(QueueListenerTest) support.run_unittest(*tests) + if __name__ == "__main__": test_main() From d45864bf23e041a227821d40decd48d8c2abf0a6 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 8 Aug 2018 00:30:59 +0530 Subject: [PATCH 03/14] fix(test/test_logging): Fix tests for HttpHandler --- Lib/test/test_logging.py | 10 ++++------ .../Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 58842ccebdc121..f2b08bf29aec41 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1889,9 +1889,7 @@ def handle_request(self, request): def test_output(self): # The log message sent to the HTTPHandler is properly received. - logger = logging.getLogger("http") - root_logger = self.root_logger - root_logger.removeHandler(self.root_logger.handlers[0]) + logger = logging.getLogger("httplogger") for secure in (False, True): addr = ('localhost', 0) if secure: @@ -1921,7 +1919,7 @@ def test_output(self): context=context, credentials=('foo', 'bar')) self.log_data = None - root_logger.addHandler(self.h_hdlr) + logger.addHandler(self.h_hdlr) for method in ('GET', 'POST'): self.h_hdlr.method = method @@ -1935,12 +1933,12 @@ def test_output(self): d = parse_qs(self.log_data.query) else: d = parse_qs(self.post_data.decode('utf-8')) - self.assertEqual(d['name'], ['http']) + self.assertEqual(d['name'], ['httplogger']) self.assertEqual(d['funcName'], ['test_output']) self.assertEqual(d['msg'], [msg]) self.server.stop(2.0) - self.root_logger.removeHandler(self.h_hdlr) + logger.removeHandler(self.h_hdlr) self.h_hdlr.close() diff --git a/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst b/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst index b7dbc56244877d..d124d049c97268 100644 --- a/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst +++ b/Misc/NEWS.d/next/Library/2018-08-02-23-51-44.bpo-24255.IZcKUO.rst @@ -1,2 +1,2 @@ Replaces debug level logic in http client with logging. Original patch by -Eryn Wells. Enhanced by Sanyam Khurana. +Eryn Wells & Conrad Ho. Enhanced by Sanyam Khurana. From 230784db63752f5112c2894274b0c0c1dfcf808e Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 8 Aug 2018 01:46:50 +0530 Subject: [PATCH 04/14] fix(test_httplib.py): Fix logging in tests --- Lib/http/client.py | 12 ++++++++---- Lib/test/test_httplib.py | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Lib/http/client.py b/Lib/http/client.py index 0a390b15a1bdd7..f946f607769c3a 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -320,9 +320,9 @@ def begin(self): self.headers = self.msg = parse_headers(self.fp) - if _log.isEnabledFor(logging.DEBUG): + if _log.isEnabledFor(logging.INFO): for hdr in self.headers: - _log.debug("Received header: ('%s': '%s')", hdr, self.headers[hdr]) + _log.info("Received header: ('%s': '%s')", hdr, self.headers[hdr]) # are we using the chunked-style of transfer encoding? tr_enc = self.headers.get("transfer-encoding") @@ -1065,7 +1065,7 @@ def _send_output(self, message_body=None, encode_chunked=False): for chunk in chunks: if not chunk: if self.debuglevel > 0: - print('Zero length chunk ignored') + _log.info('Zero length chunk ignored') continue if encode_chunked and self._http_vsn == 11: @@ -1334,7 +1334,11 @@ def getresponse(self): if self.__state != _CS_REQ_SENT or self.__response: raise ResponseNotReady(self.__state) - response = self.response_class(self.sock, method=self._method) + if self.debuglevel > 0: + response = self.response_class( + self.sock, self.debuglevel, method=self._method) + else: + response = self.response_class(self.sock, method=self._method) try: try: diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index f816eac83b682d..f6a9d55fe1c9f0 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -3,6 +3,8 @@ import io import itertools import os +import sys +import logging import array import socket import threading @@ -352,12 +354,16 @@ def test_headers_debuglevel(self): ) sock = FakeSocket(body) resp = client.HTTPResponse(sock, debuglevel=1) + logging.basicConfig(level=logging.INFO) with support.captured_stdout() as output: + output_handler = logging.StreamHandler(output) + _logger = logging.getLogger('http.client') + _logger.addHandler(output_handler) resp.begin() lines = output.getvalue().splitlines() - self.assertEqual(lines[0], "reply: 'HTTP/1.1 200 OK\\r\\n'") - self.assertEqual(lines[1], "header: First: val") - self.assertEqual(lines[2], "header: Second: val") + self.assertEqual(lines[0], "Received response: 200 OK") + self.assertEqual(lines[1], "Received header: ('First': 'val')") + self.assertEqual(lines[2], "Received header: ('Second': 'val')") class TransferEncodingTest(TestCase): @@ -1928,7 +1934,11 @@ def test_tunnel_debuglog(self): self.conn._create_connection = self._create_connection(response_text) self.conn.set_tunnel('destination.com') + logging.basicConfig(level=logging.INFO) with support.captured_stdout() as output: + output_handler = logging.StreamHandler(output) + _logger = logging.getLogger('http.client') + _logger.addHandler(output_handler) self.conn.request('PUT', '/', '') lines = output.getvalue().splitlines() self.assertIn('header: {}'.format(expected_header), lines) From 335a668792df0c64d1da13694968dfa2b4dfb54c Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 8 Aug 2018 10:42:06 +0530 Subject: [PATCH 05/14] Revert "fix(test_logging): Fix linting errors" This reverts commit 5f63c20e185b0ddc60dac0f4cde734092e00941a. --- Lib/test/test_logging.py | 833 ++++++++++++++++++--------------------- 1 file changed, 387 insertions(+), 446 deletions(-) diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index f2b08bf29aec41..90ffa7fcfb026c 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -56,9 +56,7 @@ ThreadingTCPServer, StreamRequestHandler) try: - import win32evtlog - import win32evtlogutil - import pywintypes + import win32evtlog, win32evtlogutil, pywintypes except ImportError: win32evtlog = win32evtlogutil = pywintypes = None @@ -67,7 +65,6 @@ except ImportError: pass - class BaseTest(unittest.TestCase): """Base class for logging tests.""" @@ -163,9 +160,8 @@ def assert_log_lines(self, expected_values, stream=None, pat=None): for actual, expected in zip(actual_lines, expected_values): match = pat.search(actual) if not match: - self.fail( - "Log line does not match expected pattern:\n" + actual - ) + self.fail("Log line does not match expected pattern:\n" + + actual) self.assertEqual(tuple(match.groups()), expected) s = stream.read() if s: @@ -234,7 +230,7 @@ def test_nested_explicit(self): INF = logging.getLogger("INF") INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") + INF_ERR = logging.getLogger("INF.ERR") INF_ERR.setLevel(logging.ERROR) # These should log. @@ -257,7 +253,7 @@ def test_nested_inherited(self): INF = logging.getLogger("INF") INF.setLevel(logging.INFO) - INF_ERR = logging.getLogger("INF.ERR") + INF_ERR = logging.getLogger("INF.ERR") INF_ERR.setLevel(logging.ERROR) INF_UNDEF = logging.getLogger("INF.UNDEF") INF_ERR_UNDEF = logging.getLogger("INF.ERR.UNDEF") @@ -335,7 +331,6 @@ def test_regression_29220(self): self.assertEqual(logging.getLevelName(logging.NOTSET), 'NOTSET') self.assertEqual(logging.getLevelName('NOTSET'), logging.NOTSET) - class BasicFilterTest(BaseTest): """Test the bundled Filter class.""" @@ -400,24 +395,22 @@ def test_empty_filter(self): # # First, we define our levels. There can be as many as you want - the only -# limitations are that they should be integers, the lowest should be > 0 and +# limitations are that they should be integers, the lowest should be > 0 and # larger values mean less information being logged. If you need specific # level values which do not fit into these limitations, you can use a # mapping dictionary to convert between your application levels and the # logging system. # - - -SILENT = 120 -TACITURN = 119 -TERSE = 118 -EFFUSIVE = 117 -SOCIABLE = 116 -VERBOSE = 115 -TALKATIVE = 114 -GARRULOUS = 113 -CHATTERBOX = 112 -BORING = 111 +SILENT = 120 +TACITURN = 119 +TERSE = 118 +EFFUSIVE = 117 +SOCIABLE = 116 +VERBOSE = 115 +TALKATIVE = 114 +GARRULOUS = 113 +CHATTERBOX = 112 +BORING = 111 LEVEL_RANGE = range(BORING, SILENT + 1) @@ -426,19 +419,18 @@ def test_empty_filter(self): # case the system will use "Level n" to denote the text for the level. # my_logging_levels = { - SILENT: 'Silent', - TACITURN: 'Taciturn', - TERSE: 'Terse', - EFFUSIVE: 'Effusive', - SOCIABLE: 'Sociable', - VERBOSE: 'Verbose', - TALKATIVE: 'Talkative', - GARRULOUS: 'Garrulous', - CHATTERBOX: 'Chatterbox', - BORING: 'Boring', + SILENT : 'Silent', + TACITURN : 'Taciturn', + TERSE : 'Terse', + EFFUSIVE : 'Effusive', + SOCIABLE : 'Sociable', + VERBOSE : 'Verbose', + TALKATIVE : 'Talkative', + GARRULOUS : 'Garrulous', + CHATTERBOX : 'Chatterbox', + BORING : 'Boring', } - class GarrulousFilter(logging.Filter): """A filter which blocks garrulous messages.""" @@ -446,7 +438,6 @@ class GarrulousFilter(logging.Filter): def filter(self, record): return record.levelno != GARRULOUS - class VerySpecificFilter(logging.Filter): """A filter which blocks sociable and taciturn messages.""" @@ -537,7 +528,7 @@ def test_specific_filters(self): ('Effusive', '17'), ('Terse', '18'), ('Silent', '20'), - ]) + ]) finally: if specific_filter: self.root_logger.removeFilter(specific_filter) @@ -590,7 +581,7 @@ def test_builtin_handlers(self): self.assertEqual(h.facility, h.LOG_USER) self.assertTrue(h.unixsocket) h.close() - except OSError: # syslogd might not be available + except OSError: # syslogd might not be available pass for method in ('GET', 'POST', 'PUT'): if method == 'PUT': @@ -618,10 +609,10 @@ def test_path_objects(self): os.unlink(fn) pfn = pathlib.Path(fn) cases = ( - (logging.FileHandler, (pfn, 'w')), - (logging.handlers.RotatingFileHandler, (pfn, 'a')), - (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), - ) + (logging.FileHandler, (pfn, 'w')), + (logging.handlers.RotatingFileHandler, (pfn, 'a')), + (logging.handlers.TimedRotatingFileHandler, (pfn, 'h')), + ) if sys.platform in ('linux', 'darwin'): cases += ((logging.handlers.WatchedFileHandler, (pfn, 'w')),) for cls, args in cases: @@ -660,7 +651,7 @@ def remove_loop(fname, tries): try: for _ in range(log_count): time.sleep(0.005) - r = logging.makeLogRecord({'msg': 'testing'}) + r = logging.makeLogRecord({'msg': 'testing' }) try: self.handle_time = time.time() h.handle(r) @@ -680,12 +671,10 @@ class BadStream(object): def write(self, data): raise RuntimeError('deliberate mistake') - class TestStreamHandler(logging.StreamHandler): def handleError(self, record): self.error_record = record - class StreamHandlerTest(BaseTest): def test_error_handling(self): h = TestStreamHandler(BadStream()) @@ -726,7 +715,6 @@ def test_stream_setting(self): # -- The following section could be moved into a server_helper.py module # -- if it proves to be of wider utility than just test_logging - class TestSMTPServer(smtpd.SMTPServer): """ This class implements a test SMTP server. @@ -854,7 +842,6 @@ def stop(self, timeout=None): self.server_close() self.ready.clear() - class TestHTTPServer(ControlMixin, HTTPServer): """ An HTTP server which is controllable using :class:`ControlMixin`. @@ -896,7 +883,6 @@ def get_request(self): raise return sock, addr - class TestTCPServer(ControlMixin, ThreadingTCPServer): """ A TCP server which is controllable using :class:`ControlMixin`. @@ -928,7 +914,6 @@ def server_bind(self): super(TestTCPServer, self).server_bind() self.port = self.socket.getsockname()[1] - class TestUDPServer(ControlMixin, ThreadingUDPServer): """ A UDP server which is controllable using :class:`ControlMixin`. @@ -976,7 +961,6 @@ def server_close(self): super(TestUDPServer, self).server_close() self._closed = True - if hasattr(socket, "AF_UNIX"): class TestUnixStreamServer(TestTCPServer): address_family = socket.AF_UNIX @@ -986,7 +970,6 @@ class TestUnixDatagramServer(TestUDPServer): # - end of server_helper section - class SMTPHandlerTest(BaseTest): # bpo-14314, bpo-19665, bpo-34092: don't wait forever, timeout of 1 minute TIMEOUT = 60.0 @@ -1019,7 +1002,6 @@ def process_message(self, *args): self.messages.append(args) self.handled.set() - class MemoryHandlerTest(BaseTest): """Tests for the MemoryHandler.""" @@ -1429,10 +1411,8 @@ def test_config4_ok(self): except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual( - output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n" - ) + self.assertEqual(output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n") # Original logger output is empty self.assert_log_lines([]) @@ -1650,7 +1630,6 @@ def test_noserver(self): time.sleep(self.sock_hdlr.retryTime - now + 0.001) self.root_logger.error('Nor this') - def _get_temp_domain_socket(): fd, fn = tempfile.mkstemp(prefix='test_logging_', suffix='.sock') os.close(fd) @@ -1659,7 +1638,6 @@ def _get_temp_domain_socket(): os.remove(fn) return fn - @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixSocketHandlerTest(SocketHandlerTest): @@ -1677,7 +1655,6 @@ def tearDown(self): SocketHandlerTest.tearDown(self) support.unlink(self.address) - class DatagramHandlerTest(BaseTest): """Test for DatagramHandler.""" @@ -1723,7 +1700,7 @@ def tearDown(self): BaseTest.tearDown(self) def handle_datagram(self, request): - slen = struct.pack('>L', 0) # length of prefix + slen = struct.pack('>L', 0) # length of prefix packet = request.packet[len(slen):] obj = pickle.loads(packet) record = logging.makeLogRecord(obj) @@ -1742,7 +1719,6 @@ def test_output(self): self.handled.wait() self.assertEqual(self.log_output, "spam\neggs\n") - @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixDatagramHandlerTest(DatagramHandlerTest): @@ -1760,7 +1736,6 @@ def tearDown(self): DatagramHandlerTest.tearDown(self) support.unlink(self.address) - class SysLogHandlerTest(BaseTest): """Test for SysLogHandler using UDP.""" @@ -1828,7 +1803,6 @@ def test_output(self): self.handled.wait() self.assertEqual(self.log_output, b'<11>h\xc3\xa4m-sp\xc3\xa4m') - @unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required") class UnixSysLogHandlerTest(SysLogHandlerTest): @@ -1846,7 +1820,6 @@ def tearDown(self): SysLogHandlerTest.tearDown(self) support.unlink(self.address) - @unittest.skipUnless(support.IPV6_ENABLED, 'IPv6 support required for this test.') class IPv6SysLogHandlerTest(SysLogHandlerTest): @@ -1864,7 +1837,6 @@ def tearDown(self): self.server_class.address_family = socket.AF_INET super(IPv6SysLogHandlerTest, self).tearDown() - class HTTPHandlerTest(BaseTest): """Test for HTTPHandler.""" @@ -1881,7 +1853,7 @@ def handle_request(self, request): try: rlen = int(request.headers['Content-Length']) self.post_data = request.rfile.read(rlen) - except Exception: + except: self.post_data = None request.send_response(200) request.end_headers() @@ -1907,9 +1879,8 @@ def test_output(self): else: sslctx = None context = None - self.server = server = TestHTTPServer( - addr, self.handle_request, 0.01, sslctx=sslctx - ) + self.server = server = TestHTTPServer(addr, self.handle_request, + 0.01, sslctx=sslctx) server.start() server.ready.wait() host = 'localhost:%d' % server.server_port @@ -1941,7 +1912,6 @@ def test_output(self): logger.removeHandler(self.h_hdlr) self.h_hdlr.close() - class MemoryTest(BaseTest): """Test memory persistence of logger objects.""" @@ -1967,10 +1937,8 @@ def _assertTruesurvival(self): if ref() is None: dead.append(repr_) if dead: - self.fail( - "%d objects should have survived but have been destroyed: %s" - % (len(dead), ", ".join(dead)) - ) + self.fail("%d objects should have survived " + "but have been destroyed: %s" % (len(dead), ", ".join(dead))) def test_persistent_loggers(self): # Logger objects are persistent and retain their configuration, even @@ -2068,9 +2036,8 @@ def test_warnings(self): a_file, "Dummy line") s = a_file.getvalue() a_file.close() - self.assertEqual( - s, "dummy.py:42: UserWarning: Explicit\n Dummy line\n" - ) + self.assertEqual(s, + "dummy.py:42: UserWarning: Explicit\n Dummy line\n") def test_warnings_no_handlers(self): with warnings.catch_warnings(): @@ -2089,15 +2056,12 @@ def test_warnings_no_handlers(self): def formatFunc(format, datefmt=None): return logging.Formatter(format, datefmt) - def handlerFunc(): return logging.StreamHandler() - class CustomHandler(logging.StreamHandler): pass - class ConfigDictTest(BaseTest): """Reading logging config from a dictionary.""" @@ -2109,21 +2073,21 @@ class ConfigDictTest(BaseTest): config0 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'root': { - 'level': 'WARNING', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], }, } @@ -2131,26 +2095,26 @@ class ConfigDictTest(BaseTest): config1 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2158,26 +2122,26 @@ class ConfigDictTest(BaseTest): config1a = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', }, }, - 'root': { - 'level': 'WARNING', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], }, } @@ -2185,26 +2149,26 @@ class ConfigDictTest(BaseTest): config2 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdbout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdbout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2212,53 +2176,54 @@ class ConfigDictTest(BaseTest): config2a = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NTOSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NTOSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } + # As config1 but with a misspelt level on a logger config2b = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WRANING', + 'root' : { + 'level' : 'WRANING', }, } @@ -2266,26 +2231,26 @@ class ConfigDictTest(BaseTest): config3 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'misspelled_name', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'misspelled_name', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2293,22 +2258,22 @@ class ConfigDictTest(BaseTest): config4 = { 'version': 1, 'formatters': { - 'form1': { - '()': __name__ + '.ExceptionFormatter', - 'format': '%(levelname)s:%(name)s:%(message)s', + 'form1' : { + '()' : __name__ + '.ExceptionFormatter', + 'format' : '%(levelname)s:%(name)s:%(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'root': { - 'level': 'NOTSET', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'NOTSET', + 'handlers' : ['hand1'], }, } @@ -2316,33 +2281,33 @@ class ConfigDictTest(BaseTest): config4a = { 'version': 1, 'formatters': { - 'form1': { - '()': ExceptionFormatter, - 'format': '%(levelname)s:%(name)s:%(message)s', + 'form1' : { + '()' : ExceptionFormatter, + 'format' : '%(levelname)s:%(name)s:%(message)s', }, - 'form2': { - '()': __name__ + '.formatFunc', - 'format': '%(levelname)s:%(name)s:%(message)s', + 'form2' : { + '()' : __name__ + '.formatFunc', + 'format' : '%(levelname)s:%(name)s:%(message)s', }, - 'form3': { - '()': formatFunc, - 'format': '%(levelname)s:%(name)s:%(message)s', + 'form3' : { + '()' : formatFunc, + 'format' : '%(levelname)s:%(name)s:%(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, - 'hand2': { - '()': handlerFunc, + 'hand2' : { + '()' : handlerFunc, }, }, - 'root': { - 'level': 'NOTSET', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'NOTSET', + 'handlers' : ['hand1'], }, } @@ -2350,26 +2315,26 @@ class ConfigDictTest(BaseTest): config5 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': __name__ + '.CustomHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : __name__ + '.CustomHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2378,27 +2343,27 @@ class ConfigDictTest(BaseTest): config6 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': __name__ + '.CustomHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', - '9': 'invalid parameter name', + 'handlers' : { + 'hand1' : { + 'class' : __name__ + '.CustomHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', + '9' : 'invalid parameter name', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2407,26 +2372,26 @@ class ConfigDictTest(BaseTest): config7 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.lexer': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.lexer' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2435,115 +2400,115 @@ class ConfigDictTest(BaseTest): # compiler is defined) config8 = { 'version': 1, - 'disable_existing_loggers': False, + 'disable_existing_loggers' : False, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, - 'compiler.lexer': { + 'compiler.lexer' : { }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } # config8a disables existing loggers config8a = { 'version': 1, - 'disable_existing_loggers': True, + 'disable_existing_loggers' : True, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, - 'compiler.lexer': { + 'compiler.lexer' : { }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } config9 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'WARNING', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'WARNING', + 'stream' : 'ext://sys.stdout', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'WARNING', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'NOTSET', + 'root' : { + 'level' : 'NOTSET', }, } config9a = { 'version': 1, - 'incremental': True, - 'handlers': { - 'hand1': { - 'level': 'WARNING', + 'incremental' : True, + 'handlers' : { + 'hand1' : { + 'level' : 'WARNING', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'INFO', + 'loggers' : { + 'compiler.parser' : { + 'level' : 'INFO', }, }, } config9b = { 'version': 1, - 'incremental': True, - 'handlers': { - 'hand1': { - 'level': 'INFO', + 'incremental' : True, + 'handlers' : { + 'hand1' : { + 'level' : 'INFO', }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'INFO', + 'loggers' : { + 'compiler.parser' : { + 'level' : 'INFO', }, }, } @@ -2552,33 +2517,33 @@ class ConfigDictTest(BaseTest): config10 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'filters': { - 'filt1': { - 'name': 'compiler.parser', + 'filters' : { + 'filt1' : { + 'name' : 'compiler.parser', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', - 'filters': ['filt1'], + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', + 'filters' : ['filt1'], }, }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'filters': ['filt1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'filters' : ['filt1'], }, }, - 'root': { - 'level': 'WARNING', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], }, } @@ -2586,60 +2551,60 @@ class ConfigDictTest(BaseTest): config11 = { 'version': 1, 'true_formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'formatters': 'cfg://true_formatters', - 'handlers': { - 'hand1': 'cfg://handler_configs[hand1]', + 'formatters' : 'cfg://true_formatters', + 'handlers' : { + 'hand1' : 'cfg://handler_configs[hand1]', }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } # As config11 but missing the version key config12 = { 'true_formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'formatters': 'cfg://true_formatters', - 'handlers': { - 'hand1': 'cfg://handler_configs[hand1]', + 'formatters' : 'cfg://true_formatters', + 'handlers' : { + 'hand1' : 'cfg://handler_configs[hand1]', }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2647,30 +2612,30 @@ class ConfigDictTest(BaseTest): config13 = { 'version': 2, 'true_formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, 'handler_configs': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', }, }, - 'formatters': 'cfg://true_formatters', - 'handlers': { - 'hand1': 'cfg://handler_configs[hand1]', + 'formatters' : 'cfg://true_formatters', + 'handlers' : { + 'hand1' : 'cfg://handler_configs[hand1]', }, - 'loggers': { - 'compiler.parser': { - 'level': 'DEBUG', - 'handlers': ['hand1'], + 'loggers' : { + 'compiler.parser' : { + 'level' : 'DEBUG', + 'handlers' : ['hand1'], }, }, - 'root': { - 'level': 'WARNING', + 'root' : { + 'level' : 'WARNING', }, } @@ -2678,25 +2643,25 @@ class ConfigDictTest(BaseTest): config14 = { 'version': 1, 'formatters': { - 'form1': { - 'format': '%(levelname)s ++ %(message)s', + 'form1' : { + 'format' : '%(levelname)s ++ %(message)s', }, }, - 'handlers': { - 'hand1': { - 'class': 'logging.StreamHandler', - 'formatter': 'form1', - 'level': 'NOTSET', - 'stream': 'ext://sys.stdout', + 'handlers' : { + 'hand1' : { + 'class' : 'logging.StreamHandler', + 'formatter' : 'form1', + 'level' : 'NOTSET', + 'stream' : 'ext://sys.stdout', '.': { 'foo': 'bar', 'terminator': '!\n', } }, }, - 'root': { - 'level': 'WARNING', - 'handlers': ['hand1'], + 'root' : { + 'level' : 'WARNING', + 'handlers' : ['hand1'], }, } @@ -2720,7 +2685,7 @@ class ConfigDictTest(BaseTest): "formatter": "mySimpleFormatter", "target": "fileGlobal", "level": "DEBUG" - } + } }, "loggers": { "mymodule": { @@ -2784,16 +2749,14 @@ def test_config4_ok(self): # A config specifying a custom formatter class. with support.captured_stdout() as output: self.apply_config(self.config4) - # logger = logging.getLogger() + #logger = logging.getLogger() try: raise RuntimeError() except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual( - output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n" - ) + self.assertEqual(output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n") # Original logger output is empty self.assert_log_lines([]) @@ -2801,16 +2764,14 @@ def test_config4a_ok(self): # A config specifying a custom formatter class. with support.captured_stdout() as output: self.apply_config(self.config4a) - # logger = logging.getLogger() + #logger = logging.getLogger() try: raise RuntimeError() except RuntimeError: logging.exception("just testing") sys.stdout.seek(0) - self.assertEqual( - output.getvalue(), - "ERROR:root:just testing\nGot a [RuntimeError]\n" - ) + self.assertEqual(output.getvalue(), + "ERROR:root:just testing\nGot a [RuntimeError]\n") # Original logger output is empty self.assert_log_lines([]) @@ -3143,7 +3104,7 @@ def test_baseconfig(self): d = { 'atuple': (1, 2, 3), 'alist': ['a', 'b', 'c'], - 'adict': {'d': 'e', 'f': 3}, + 'adict': {'d': 'e', 'f': 3 }, 'nest1': ('g', ('h', 'i'), 'j'), 'nest2': ['k', ['l', 'm'], 'n'], 'nest3': ['o', 'cfg://alist', 'p'], @@ -3161,7 +3122,6 @@ def test_baseconfig(self): self.assertRaises(ValueError, bc.convert, 'cfg://!') self.assertRaises(KeyError, bc.convert, 'cfg://adict[2]') - class ManagerTest(BaseTest): def test_manager_loggerclass(self): logged = [] @@ -3185,7 +3145,6 @@ def test_set_log_record_factory(self): man.setLogRecordFactory(expected) self.assertEqual(man.logRecordFactory, expected) - class ChildLoggerTest(BaseTest): def test_child_loggers(self): r = logging.getLogger() @@ -3206,7 +3165,6 @@ def test_child_loggers(self): class DerivedLogRecord(logging.LogRecord): pass - class LogRecordFactoryTest(BaseTest): def setUp(self): @@ -3217,8 +3175,8 @@ def __init__(self, cls): def filter(self, record): t = type(record) if t is not self.cls: - msg = 'Unexpected LogRecord type %s, expected %s' % ( - t, self.cls) + msg = 'Unexpected LogRecord type %s, expected %s' % (t, + self.cls) raise TypeError(msg) return True @@ -3238,7 +3196,7 @@ def test_logrecord_class(self): logging.setLogRecordFactory(DerivedLogRecord) self.root_logger.error(self.next_message()) self.assert_log_lines([ - ('root', 'ERROR', '2'), + ('root', 'ERROR', '2'), ]) @@ -3319,7 +3277,6 @@ def test_queue_listener(self): self.assertFalse(handler.matches(levelno=logging.ERROR, message='5')) self.assertTrue(handler.matches(levelno=logging.CRITICAL, message='6')) - if hasattr(logging.handlers, 'QueueListener'): import multiprocessing from unittest.mock import patch @@ -3397,25 +3354,21 @@ def test_no_messages_in_queue_after_stop(self): support.import_module('multiprocessing.synchronize') for i in range(self.repeat): queue = multiprocessing.Queue() - self.setup_and_log(queue, '%s_%s' % (self.id(), i)) + self.setup_and_log(queue, '%s_%s' %(self.id(), i)) # time.sleep(1) items = list(self.get_all_from_queue(queue)) queue.close() queue.join_thread() expected = [[], [logging.handlers.QueueListener._sentinel]] - self.assertIn( - items, expected, 'Found unexpected messages in queue: %s' - '' % ([ - m.msg if isinstance(m, logging.LogRecord) - else m for m in items] - ) - ) + self.assertIn(items, expected, + 'Found unexpected messages in queue: %s' % ( + [m.msg if isinstance(m, logging.LogRecord) + else m for m in items])) ZERO = datetime.timedelta(0) - class UTC(datetime.tzinfo): def utcoffset(self, dt): return ZERO @@ -3425,10 +3378,8 @@ def utcoffset(self, dt): def tzname(self, dt): return 'UTC' - utc = UTC() - class FormatterTest(unittest.TestCase): def setUp(self): self.common = { @@ -3518,7 +3469,6 @@ def test_time(self): f.format(r) self.assertEqual(r.asctime, '1993-04-21 08:03:00,123') - class TestBufferingFormatter(logging.BufferingFormatter): def formatHeader(self, records): return '[(%d)' % len(records) @@ -3526,7 +3476,6 @@ def formatHeader(self, records): def formatFooter(self, records): return '(%d)]' % len(records) - class BufferingFormatterTest(unittest.TestCase): def setUp(self): self.records = [ @@ -3546,7 +3495,6 @@ def test_custom(self): f = TestBufferingFormatter(lf) self.assertEqual('[(2)(2)]', f.format(self.records)) - class ExceptionTest(BaseTest): def test_formatting(self): r = self.root_logger @@ -3554,7 +3502,7 @@ def test_formatting(self): r.addHandler(h) try: raise RuntimeError('deliberate mistake') - except Exception: + except: logging.exception('failed', stack_info=True) r.removeHandler(h) h.close() @@ -3564,9 +3512,9 @@ def test_formatting(self): self.assertTrue(r.exc_text.endswith('\nRuntimeError: ' 'deliberate mistake')) self.assertTrue(r.stack_info.startswith('Stack (most recent ' - 'call last):\n')) + 'call last):\n')) self.assertTrue(r.stack_info.endswith('logging.exception(\'failed\', ' - 'stack_info=True)')) + 'stack_info=True)')) class LastResortTest(BaseTest): @@ -3821,7 +3769,7 @@ def test_dict_arg(self): h = RecordingHandler() r = logging.getLogger() r.addHandler(h) - d = {'less': 'more'} + d = {'less' : 'more' } logging.warning('less is %(less)s', d) self.assertIs(h.records[0].args, d) self.assertEqual(h.records[0].message, 'less is more') @@ -3863,7 +3811,6 @@ def test_optional(self): logging.logProcesses = log_processes logging.logMultiprocessing = log_multiprocessing - class BasicConfigTest(unittest.TestCase): """Test suite for logging.basicConfig.""" @@ -3915,18 +3862,16 @@ def test_strformatstyle(self): logging.basicConfig(stream=sys.stdout, style="{") logging.error("Log an error") sys.stdout.seek(0) - self.assertEqual( - output.getvalue().strip(), "ERROR:root:Log an error" - ) + self.assertEqual(output.getvalue().strip(), + "ERROR:root:Log an error") def test_stringtemplatestyle(self): with support.captured_stdout() as output: logging.basicConfig(stream=sys.stdout, style="$") logging.error("Log an error") sys.stdout.seek(0) - self.assertEqual( - output.getvalue().strip(), "ERROR:root:Log an error" - ) + self.assertEqual(output.getvalue().strip(), + "ERROR:root:Log an error") def test_filename(self): @@ -4003,11 +3948,11 @@ def test_incompatible(self): handlers = [logging.StreamHandler()] stream = sys.stderr assertRaises(ValueError, logging.basicConfig, filename='test.log', - stream=stream) + stream=stream) assertRaises(ValueError, logging.basicConfig, filename='test.log', - handlers=handlers) + handlers=handlers) assertRaises(ValueError, logging.basicConfig, stream=stream, - handlers=handlers) + handlers=handlers) # Issue 23207: test for invalid kwargs assertRaises(ValueError, logging.basicConfig, loglevel=logging.INFO) # Should pop both filename and filemode even if filename is None @@ -4056,7 +4001,6 @@ def _test_log(self, method, level=None): called = [] old_basic_config = logging.basicConfig - def my_basic_config(*a, **kw): old_basic_config() old_level = logging.root.level @@ -4533,7 +4477,6 @@ def rotator(source, dest): self.assertFalse(os.path.exists(namer(self.fn + ".3"))) rh.close() - class TimedRotatingFileHandlerTest(BaseFileTest): # other test methods added below def test_rollover(self): @@ -4556,7 +4499,7 @@ def test_rollover(self): # could of course still fail, but the chances are lower. found = False now = datetime.datetime.now() - GO_BACK = 5 * 60 # seconds + GO_BACK = 5 * 60 # seconds for secs in range(GO_BACK): prev = now - datetime.timedelta(seconds=secs) fn = self.fn + prev.strftime(".%Y-%m-%d_%H-%M-%S") @@ -4602,7 +4545,7 @@ def test_compute_rollover_daily_attime(self): finally: rh.close() - # @unittest.skipIf(True, 'Temporarily skipped while failures investigated.') + #@unittest.skipIf(True, 'Temporarily skipped while failures investigated.') def test_compute_rollover_weekly_attime(self): currentTime = int(time.time()) today = currentTime - currentTime % 86400 @@ -4647,7 +4590,6 @@ def test_compute_rollover_weekly_attime(self): def secs(**kw): return datetime.timedelta(**kw) // datetime.timedelta(seconds=1) - for when, exp in (('S', 1), ('M', 60), ('H', 60 * 60), @@ -4655,7 +4597,7 @@ def secs(**kw): ('MIDNIGHT', 60 * 60 * 24), # current time (epoch start) is a Thursday, W0 means Monday ('W0', secs(days=4, hours=24)), - ): + ): def test_compute_rollover(self, when=when, exp=exp): rh = logging.handlers.TimedRotatingFileHandler( self.fn, when=when, interval=1, backupCount=0, utc=True) @@ -4675,9 +4617,9 @@ def test_compute_rollover(self, when=when, exp=exp): currentMinute = t[4] currentSecond = t[5] # r is the number of seconds left between now and midnight - r = logging.handlers._MIDNIGHT - ( - (currentHour * 60 + currentMinute) * 60 + currentSecond - ) + r = logging.handlers._MIDNIGHT - ((currentHour * 60 + + currentMinute) * 60 + + currentSecond) result = currentTime + r print('t: %s (%s)' % (t, rh.utc), file=sys.stderr) print('currentHour: %s' % currentHour, file=sys.stderr) @@ -4712,7 +4654,7 @@ def test_basic(self): # Now see if the event is recorded self.assertLess(num_recs, win32evtlog.GetNumberOfEventLogRecords(elh)) flags = win32evtlog.EVENTLOG_BACKWARDS_READ | \ - win32evtlog.EVENTLOG_SEQUENTIAL_READ + win32evtlog.EVENTLOG_SEQUENTIAL_READ found = False GO_BACK = 100 events = win32evtlog.ReadEventLog(elh, flags, GO_BACK) @@ -4751,7 +4693,7 @@ def test_main(): StreamHandlerTest, LogRecordFactoryTest, ChildLoggerTest, QueueHandlerTest, ShutdownTest, ModuleLevelMiscTest, BasicConfigTest, LoggerAdapterTest, LoggerTest, SMTPHandlerTest, FileHandlerTest, - RotatingFileHandlerTest, LastResortTest, LogRecordTest, + RotatingFileHandlerTest, LastResortTest, LogRecordTest, ExceptionTest, SysLogHandlerTest, IPv6SysLogHandlerTest, HTTPHandlerTest, NTEventLogHandlerTest, TimedRotatingFileHandlerTest, UnixSocketHandlerTest, UnixDatagramHandlerTest, UnixSysLogHandlerTest, @@ -4761,6 +4703,5 @@ def test_main(): tests.append(QueueListenerTest) support.run_unittest(*tests) - if __name__ == "__main__": test_main() From ed6ce82d7914b17c231347724be1872a4459432f Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 8 Aug 2018 10:56:33 +0530 Subject: [PATCH 06/14] fix test_httplib for logging --- Lib/http/client.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/http/client.py b/Lib/http/client.py index f946f607769c3a..5d87603c2436c7 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -938,6 +938,9 @@ def _tunnel(self): if line in (b'\r\n', b'\n', b''): break + if self.debuglevel > 0: + _log.info('header: {}'.format(line.decode())) + def connect(self): """Connect to the host and port specified in __init__.""" _log.debug('Opening socket to %s:%s', self.host, self.port) From d66ea059222a9313f09d032593ff59e13ab547e5 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Wed, 15 Aug 2018 21:35:23 +0530 Subject: [PATCH 07/14] Minor fixes --- Lib/http/client.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Lib/http/client.py b/Lib/http/client.py index 5d87603c2436c7..19bad43751c459 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -261,6 +261,8 @@ def _read_status(self): line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") if len(line) > _MAXLINE: raise LineTooLong("status line") + if self.debuglevel > 0: + _log.info("reply: {}".format(repr(line))) if not line: # Presumably, the server closed the connection before # sending a valid response. @@ -308,6 +310,9 @@ def begin(self): if not skip: break + if self.debuglevel > 0: + _log.info("header: {}".format(skip)) + self.code = self.status = status self.reason = reason.strip() if version in ("HTTP/1.0", "HTTP/0.9"): From 76d8d5bd920d71548b1f5acb4ef804626d7c2cec Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 27 Aug 2018 09:55:32 +0530 Subject: [PATCH 08/14] Minor fixes --- Lib/test/test_httplib.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index f6a9d55fe1c9f0..6c9714a3c8b059 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -348,9 +348,9 @@ def test_invalid_headers(self): def test_headers_debuglevel(self): body = ( - b'HTTP/1.1 200 OK\r\n' - b'First: val\r\n' - b'Second: val\r\n' + b'200 OK' + b'First: val' + b'Second: val' ) sock = FakeSocket(body) resp = client.HTTPResponse(sock, debuglevel=1) From ea3b6d508dee5739098d0a189471cb98bdf9063e Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 27 Aug 2018 10:10:19 +0530 Subject: [PATCH 09/14] Fix tests --- Lib/test/test_httplib.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 6c9714a3c8b059..5f9cc4c251011d 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -348,9 +348,9 @@ def test_invalid_headers(self): def test_headers_debuglevel(self): body = ( - b'200 OK' - b'First: val' - b'Second: val' + b'HTTP/1.1 200 OK\r\n' + b'First: val\r\n' + b'Second: val\r\n' ) sock = FakeSocket(body) resp = client.HTTPResponse(sock, debuglevel=1) @@ -361,9 +361,10 @@ def test_headers_debuglevel(self): _logger.addHandler(output_handler) resp.begin() lines = output.getvalue().splitlines() - self.assertEqual(lines[0], "Received response: 200 OK") - self.assertEqual(lines[1], "Received header: ('First': 'val')") - self.assertEqual(lines[2], "Received header: ('Second': 'val')") + self.assertEqual(lines[0], "reply: 'HTTP/1.1 200 OK\\r\\n'") + self.assertEqual(lines[1], "Received response: 200 OK") + self.assertEqual(lines[2], "Received header: ('First': 'val')") + self.assertEqual(lines[3], "Received header: ('Second': 'val')") class TransferEncodingTest(TestCase): From c247e9400597ccf99206481925d74acd11c4b579 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 27 Aug 2018 12:19:45 +0530 Subject: [PATCH 10/14] Prevent the alteration of test env by logging handlers --- Lib/test/test_httplib.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 5f9cc4c251011d..77e73e94011c6a 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -128,6 +128,17 @@ def create_connection(self, *pos, **kw): return FakeSocket(*self.fake_socket_args) class HeaderTests(TestCase): + + def setUp(self): + self.handlers = logging.root.handlers + self.saved_handlers = logging._handlers.copy() + self.saved_handler_list = logging._handlerList[:] + + def tearDown(self): + logging._handlers.clear() + logging._handlers.update(self.saved_handlers) + logging._handlerList[:] = self.saved_handler_list + def test_auto_headers(self): # Some headers are added automatically, but should not be added by # .request() if they are explicitly set. @@ -1878,8 +1889,14 @@ def setUp(self): self.host = 'proxy.com' self.conn = client.HTTPConnection(self.host) self.conn._create_connection = self._create_connection(response_text) + self.handlers = logging.root.handlers + self.saved_handlers = logging._handlers.copy() + self.saved_handler_list = logging._handlerList[:] def tearDown(self): + logging._handlers.clear() + logging._handlers.update(self.saved_handlers) + logging._handlerList[:] = self.saved_handler_list self.conn.close() def _create_connection(self, response_text): From 68d5f5a2076a6016fd3983c3bc2dab87b7f2c300 Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Mon, 27 Aug 2018 12:36:10 +0530 Subject: [PATCH 11/14] Minor flake8 fixes --- Lib/test/test_httplib.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 77e73e94011c6a..68d0c6a3df9623 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -1879,11 +1879,13 @@ def test_getting_header_defaultint(self): header = self.resp.getheader('No-Such-Header',default=42) self.assertEqual(header, 42) + class TunnelTests(TestCase): + def setUp(self): response_text = ( - 'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT - 'HTTP/1.1 200 OK\r\n' # Reply to HEAD + 'HTTP/1.0 200 OK\r\n\r\n' # Reply to CONNECT + 'HTTP/1.1 200 OK\r\n' # Reply to HEAD 'Content-Length: 42\r\n\r\n' ) self.host = 'proxy.com' From bc49a77fcba5f4eabf1c31898eadeb3205d1a71f Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Fri, 10 May 2019 21:03:19 +0530 Subject: [PATCH 12/14] bpo-24255: Fix tests --- Lib/test/test_httplib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index 4f68983204e357..e4dd59b23c69b0 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -376,8 +376,8 @@ def test_headers_debuglevel(self): lines = output.getvalue().splitlines() self.assertEqual(lines[0], "reply: 'HTTP/1.1 200 OK\\r\\n'") self.assertEqual(lines[1], "Received response: 200 OK") - self.assertEqual(lines[2], "Received header: ('First': 'val')") - self.assertEqual(lines[3], "Received header: ('Second': 'val')") + self.assertEqual(lines[2], "Received header: ('First': 'val1')") + self.assertEqual(lines[3], "Received header: ('Second': 'val2')") class TransferEncodingTest(TestCase): From 5c9062deceefa1ffeac2a23860215ef4fd97244d Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Sat, 11 May 2019 19:13:32 +0530 Subject: [PATCH 13/14] Minor fix in the tests --- Lib/test/test_httplib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index e4dd59b23c69b0..c4115655832d23 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -376,8 +376,8 @@ def test_headers_debuglevel(self): lines = output.getvalue().splitlines() self.assertEqual(lines[0], "reply: 'HTTP/1.1 200 OK\\r\\n'") self.assertEqual(lines[1], "Received response: 200 OK") - self.assertEqual(lines[2], "Received header: ('First': 'val1')") - self.assertEqual(lines[3], "Received header: ('Second': 'val2')") + self.assertEqual(lines[2], "Received header: ('First': 'val')") + self.assertEqual(lines[3], "Received header: ('Second': 'val1')") class TransferEncodingTest(TestCase): From bba622483e1651fa036c03aefbc6a5517cf6736d Mon Sep 17 00:00:00 2001 From: Sanyam Khurana Date: Fri, 21 Jun 2019 16:11:03 +0530 Subject: [PATCH 14/14] Address review comments --- Lib/http/client.py | 6 +++--- Lib/test/test_httplib.py | 1 - Lib/test/test_logging.py | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Lib/http/client.py b/Lib/http/client.py index 7560dd3d4263eb..9dbc21acf478d4 100644 --- a/Lib/http/client.py +++ b/Lib/http/client.py @@ -269,7 +269,7 @@ def _read_status(self): if len(line) > _MAXLINE: raise LineTooLong("status line") if self.debuglevel > 0: - _log.info("reply: {}".format(repr(line))) + _log.info("reply: %s" % repr(line)) if not line: # Presumably, the server closed the connection before # sending a valid response. @@ -318,7 +318,7 @@ def begin(self): break if self.debuglevel > 0: - _log.info("header: {}".format(skip)) + _log.info("header: %s" % skip) self.code = self.status = status self.reason = reason.strip() @@ -932,7 +932,7 @@ def _tunnel(self): break if self.debuglevel > 0: - _log.info('header: {}'.format(line.decode())) + _log.info('header: %s' % line.decode()) def connect(self): """Connect to the host and port specified in __init__.""" diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py index c4115655832d23..14c60396005965 100644 --- a/Lib/test/test_httplib.py +++ b/Lib/test/test_httplib.py @@ -3,7 +3,6 @@ import io import itertools import os -import sys import logging import array import re diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 0055b6a4fa17ab..8d6dc8bacb67c7 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -1955,7 +1955,7 @@ def handle_request(self, request): def test_output(self): # The log message sent to the HTTPHandler is properly received. - logger = logging.getLogger("httplogger") + logger = logging.getLogger("http") for secure in (False, True): addr = ('localhost', 0) if secure: