| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | """Utilities shared by tests.""" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  | import asyncio | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | import collections | 
					
						
							|  |  |  | import contextlib | 
					
						
							|  |  |  | import io | 
					
						
							| 
									
										
										
										
											2014-07-14 22:26:34 +02:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | import os | 
					
						
							| 
									
										
										
										
											2014-02-18 18:02:19 -05:00
										 |  |  | import re | 
					
						
							| 
									
										
										
										
											2017-11-28 15:19:56 +01:00
										 |  |  | import selectors | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | import socket | 
					
						
							|  |  |  | import socketserver | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | import sys | 
					
						
							|  |  |  | import threading | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  | import unittest | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  | import weakref | 
					
						
							| 
									
										
										
										
											2022-10-16 04:39:30 +05:30
										 |  |  | import warnings | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  | from unittest import mock | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | from http.server import HTTPServer | 
					
						
							| 
									
										
										
										
											2014-02-20 10:37:27 +01:00
										 |  |  | from wsgiref.simple_server import WSGIRequestHandler, WSGIServer | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | try: | 
					
						
							|  |  |  |     import ssl | 
					
						
							|  |  |  | except ImportError:  # pragma: no cover | 
					
						
							|  |  |  |     ssl = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-11 10:04:40 -05:00
										 |  |  | from asyncio import base_events | 
					
						
							|  |  |  | from asyncio import events | 
					
						
							| 
									
										
										
										
											2017-12-15 07:04:38 +02:00
										 |  |  | from asyncio import format_helpers | 
					
						
							| 
									
										
										
										
											2017-12-11 10:04:40 -05:00
										 |  |  | from asyncio import futures | 
					
						
							|  |  |  | from asyncio import tasks | 
					
						
							|  |  |  | from asyncio.log import logger | 
					
						
							| 
									
										
										
										
											2017-06-30 11:12:33 +02:00
										 |  |  | from test import support | 
					
						
							| 
									
										
										
										
											2022-06-17 13:16:51 +02:00
										 |  |  | from test.support import socket_helper | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  | from test.support import threading_helper | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-30 00:35:36 -05:00
										 |  |  | def data_file(filename): | 
					
						
							|  |  |  |     if hasattr(support, 'TEST_HOME_DIR'): | 
					
						
							|  |  |  |         fullname = os.path.join(support.TEST_HOME_DIR, filename) | 
					
						
							|  |  |  |         if os.path.isfile(fullname): | 
					
						
							|  |  |  |             return fullname | 
					
						
							| 
									
										
										
										
											2018-11-30 17:56:56 +01:00
										 |  |  |     fullname = os.path.join(os.path.dirname(__file__), '..', filename) | 
					
						
							| 
									
										
										
										
											2017-12-30 00:35:36 -05:00
										 |  |  |     if os.path.isfile(fullname): | 
					
						
							|  |  |  |         return fullname | 
					
						
							|  |  |  |     raise FileNotFoundError(filename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ONLYCERT = data_file('ssl_cert.pem') | 
					
						
							|  |  |  | ONLYKEY = data_file('ssl_key.pem') | 
					
						
							|  |  |  | SIGNED_CERTFILE = data_file('keycert3.pem') | 
					
						
							|  |  |  | SIGNING_CA = data_file('pycacert.pem') | 
					
						
							| 
									
										
										
										
											2018-01-20 15:16:30 +01:00
										 |  |  | PEERCERT = { | 
					
						
							|  |  |  |     'OCSP': ('http://testca.pythontest.net/testca/ocsp/',), | 
					
						
							|  |  |  |     'caIssuers': ('http://testca.pythontest.net/testca/pycacert.cer',), | 
					
						
							|  |  |  |     'crlDistributionPoints': ('http://testca.pythontest.net/testca/revocation.crl',), | 
					
						
							|  |  |  |     'issuer': ((('countryName', 'XY'),), | 
					
						
							|  |  |  |             (('organizationName', 'Python Software Foundation CA'),), | 
					
						
							|  |  |  |             (('commonName', 'our-ca-server'),)), | 
					
						
							| 
									
										
										
										
											2021-04-17 10:07:19 +02:00
										 |  |  |     'notAfter': 'Oct 28 14:23:16 2037 GMT', | 
					
						
							| 
									
										
										
										
											2018-08-30 07:25:49 +02:00
										 |  |  |     'notBefore': 'Aug 29 14:23:16 2018 GMT', | 
					
						
							|  |  |  |     'serialNumber': 'CB2D80995A69525C', | 
					
						
							| 
									
										
										
										
											2018-01-20 15:16:30 +01:00
										 |  |  |     'subject': ((('countryName', 'XY'),), | 
					
						
							|  |  |  |              (('localityName', 'Castle Anthrax'),), | 
					
						
							|  |  |  |              (('organizationName', 'Python Software Foundation'),), | 
					
						
							|  |  |  |              (('commonName', 'localhost'),)), | 
					
						
							|  |  |  |     'subjectAltName': (('DNS', 'localhost'),), | 
					
						
							|  |  |  |     'version': 3 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-30 00:35:36 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def simple_server_sslcontext(): | 
					
						
							|  |  |  |     server_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | 
					
						
							|  |  |  |     server_context.load_cert_chain(ONLYCERT, ONLYKEY) | 
					
						
							|  |  |  |     server_context.check_hostname = False | 
					
						
							|  |  |  |     server_context.verify_mode = ssl.CERT_NONE | 
					
						
							|  |  |  |     return server_context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-04 11:32:35 -04:00
										 |  |  | def simple_client_sslcontext(*, disable_verify=True): | 
					
						
							| 
									
										
										
										
											2017-12-30 00:35:36 -05:00
										 |  |  |     client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) | 
					
						
							|  |  |  |     client_context.check_hostname = False | 
					
						
							| 
									
										
										
										
											2018-06-04 11:32:35 -04:00
										 |  |  |     if disable_verify: | 
					
						
							|  |  |  |         client_context.verify_mode = ssl.CERT_NONE | 
					
						
							| 
									
										
										
										
											2017-12-30 00:35:36 -05:00
										 |  |  |     return client_context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | def dummy_ssl_context(): | 
					
						
							|  |  |  |     if ssl is None: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2021-04-19 07:27:10 +02:00
										 |  |  |         return simple_client_sslcontext(disable_verify=True) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def run_briefly(loop): | 
					
						
							| 
									
										
										
										
											2017-12-09 00:23:48 +02:00
										 |  |  |     async def once(): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         pass | 
					
						
							|  |  |  |     gen = once() | 
					
						
							| 
									
										
										
										
											2014-07-08 11:29:25 +02:00
										 |  |  |     t = loop.create_task(gen) | 
					
						
							| 
									
										
										
										
											2014-06-30 14:51:04 +02:00
										 |  |  |     # Don't log a warning if the task is not done after run_until_complete(). | 
					
						
							|  |  |  |     # It occurs if the loop is stopped or if a task raises a BaseException. | 
					
						
							|  |  |  |     t._log_destroy_pending = False | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     try: | 
					
						
							|  |  |  |         loop.run_until_complete(t) | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         gen.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 11:30:03 +01:00
										 |  |  | def run_until(loop, pred, timeout=support.SHORT_TIMEOUT): | 
					
						
							| 
									
										
										
										
											2022-06-15 18:28:00 +02:00
										 |  |  |     delay = 0.001 | 
					
						
							| 
									
										
										
										
											2022-06-15 14:09:56 +02:00
										 |  |  |     for _ in support.busy_retry(timeout, error=False): | 
					
						
							|  |  |  |         if pred(): | 
					
						
							|  |  |  |             break | 
					
						
							| 
									
										
										
										
											2022-06-15 18:28:00 +02:00
										 |  |  |         loop.run_until_complete(tasks.sleep(delay)) | 
					
						
							|  |  |  |         delay = max(delay * 2, 1.0) | 
					
						
							| 
									
										
										
										
											2022-06-15 14:09:56 +02:00
										 |  |  |     else: | 
					
						
							|  |  |  |         raise futures.TimeoutError() | 
					
						
							| 
									
										
										
										
											2013-10-20 01:51:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | def run_once(loop): | 
					
						
							| 
									
										
										
										
											2015-11-19 13:28:47 -08:00
										 |  |  |     """Legacy API to run once through the event loop.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This is the recommended pattern for test code.  It will poll the | 
					
						
							|  |  |  |     selector once and run all callbacks scheduled in response to I/O | 
					
						
							|  |  |  |     events. | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:28:47 -08:00
										 |  |  |     loop.call_soon(loop.stop) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     loop.run_forever() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | class SilentWSGIRequestHandler(WSGIRequestHandler): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |     def get_stderr(self): | 
					
						
							|  |  |  |         return io.StringIO() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |     def log_message(self, format, *args): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | class SilentWSGIServer(WSGIServer): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 20:32:59 +01:00
										 |  |  |     request_timeout = support.LOOPBACK_TIMEOUT | 
					
						
							| 
									
										
										
										
											2014-10-15 16:58:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_request(self): | 
					
						
							|  |  |  |         request, client_addr = super().get_request() | 
					
						
							|  |  |  |         request.settimeout(self.request_timeout) | 
					
						
							|  |  |  |         return request, client_addr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |     def handle_error(self, request, client_address): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class SSLWSGIServerMixin: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def finish_request(self, request, client_address): | 
					
						
							|  |  |  |         # The relative location of our test directory (which | 
					
						
							|  |  |  |         # contains the ssl key and certificate files) differs | 
					
						
							|  |  |  |         # between the stdlib and stand-alone asyncio. | 
					
						
							|  |  |  |         # Prefer our own if we can find it. | 
					
						
							| 
									
										
										
										
											2021-04-19 07:27:10 +02:00
										 |  |  |         context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) | 
					
						
							| 
									
										
										
										
											2018-11-30 18:30:09 +01:00
										 |  |  |         context.load_cert_chain(ONLYCERT, ONLYKEY) | 
					
						
							| 
									
										
										
										
											2016-09-10 23:23:33 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ssock = context.wrap_socket(request, server_side=True) | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |         try: | 
					
						
							|  |  |  |             self.RequestHandlerClass(ssock, client_address, self) | 
					
						
							|  |  |  |             ssock.close() | 
					
						
							|  |  |  |         except OSError: | 
					
						
							|  |  |  |             # maybe socket has been closed by peer | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | class SSLWSGIServer(SSLWSGIServerMixin, SilentWSGIServer): | 
					
						
							|  |  |  |     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _run_test_server(*, address, use_ssl=False, server_cls, server_ssl_cls): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-12 19:00:22 +02:00
										 |  |  |     def loop(environ): | 
					
						
							|  |  |  |         size = int(environ['CONTENT_LENGTH']) | 
					
						
							|  |  |  |         while size: | 
					
						
							|  |  |  |             data = environ['wsgi.input'].read(min(size, 0x10000)) | 
					
						
							|  |  |  |             yield data | 
					
						
							|  |  |  |             size -= len(data) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def app(environ, start_response): | 
					
						
							|  |  |  |         status = '200 OK' | 
					
						
							|  |  |  |         headers = [('Content-type', 'text/plain')] | 
					
						
							|  |  |  |         start_response(status, headers) | 
					
						
							| 
									
										
										
										
											2018-11-12 19:00:22 +02:00
										 |  |  |         if environ['PATH_INFO'] == '/loop': | 
					
						
							|  |  |  |             return loop(environ) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return [b'Test message'] | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Run the test WSGI server in a separate thread in order not to | 
					
						
							|  |  |  |     # interfere with event handling in the main thread | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |     server_class = server_ssl_cls if use_ssl else server_cls | 
					
						
							|  |  |  |     httpd = server_class(address, SilentWSGIRequestHandler) | 
					
						
							|  |  |  |     httpd.set_app(app) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     httpd.address = httpd.server_address | 
					
						
							| 
									
										
										
										
											2014-10-15 16:58:21 +02:00
										 |  |  |     server_thread = threading.Thread( | 
					
						
							|  |  |  |         target=lambda: httpd.serve_forever(poll_interval=0.05)) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     server_thread.start() | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         yield httpd | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         httpd.shutdown() | 
					
						
							| 
									
										
										
										
											2013-10-20 23:26:23 +02:00
										 |  |  |         httpd.server_close() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         server_thread.join() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | if hasattr(socket, 'AF_UNIX'): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class UnixHTTPServer(socketserver.UnixStreamServer, HTTPServer): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def server_bind(self): | 
					
						
							|  |  |  |             socketserver.UnixStreamServer.server_bind(self) | 
					
						
							|  |  |  |             self.server_name = '127.0.0.1' | 
					
						
							|  |  |  |             self.server_port = 80 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class UnixWSGIServer(UnixHTTPServer, WSGIServer): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-10 20:32:59 +01:00
										 |  |  |         request_timeout = support.LOOPBACK_TIMEOUT | 
					
						
							| 
									
										
										
										
											2014-10-15 16:58:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |         def server_bind(self): | 
					
						
							|  |  |  |             UnixHTTPServer.server_bind(self) | 
					
						
							|  |  |  |             self.setup_environ() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def get_request(self): | 
					
						
							|  |  |  |             request, client_addr = super().get_request() | 
					
						
							| 
									
										
										
										
											2014-10-15 16:58:21 +02:00
										 |  |  |             request.settimeout(self.request_timeout) | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  |             # Code in the stdlib expects that get_request | 
					
						
							|  |  |  |             # will return a socket and a tuple (host, port). | 
					
						
							|  |  |  |             # However, this isn't true for UNIX sockets, | 
					
						
							|  |  |  |             # as the second return value will be a path; | 
					
						
							|  |  |  |             # hence we return some fake data sufficient | 
					
						
							|  |  |  |             # to get the tests going | 
					
						
							|  |  |  |             return request, ('127.0.0.1', '') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class SilentUnixWSGIServer(UnixWSGIServer): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def handle_error(self, request, client_address): | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     class UnixSSLWSGIServer(SSLWSGIServerMixin, SilentUnixWSGIServer): | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def gen_unix_socket_path(): | 
					
						
							| 
									
										
										
										
											2022-06-17 13:16:51 +02:00
										 |  |  |         return socket_helper.create_unix_domain_name() | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @contextlib.contextmanager | 
					
						
							|  |  |  |     def unix_socket_path(): | 
					
						
							|  |  |  |         path = gen_unix_socket_path() | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             yield path | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 os.unlink(path) | 
					
						
							|  |  |  |             except OSError: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @contextlib.contextmanager | 
					
						
							|  |  |  |     def run_test_unix_server(*, use_ssl=False): | 
					
						
							|  |  |  |         with unix_socket_path() as path: | 
					
						
							|  |  |  |             yield from _run_test_server(address=path, use_ssl=use_ssl, | 
					
						
							|  |  |  |                                         server_cls=SilentUnixWSGIServer, | 
					
						
							|  |  |  |                                         server_ssl_cls=UnixSSLWSGIServer) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def run_test_server(*, host='127.0.0.1', port=0, use_ssl=False): | 
					
						
							|  |  |  |     yield from _run_test_server(address=(host, port), use_ssl=use_ssl, | 
					
						
							|  |  |  |                                 server_cls=SilentWSGIServer, | 
					
						
							|  |  |  |                                 server_ssl_cls=SSLWSGIServer) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-13 18:42:29 +02:00
										 |  |  | def echo_datagrams(sock): | 
					
						
							|  |  |  |     while True: | 
					
						
							|  |  |  |         data, addr = sock.recvfrom(4096) | 
					
						
							|  |  |  |         if data == b'STOP': | 
					
						
							|  |  |  |             sock.close() | 
					
						
							|  |  |  |             break | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             sock.sendto(data, addr) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def run_udp_echo_server(*, host='127.0.0.1', port=0): | 
					
						
							|  |  |  |     addr_info = socket.getaddrinfo(host, port, type=socket.SOCK_DGRAM) | 
					
						
							|  |  |  |     family, type, proto, _, sockaddr = addr_info[0] | 
					
						
							|  |  |  |     sock = socket.socket(family, type, proto) | 
					
						
							|  |  |  |     sock.bind((host, port)) | 
					
						
							|  |  |  |     thread = threading.Thread(target=lambda: echo_datagrams(sock)) | 
					
						
							|  |  |  |     thread.start() | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         yield sock.getsockname() | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         sock.sendto(b'STOP', sock.getsockname()) | 
					
						
							|  |  |  |         thread.join() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | def make_test_protocol(base): | 
					
						
							|  |  |  |     dct = {} | 
					
						
							|  |  |  |     for name in dir(base): | 
					
						
							|  |  |  |         if name.startswith('__') and name.endswith('__'): | 
					
						
							|  |  |  |             # skip magic names | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2014-02-11 11:34:30 +01:00
										 |  |  |         dct[name] = MockCallback(return_value=None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     return type('TestProtocol', (base,) + base.__bases__, dct)() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestSelector(selectors.BaseSelector): | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-01 11:04:17 +01:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.keys = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def register(self, fileobj, events, data=None): | 
					
						
							|  |  |  |         key = selectors.SelectorKey(fileobj, 0, events, data) | 
					
						
							|  |  |  |         self.keys[fileobj] = key | 
					
						
							|  |  |  |         return key | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def unregister(self, fileobj): | 
					
						
							|  |  |  |         return self.keys.pop(fileobj) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def select(self, timeout): | 
					
						
							|  |  |  |         return [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-01 11:04:17 +01:00
										 |  |  |     def get_map(self): | 
					
						
							|  |  |  |         return self.keys | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TestLoop(base_events.BaseEventLoop): | 
					
						
							|  |  |  |     """Loop for unittests.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     It manages self time directly. | 
					
						
							|  |  |  |     If something scheduled to be executed later then | 
					
						
							|  |  |  |     on next loop iteration after all ready handlers done | 
					
						
							|  |  |  |     generator passed to __init__ is calling. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Generator should be like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def gen(): | 
					
						
							|  |  |  |             ... | 
					
						
							|  |  |  |             when = yield ... | 
					
						
							|  |  |  |             ... = yield time_advance | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 22:27:48 -05:00
										 |  |  |     Value returned by yield is absolute time of next scheduled handler. | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     Value passed to yield is time advance to move loop's time forward. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, gen=None): | 
					
						
							|  |  |  |         super().__init__() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if gen is None: | 
					
						
							|  |  |  |             def gen(): | 
					
						
							|  |  |  |                 yield | 
					
						
							|  |  |  |             self._check_on_close = False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             self._check_on_close = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self._gen = gen() | 
					
						
							|  |  |  |         next(self._gen) | 
					
						
							|  |  |  |         self._time = 0 | 
					
						
							| 
									
										
										
										
											2014-02-11 09:03:47 +01:00
										 |  |  |         self._clock_resolution = 1e-9 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self._timers = [] | 
					
						
							|  |  |  |         self._selector = TestSelector() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.readers = {} | 
					
						
							|  |  |  |         self.writers = {} | 
					
						
							|  |  |  |         self.reset_counters() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |         self._transports = weakref.WeakValueDictionary() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def time(self): | 
					
						
							|  |  |  |         return self._time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def advance_time(self, advance): | 
					
						
							|  |  |  |         """Move test time forward.""" | 
					
						
							|  |  |  |         if advance: | 
					
						
							|  |  |  |             self._time += advance | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def close(self): | 
					
						
							| 
									
										
										
										
											2015-01-15 00:04:21 +01:00
										 |  |  |         super().close() | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         if self._check_on_close: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 self._gen.send(0) | 
					
						
							|  |  |  |             except StopIteration: | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else:  # pragma: no cover | 
					
						
							|  |  |  |                 raise AssertionError("Time generator is not finished") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |     def _add_reader(self, fd, callback, *args): | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |         self.readers[fd] = events.Handle(callback, args, self, None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |     def _remove_reader(self, fd): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.remove_reader_count[fd] += 1 | 
					
						
							|  |  |  |         if fd in self.readers: | 
					
						
							|  |  |  |             del self.readers[fd] | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_reader(self, fd, callback, *args): | 
					
						
							| 
									
										
										
										
											2017-12-18 17:03:23 -05:00
										 |  |  |         if fd not in self.readers: | 
					
						
							|  |  |  |             raise AssertionError(f'fd {fd} is not registered') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         handle = self.readers[fd] | 
					
						
							| 
									
										
										
										
											2017-12-18 17:03:23 -05:00
										 |  |  |         if handle._callback != callback: | 
					
						
							|  |  |  |             raise AssertionError( | 
					
						
							|  |  |  |                 f'unexpected callback: {handle._callback} != {callback}') | 
					
						
							|  |  |  |         if handle._args != args: | 
					
						
							|  |  |  |             raise AssertionError( | 
					
						
							|  |  |  |                 f'unexpected callback args: {handle._args} != {args}') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_no_reader(self, fd): | 
					
						
							|  |  |  |         if fd in self.readers: | 
					
						
							|  |  |  |             raise AssertionError(f'fd {fd} is registered') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |     def _add_writer(self, fd, callback, *args): | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |         self.writers[fd] = events.Handle(callback, args, self, None) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |     def _remove_writer(self, fd): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self.remove_writer_count[fd] += 1 | 
					
						
							|  |  |  |         if fd in self.writers: | 
					
						
							|  |  |  |             del self.writers[fd] | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def assert_writer(self, fd, callback, *args): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         if fd not in self.writers: | 
					
						
							|  |  |  |             raise AssertionError(f'fd {fd} is not registered') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         handle = self.writers[fd] | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         if handle._callback != callback: | 
					
						
							|  |  |  |             raise AssertionError(f'{handle._callback!r} != {callback!r}') | 
					
						
							|  |  |  |         if handle._args != args: | 
					
						
							|  |  |  |             raise AssertionError(f'{handle._args!r} != {args!r}') | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |     def _ensure_fd_no_transport(self, fd): | 
					
						
							| 
									
										
										
										
											2017-11-13 13:38:22 -05:00
										 |  |  |         if not isinstance(fd, int): | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 fd = int(fd.fileno()) | 
					
						
							|  |  |  |             except (AttributeError, TypeError, ValueError): | 
					
						
							|  |  |  |                 # This code matches selectors._fileobj_to_fd function. | 
					
						
							|  |  |  |                 raise ValueError("Invalid file object: " | 
					
						
							|  |  |  |                                  "{!r}".format(fd)) from None | 
					
						
							| 
									
										
										
										
											2016-10-05 17:48:59 -04:00
										 |  |  |         try: | 
					
						
							|  |  |  |             transport = self._transports[fd] | 
					
						
							|  |  |  |         except KeyError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             raise RuntimeError( | 
					
						
							|  |  |  |                 'File descriptor {!r} is used by transport {!r}'.format( | 
					
						
							|  |  |  |                     fd, transport)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_reader(self, fd, callback, *args): | 
					
						
							|  |  |  |         """Add a reader callback.""" | 
					
						
							|  |  |  |         self._ensure_fd_no_transport(fd) | 
					
						
							|  |  |  |         return self._add_reader(fd, callback, *args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def remove_reader(self, fd): | 
					
						
							|  |  |  |         """Remove a reader callback.""" | 
					
						
							|  |  |  |         self._ensure_fd_no_transport(fd) | 
					
						
							|  |  |  |         return self._remove_reader(fd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def add_writer(self, fd, callback, *args): | 
					
						
							|  |  |  |         """Add a writer callback..""" | 
					
						
							|  |  |  |         self._ensure_fd_no_transport(fd) | 
					
						
							|  |  |  |         return self._add_writer(fd, callback, *args) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def remove_writer(self, fd): | 
					
						
							|  |  |  |         """Remove a writer callback.""" | 
					
						
							|  |  |  |         self._ensure_fd_no_transport(fd) | 
					
						
							|  |  |  |         return self._remove_writer(fd) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |     def reset_counters(self): | 
					
						
							|  |  |  |         self.remove_reader_count = collections.defaultdict(int) | 
					
						
							|  |  |  |         self.remove_writer_count = collections.defaultdict(int) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _run_once(self): | 
					
						
							|  |  |  |         super()._run_once() | 
					
						
							|  |  |  |         for when in self._timers: | 
					
						
							|  |  |  |             advance = self._gen.send(when) | 
					
						
							|  |  |  |             self.advance_time(advance) | 
					
						
							|  |  |  |         self._timers = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |     def call_at(self, when, callback, *args, context=None): | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  |         self._timers.append(when) | 
					
						
							| 
									
										
										
										
											2018-01-22 19:11:18 -05:00
										 |  |  |         return super().call_at(when, callback, *args, context=context) | 
					
						
							| 
									
										
										
										
											2013-10-17 13:40:50 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def _process_events(self, event_list): | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def _write_to_self(self): | 
					
						
							|  |  |  |         pass | 
					
						
							| 
									
										
										
										
											2014-02-11 11:34:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:15:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-11 11:34:30 +01:00
										 |  |  | def MockCallback(**kwargs): | 
					
						
							| 
									
										
										
										
											2014-02-26 10:25:02 +01:00
										 |  |  |     return mock.Mock(spec=['__call__'], **kwargs) | 
					
						
							| 
									
										
										
										
											2014-02-18 18:02:19 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MockPattern(str): | 
					
						
							|  |  |  |     """A regex based str with a fuzzy __eq__.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Use this helper with 'mock.assert_called_with', or anywhere | 
					
						
							| 
									
										
										
										
											2014-02-18 22:27:48 -05:00
										 |  |  |     where a regex comparison between strings is needed. | 
					
						
							| 
									
										
										
										
											2014-02-18 18:02:19 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     For instance: | 
					
						
							|  |  |  |        mock_call.assert_called_with(MockPattern('spam.*ham')) | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         return bool(re.search(str(self), other, re.S)) | 
					
						
							| 
									
										
										
										
											2014-06-12 18:39:26 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-21 14:56:59 -05:00
										 |  |  | class MockInstanceOf: | 
					
						
							|  |  |  |     def __init__(self, type): | 
					
						
							|  |  |  |         self._type = type | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __eq__(self, other): | 
					
						
							|  |  |  |         return isinstance(other, self._type) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-12 18:39:26 +02:00
										 |  |  | def get_function_source(func): | 
					
						
							| 
									
										
										
										
											2017-12-15 07:04:38 +02:00
										 |  |  |     source = format_helpers._get_function_source(func) | 
					
						
							| 
									
										
										
										
											2014-06-12 18:39:26 +02:00
										 |  |  |     if source is None: | 
					
						
							|  |  |  |         raise ValueError("unable to get the source of %r" % (func,)) | 
					
						
							|  |  |  |     return source | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class TestCase(unittest.TestCase): | 
					
						
							| 
									
										
										
										
											2017-09-01 14:46:06 +02:00
										 |  |  |     @staticmethod | 
					
						
							|  |  |  |     def close_loop(loop): | 
					
						
							| 
									
										
										
										
											2019-09-19 16:45:06 +02:00
										 |  |  |         if loop._default_executor is not None: | 
					
						
							|  |  |  |             if not loop.is_closed(): | 
					
						
							|  |  |  |                 loop.run_until_complete(loop.shutdown_default_executor()) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 loop._default_executor.shutdown(wait=True) | 
					
						
							| 
									
										
										
										
											2017-09-01 14:46:06 +02:00
										 |  |  |         loop.close() | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  |         policy = support.maybe_get_event_loop_policy() | 
					
						
							|  |  |  |         if policy is not None: | 
					
						
							|  |  |  |             try: | 
					
						
							| 
									
										
										
										
											2022-10-16 04:39:30 +05:30
										 |  |  |                 with warnings.catch_warnings(): | 
					
						
							|  |  |  |                     warnings.simplefilter('ignore', DeprecationWarning) | 
					
						
							|  |  |  |                     watcher = policy.get_child_watcher() | 
					
						
							| 
									
										
										
										
											2019-06-30 12:54:59 +03:00
										 |  |  |             except NotImplementedError: | 
					
						
							|  |  |  |                 # watcher is not implemented by EventLoopPolicy, e.g. Windows | 
					
						
							|  |  |  |                 pass | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 if isinstance(watcher, asyncio.ThreadedChildWatcher): | 
					
						
							|  |  |  |                     threads = list(watcher._threads.values()) | 
					
						
							|  |  |  |                     for thread in threads: | 
					
						
							|  |  |  |                         thread.join() | 
					
						
							| 
									
										
										
										
											2017-09-01 14:46:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |     def set_event_loop(self, loop, *, cleanup=True): | 
					
						
							| 
									
										
										
										
											2021-12-20 12:23:05 +02:00
										 |  |  |         if loop is None: | 
					
						
							|  |  |  |             raise AssertionError('loop is None') | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |         # ensure that the event loop is passed explicitly in asyncio | 
					
						
							|  |  |  |         events.set_event_loop(None) | 
					
						
							|  |  |  |         if cleanup: | 
					
						
							| 
									
										
										
										
											2017-09-01 14:46:06 +02:00
										 |  |  |             self.addCleanup(self.close_loop, loop) | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def new_test_loop(self, gen=None): | 
					
						
							|  |  |  |         loop = TestLoop(gen) | 
					
						
							|  |  |  |         self.set_event_loop(loop) | 
					
						
							|  |  |  |         return loop | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  |     def setUp(self): | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |         self._thread_cleanup = threading_helper.threading_setup() | 
					
						
							| 
									
										
										
										
											2016-11-04 14:29:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-18 01:36:32 +02:00
										 |  |  |     def tearDown(self): | 
					
						
							|  |  |  |         events.set_event_loop(None) | 
					
						
							| 
									
										
										
										
											2014-07-14 22:26:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-02 18:36:31 +01:00
										 |  |  |         # Detect CPython bug #23353: ensure that yield/yield-from is not used | 
					
						
							|  |  |  |         # in an except block of a generator | 
					
						
							| 
									
										
										
										
											2023-04-06 11:08:25 +01:00
										 |  |  |         self.assertIsNone(sys.exception()) | 
					
						
							| 
									
										
										
										
											2015-02-02 18:36:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-30 11:12:33 +02:00
										 |  |  |         self.doCleanups() | 
					
						
							| 
									
										
										
										
											2020-05-28 06:10:27 +08:00
										 |  |  |         threading_helper.threading_cleanup(*self._thread_cleanup) | 
					
						
							| 
									
										
										
										
											2017-06-30 11:12:33 +02:00
										 |  |  |         support.reap_children() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-14 22:26:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | @contextlib.contextmanager | 
					
						
							|  |  |  | def disable_logger(): | 
					
						
							|  |  |  |     """Context manager to disable asyncio logger.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     For example, it can be used to ignore warnings in debug mode. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     old_level = logger.level | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         logger.setLevel(logging.CRITICAL+1) | 
					
						
							|  |  |  |         yield | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         logger.setLevel(old_level) | 
					
						
							| 
									
										
										
										
											2014-08-25 23:20:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-16 19:31:17 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | def mock_nonblocking_socket(proto=socket.IPPROTO_TCP, type=socket.SOCK_STREAM, | 
					
						
							|  |  |  |                             family=socket.AF_INET): | 
					
						
							| 
									
										
										
										
											2014-08-25 23:20:52 +02:00
										 |  |  |     """Create a mock of a non-blocking socket.""" | 
					
						
							| 
									
										
										
										
											2015-12-16 19:31:17 -05:00
										 |  |  |     sock = mock.MagicMock(socket.socket) | 
					
						
							|  |  |  |     sock.proto = proto | 
					
						
							|  |  |  |     sock.type = type | 
					
						
							|  |  |  |     sock.family = family | 
					
						
							| 
									
										
										
										
											2014-08-25 23:20:52 +02:00
										 |  |  |     sock.gettimeout.return_value = 0.0 | 
					
						
							|  |  |  |     return sock |