Compare commits
	
		
			No commits in common. "master" and "v2.1.0" have entirely different histories.
		
	
	
		
							
								
								
									
										19
									
								
								.travis.yml
								
								
								
								
							
							
						
						
									
										19
									
								
								.travis.yml
								
								
								
								
							|  | @ -1,14 +1,12 @@ | ||||||
| language: python | language: python | ||||||
| sudo: required |  | ||||||
| dist: xenial |  | ||||||
| 
 | 
 | ||||||
| addons: | addons: | ||||||
|   apt: |   apt: | ||||||
|     sources: |     sources: | ||||||
|       - deadsnakes |       - deadsnakes | ||||||
|     packages: |     packages: | ||||||
|       - python2.4 |       # - python2.4 | ||||||
|       - python2.5 |       # - python2.5 | ||||||
|       - python2.6 |       - python2.6 | ||||||
|       - python3.2 |       - python3.2 | ||||||
|       - python3.3 |       - python3.3 | ||||||
|  | @ -17,10 +15,10 @@ matrix: | ||||||
|   include: |   include: | ||||||
|     - python: 2.7 |     - python: 2.7 | ||||||
|       env: TOXENV=flake8 |       env: TOXENV=flake8 | ||||||
|     - python: 2.7 |     # - python: 2.7 | ||||||
|       env: TOXENV=py24 |     #   env: TOXENV=py24 | ||||||
|     - python: 2.7 |     # - python: 2.7 | ||||||
|       env: TOXENV=py25 |     #   env: TOXENV=py25 | ||||||
|     - python: 2.7 |     - python: 2.7 | ||||||
|       env: TOXENV=py26 |       env: TOXENV=py26 | ||||||
|     - python: 2.7 |     - python: 2.7 | ||||||
|  | @ -35,13 +33,8 @@ matrix: | ||||||
|       env: TOXENV=py35 |       env: TOXENV=py35 | ||||||
|     - python: 3.6 |     - python: 3.6 | ||||||
|       env: TOXENV=py36 |       env: TOXENV=py36 | ||||||
|     - python: 3.7 |  | ||||||
|       env: TOXENV=py37 |  | ||||||
|     - python: 3.8-dev |  | ||||||
|       env: TOXENV=py38 |  | ||||||
|     - python: pypy |     - python: pypy | ||||||
|       env: TOXENV=pypy |       env: TOXENV=pypy | ||||||
|       dist: trusty |  | ||||||
| 
 | 
 | ||||||
| before_install: | before_install: | ||||||
|   - if [[ $(echo "$TOXENV" | egrep -c "py35") != 0 ]]; then pyenv global system 3.5; fi; |   - if [[ $(echo "$TOXENV" | egrep -c "py35") != 0 ]]; then pyenv global system 3.5; fi; | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										3
									
								
								setup.py
								
								
								
								
							|  | @ -92,8 +92,5 @@ setup( | ||||||
|         'Programming Language :: Python :: 3.5', |         'Programming Language :: Python :: 3.5', | ||||||
|         'Programming Language :: Python :: 3.6', |         'Programming Language :: Python :: 3.6', | ||||||
|         'Programming Language :: Python :: 3.7', |         'Programming Language :: Python :: 3.7', | ||||||
|         'Programming Language :: Python :: 3.8', |  | ||||||
|         'Programming Language :: Python :: 3.9', |  | ||||||
|         'Programming Language :: Python :: 3.10', |  | ||||||
|     ] |     ] | ||||||
| ) | ) | ||||||
|  |  | ||||||
							
								
								
									
										168
									
								
								speedtest.py
								
								
								
								
							
							
						
						
									
										168
									
								
								speedtest.py
								
								
								
								
							|  | @ -15,18 +15,18 @@ | ||||||
| #    License for the specific language governing permissions and limitations | #    License for the specific language governing permissions and limitations | ||||||
| #    under the License. | #    under the License. | ||||||
| 
 | 
 | ||||||
| import csv |  | ||||||
| import datetime |  | ||||||
| import errno |  | ||||||
| import math |  | ||||||
| import os | import os | ||||||
| import platform |  | ||||||
| import re | import re | ||||||
|  | import csv | ||||||
|  | import sys | ||||||
|  | import math | ||||||
|  | import errno | ||||||
| import signal | import signal | ||||||
| import socket | import socket | ||||||
| import sys |  | ||||||
| import threading |  | ||||||
| import timeit | import timeit | ||||||
|  | import datetime | ||||||
|  | import platform | ||||||
|  | import threading | ||||||
| import xml.parsers.expat | import xml.parsers.expat | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|  | @ -36,7 +36,7 @@ except ImportError: | ||||||
|     gzip = None |     gzip = None | ||||||
|     GZIP_BASE = object |     GZIP_BASE = object | ||||||
| 
 | 
 | ||||||
| __version__ = '2.1.4b1' | __version__ = '2.1.0' | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class FakeShutdownEvent(object): | class FakeShutdownEvent(object): | ||||||
|  | @ -49,16 +49,10 @@ class FakeShutdownEvent(object): | ||||||
|         "Dummy method to always return false""" |         "Dummy method to always return false""" | ||||||
|         return False |         return False | ||||||
| 
 | 
 | ||||||
|     is_set = isSet |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| # Some global variables we use | # Some global variables we use | ||||||
| DEBUG = False | DEBUG = False | ||||||
| _GLOBAL_DEFAULT_TIMEOUT = object() | _GLOBAL_DEFAULT_TIMEOUT = object() | ||||||
| PY25PLUS = sys.version_info[:2] >= (2, 5) |  | ||||||
| PY26PLUS = sys.version_info[:2] >= (2, 6) |  | ||||||
| PY32PLUS = sys.version_info[:2] >= (3, 2) |  | ||||||
| PY310PLUS = sys.version_info[:2] >= (3, 10) |  | ||||||
| 
 | 
 | ||||||
| # Begin import game to handle Python 2 and Python 3 | # Begin import game to handle Python 2 and Python 3 | ||||||
| try: | try: | ||||||
|  | @ -70,15 +64,14 @@ except ImportError: | ||||||
|         json = None |         json = None | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|     import xml.etree.ElementTree as ET |     import xml.etree.cElementTree as ET | ||||||
|     try: |  | ||||||
|         from xml.etree.ElementTree import _Element as ET_Element |  | ||||||
|     except ImportError: |  | ||||||
|         pass |  | ||||||
| except ImportError: | except ImportError: | ||||||
|     from xml.dom import minidom as DOM |     try: | ||||||
|     from xml.parsers.expat import ExpatError |         import xml.etree.ElementTree as ET | ||||||
|     ET = None |     except ImportError: | ||||||
|  |         from xml.dom import minidom as DOM | ||||||
|  |         from xml.parsers.expat import ExpatError | ||||||
|  |         ET = None | ||||||
| 
 | 
 | ||||||
| try: | try: | ||||||
|     from urllib2 import (urlopen, Request, HTTPError, URLError, |     from urllib2 import (urlopen, Request, HTTPError, URLError, | ||||||
|  | @ -104,11 +97,6 @@ except ImportError: | ||||||
|     except ImportError: |     except ImportError: | ||||||
|         HTTPSConnection = None |         HTTPSConnection = None | ||||||
| 
 | 
 | ||||||
| try: |  | ||||||
|     from httplib import FakeSocket |  | ||||||
| except ImportError: |  | ||||||
|     FakeSocket = None |  | ||||||
| 
 |  | ||||||
| try: | try: | ||||||
|     from Queue import Queue |     from Queue import Queue | ||||||
| except ImportError: | except ImportError: | ||||||
|  | @ -269,6 +257,7 @@ else: | ||||||
|             write(arg) |             write(arg) | ||||||
|         write(end) |         write(end) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| # Exception "constants" to support Python 2 through Python 3 | # Exception "constants" to support Python 2 through Python 3 | ||||||
| try: | try: | ||||||
|     import ssl |     import ssl | ||||||
|  | @ -285,23 +274,6 @@ except ImportError: | ||||||
|     ssl = None |     ssl = None | ||||||
|     HTTP_ERRORS = (HTTPError, URLError, socket.error, BadStatusLine) |     HTTP_ERRORS = (HTTPError, URLError, socket.error, BadStatusLine) | ||||||
| 
 | 
 | ||||||
| if PY32PLUS: |  | ||||||
|     etree_iter = ET.Element.iter |  | ||||||
| elif PY25PLUS: |  | ||||||
|     etree_iter = ET_Element.getiterator |  | ||||||
| 
 |  | ||||||
| if PY26PLUS: |  | ||||||
|     thread_is_alive = threading.Thread.is_alive |  | ||||||
| else: |  | ||||||
|     thread_is_alive = threading.Thread.isAlive |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def event_is_set(event): |  | ||||||
|     try: |  | ||||||
|         return event.is_set() |  | ||||||
|     except AttributeError: |  | ||||||
|         return event.isSet() |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| class SpeedtestException(Exception): | class SpeedtestException(Exception): | ||||||
|     """Base exception for this module""" |     """Base exception for this module""" | ||||||
|  | @ -422,8 +394,6 @@ class SpeedtestHTTPConnection(HTTPConnection): | ||||||
|         source_address = kwargs.pop('source_address', None) |         source_address = kwargs.pop('source_address', None) | ||||||
|         timeout = kwargs.pop('timeout', 10) |         timeout = kwargs.pop('timeout', 10) | ||||||
| 
 | 
 | ||||||
|         self._tunnel_host = None |  | ||||||
| 
 |  | ||||||
|         HTTPConnection.__init__(self, *args, **kwargs) |         HTTPConnection.__init__(self, *args, **kwargs) | ||||||
| 
 | 
 | ||||||
|         self.source_address = source_address |         self.source_address = source_address | ||||||
|  | @ -444,23 +414,17 @@ class SpeedtestHTTPConnection(HTTPConnection): | ||||||
|                 self.source_address |                 self.source_address | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         if self._tunnel_host: |  | ||||||
|             self._tunnel() |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| if HTTPSConnection: | if HTTPSConnection: | ||||||
|     class SpeedtestHTTPSConnection(HTTPSConnection): |     class SpeedtestHTTPSConnection(HTTPSConnection, | ||||||
|  |                                    SpeedtestHTTPConnection): | ||||||
|         """Custom HTTPSConnection to support source_address across |         """Custom HTTPSConnection to support source_address across | ||||||
|         Python 2.4 - Python 3 |         Python 2.4 - Python 3 | ||||||
|         """ |         """ | ||||||
|         default_port = 443 |  | ||||||
| 
 |  | ||||||
|         def __init__(self, *args, **kwargs): |         def __init__(self, *args, **kwargs): | ||||||
|             source_address = kwargs.pop('source_address', None) |             source_address = kwargs.pop('source_address', None) | ||||||
|             timeout = kwargs.pop('timeout', 10) |             timeout = kwargs.pop('timeout', 10) | ||||||
| 
 | 
 | ||||||
|             self._tunnel_host = None |  | ||||||
| 
 |  | ||||||
|             HTTPSConnection.__init__(self, *args, **kwargs) |             HTTPSConnection.__init__(self, *args, **kwargs) | ||||||
| 
 | 
 | ||||||
|             self.timeout = timeout |             self.timeout = timeout | ||||||
|  | @ -468,30 +432,14 @@ if HTTPSConnection: | ||||||
| 
 | 
 | ||||||
|         def connect(self): |         def connect(self): | ||||||
|             "Connect to a host on a given (SSL) port." |             "Connect to a host on a given (SSL) port." | ||||||
|             try: |  | ||||||
|                 self.sock = socket.create_connection( |  | ||||||
|                     (self.host, self.port), |  | ||||||
|                     self.timeout, |  | ||||||
|                     self.source_address |  | ||||||
|                 ) |  | ||||||
|             except (AttributeError, TypeError): |  | ||||||
|                 self.sock = create_connection( |  | ||||||
|                     (self.host, self.port), |  | ||||||
|                     self.timeout, |  | ||||||
|                     self.source_address |  | ||||||
|                 ) |  | ||||||
| 
 | 
 | ||||||
|             if self._tunnel_host: |             SpeedtestHTTPConnection.connect(self) | ||||||
|                 self._tunnel() |  | ||||||
| 
 | 
 | ||||||
|             if ssl: |             if ssl: | ||||||
|                 try: |                 try: | ||||||
|                     kwargs = {} |                     kwargs = {} | ||||||
|                     if hasattr(ssl, 'SSLContext'): |                     if hasattr(ssl, 'SSLContext'): | ||||||
|                         if self._tunnel_host: |                         kwargs['server_hostname'] = self.host | ||||||
|                             kwargs['server_hostname'] = self._tunnel_host |  | ||||||
|                         else: |  | ||||||
|                             kwargs['server_hostname'] = self.host |  | ||||||
|                     self.sock = self._context.wrap_socket(self.sock, **kwargs) |                     self.sock = self._context.wrap_socket(self.sock, **kwargs) | ||||||
|                 except AttributeError: |                 except AttributeError: | ||||||
|                     self.sock = ssl.wrap_socket(self.sock) |                     self.sock = ssl.wrap_socket(self.sock) | ||||||
|  | @ -499,20 +447,6 @@ if HTTPSConnection: | ||||||
|                         self.sock.server_hostname = self.host |                         self.sock.server_hostname = self.host | ||||||
|                     except AttributeError: |                     except AttributeError: | ||||||
|                         pass |                         pass | ||||||
|             elif FakeSocket: |  | ||||||
|                 # Python 2.4/2.5 support |  | ||||||
|                 try: |  | ||||||
|                     self.sock = FakeSocket(self.sock, socket.ssl(self.sock)) |  | ||||||
|                 except AttributeError: |  | ||||||
|                     raise SpeedtestException( |  | ||||||
|                         'This version of Python does not support HTTPS/SSL ' |  | ||||||
|                         'functionality' |  | ||||||
|                     ) |  | ||||||
|             else: |  | ||||||
|                 raise SpeedtestException( |  | ||||||
|                     'This version of Python does not support HTTPS/SSL ' |  | ||||||
|                     'functionality' |  | ||||||
|                 ) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _build_connection(connection, source_address, timeout, context=None): | def _build_connection(connection, source_address, timeout, context=None): | ||||||
|  | @ -778,7 +712,7 @@ def print_dots(shutdown_event): | ||||||
|     status |     status | ||||||
|     """ |     """ | ||||||
|     def inner(current, total, start=False, end=False): |     def inner(current, total, start=False, end=False): | ||||||
|         if event_is_set(shutdown_event): |         if shutdown_event.isSet(): | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|         sys.stdout.write('.') |         sys.stdout.write('.') | ||||||
|  | @ -817,7 +751,7 @@ class HTTPDownloader(threading.Thread): | ||||||
|         try: |         try: | ||||||
|             if (timeit.default_timer() - self.starttime) <= self.timeout: |             if (timeit.default_timer() - self.starttime) <= self.timeout: | ||||||
|                 f = self._opener(self.request) |                 f = self._opener(self.request) | ||||||
|                 while (not event_is_set(self._shutdown_event) and |                 while (not self._shutdown_event.isSet() and | ||||||
|                         (timeit.default_timer() - self.starttime) <= |                         (timeit.default_timer() - self.starttime) <= | ||||||
|                         self.timeout): |                         self.timeout): | ||||||
|                     self.result.append(len(f.read(10240))) |                     self.result.append(len(f.read(10240))) | ||||||
|  | @ -826,8 +760,6 @@ class HTTPDownloader(threading.Thread): | ||||||
|                 f.close() |                 f.close() | ||||||
|         except IOError: |         except IOError: | ||||||
|             pass |             pass | ||||||
|         except HTTP_ERRORS: |  | ||||||
|             pass |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class HTTPUploaderData(object): | class HTTPUploaderData(object): | ||||||
|  | @ -873,7 +805,7 @@ class HTTPUploaderData(object): | ||||||
| 
 | 
 | ||||||
|     def read(self, n=10240): |     def read(self, n=10240): | ||||||
|         if ((timeit.default_timer() - self.start) <= self.timeout and |         if ((timeit.default_timer() - self.start) <= self.timeout and | ||||||
|                 not event_is_set(self._shutdown_event)): |                 not self._shutdown_event.isSet()): | ||||||
|             chunk = self.data.read(n) |             chunk = self.data.read(n) | ||||||
|             self.total.append(len(chunk)) |             self.total.append(len(chunk)) | ||||||
|             return chunk |             return chunk | ||||||
|  | @ -893,7 +825,7 @@ class HTTPUploader(threading.Thread): | ||||||
|         self.request = request |         self.request = request | ||||||
|         self.request.data.start = self.starttime = start |         self.request.data.start = self.starttime = start | ||||||
|         self.size = size |         self.size = size | ||||||
|         self.result = 0 |         self.result = None | ||||||
|         self.timeout = timeout |         self.timeout = timeout | ||||||
|         self.i = i |         self.i = i | ||||||
| 
 | 
 | ||||||
|  | @ -911,7 +843,7 @@ class HTTPUploader(threading.Thread): | ||||||
|         request = self.request |         request = self.request | ||||||
|         try: |         try: | ||||||
|             if ((timeit.default_timer() - self.starttime) <= self.timeout and |             if ((timeit.default_timer() - self.starttime) <= self.timeout and | ||||||
|                     not event_is_set(self._shutdown_event)): |                     not self._shutdown_event.isSet()): | ||||||
|                 try: |                 try: | ||||||
|                     f = self._opener(request) |                     f = self._opener(request) | ||||||
|                 except TypeError: |                 except TypeError: | ||||||
|  | @ -928,8 +860,6 @@ class HTTPUploader(threading.Thread): | ||||||
|                 self.result = 0 |                 self.result = 0 | ||||||
|         except (IOError, SpeedtestUploadTimeout): |         except (IOError, SpeedtestUploadTimeout): | ||||||
|             self.result = sum(self.request.data.total) |             self.result = sum(self.request.data.total) | ||||||
|         except HTTP_ERRORS: |  | ||||||
|             self.result = 0 |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class SpeedtestResults(object): | class SpeedtestResults(object): | ||||||
|  | @ -1183,9 +1113,9 @@ class Speedtest(object): | ||||||
|             # times = get_attributes_by_tag_name(root, 'times') |             # times = get_attributes_by_tag_name(root, 'times') | ||||||
|             client = get_attributes_by_tag_name(root, 'client') |             client = get_attributes_by_tag_name(root, 'client') | ||||||
| 
 | 
 | ||||||
|         ignore_servers = [ |         ignore_servers = list( | ||||||
|             int(i) for i in server_config['ignoreids'].split(',') if i |             map(int, server_config['ignoreids'].split(',')) | ||||||
|         ] |         ) | ||||||
| 
 | 
 | ||||||
|         ratio = int(upload['ratio']) |         ratio = int(upload['ratio']) | ||||||
|         upload_max = int(upload['maxchunkcount']) |         upload_max = int(upload['maxchunkcount']) | ||||||
|  | @ -1313,7 +1243,7 @@ class Speedtest(object): | ||||||
|                             raise SpeedtestServersError( |                             raise SpeedtestServersError( | ||||||
|                                 'Malformed speedtest.net server list: %s' % e |                                 'Malformed speedtest.net server list: %s' % e | ||||||
|                             ) |                             ) | ||||||
|                         elements = etree_iter(root, 'server') |                         elements = root.getiterator('server') | ||||||
|                     except AttributeError: |                     except AttributeError: | ||||||
|                         try: |                         try: | ||||||
|                             root = DOM.parseString(serversxml) |                             root = DOM.parseString(serversxml) | ||||||
|  | @ -1533,9 +1463,6 @@ class Speedtest(object): | ||||||
|                 build_request(url, bump=i, secure=self._secure) |                 build_request(url, bump=i, secure=self._secure) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         max_threads = threads or self.config['threads']['download'] |  | ||||||
|         in_flight = {'threads': 0} |  | ||||||
| 
 |  | ||||||
|         def producer(q, requests, request_count): |         def producer(q, requests, request_count): | ||||||
|             for i, request in enumerate(requests): |             for i, request in enumerate(requests): | ||||||
|                 thread = HTTPDownloader( |                 thread = HTTPDownloader( | ||||||
|  | @ -1546,26 +1473,21 @@ class Speedtest(object): | ||||||
|                     opener=self._opener, |                     opener=self._opener, | ||||||
|                     shutdown_event=self._shutdown_event |                     shutdown_event=self._shutdown_event | ||||||
|                 ) |                 ) | ||||||
|                 while in_flight['threads'] >= max_threads: |  | ||||||
|                     timeit.time.sleep(0.001) |  | ||||||
|                 thread.start() |                 thread.start() | ||||||
|                 q.put(thread, True) |                 q.put(thread, True) | ||||||
|                 in_flight['threads'] += 1 |  | ||||||
|                 callback(i, request_count, start=True) |                 callback(i, request_count, start=True) | ||||||
| 
 | 
 | ||||||
|         finished = [] |         finished = [] | ||||||
| 
 | 
 | ||||||
|         def consumer(q, request_count): |         def consumer(q, request_count): | ||||||
|             _is_alive = thread_is_alive |  | ||||||
|             while len(finished) < request_count: |             while len(finished) < request_count: | ||||||
|                 thread = q.get(True) |                 thread = q.get(True) | ||||||
|                 while _is_alive(thread): |                 while thread.isAlive(): | ||||||
|                     thread.join(timeout=0.001) |                     thread.join(timeout=0.1) | ||||||
|                 in_flight['threads'] -= 1 |  | ||||||
|                 finished.append(sum(thread.result)) |                 finished.append(sum(thread.result)) | ||||||
|                 callback(thread.i, request_count, end=True) |                 callback(thread.i, request_count, end=True) | ||||||
| 
 | 
 | ||||||
|         q = Queue(max_threads) |         q = Queue(threads or self.config['threads']['download']) | ||||||
|         prod_thread = threading.Thread(target=producer, |         prod_thread = threading.Thread(target=producer, | ||||||
|                                        args=(q, requests, request_count)) |                                        args=(q, requests, request_count)) | ||||||
|         cons_thread = threading.Thread(target=consumer, |         cons_thread = threading.Thread(target=consumer, | ||||||
|  | @ -1573,11 +1495,10 @@ class Speedtest(object): | ||||||
|         start = timeit.default_timer() |         start = timeit.default_timer() | ||||||
|         prod_thread.start() |         prod_thread.start() | ||||||
|         cons_thread.start() |         cons_thread.start() | ||||||
|         _is_alive = thread_is_alive |         while prod_thread.isAlive(): | ||||||
|         while _is_alive(prod_thread): |             prod_thread.join(timeout=0.1) | ||||||
|             prod_thread.join(timeout=0.001) |         while cons_thread.isAlive(): | ||||||
|         while _is_alive(cons_thread): |             cons_thread.join(timeout=0.1) | ||||||
|             cons_thread.join(timeout=0.001) |  | ||||||
| 
 | 
 | ||||||
|         stop = timeit.default_timer() |         stop = timeit.default_timer() | ||||||
|         self.results.bytes_received = sum(finished) |         self.results.bytes_received = sum(finished) | ||||||
|  | @ -1626,9 +1547,6 @@ class Speedtest(object): | ||||||
|                 ) |                 ) | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         max_threads = threads or self.config['threads']['upload'] |  | ||||||
|         in_flight = {'threads': 0} |  | ||||||
| 
 |  | ||||||
|         def producer(q, requests, request_count): |         def producer(q, requests, request_count): | ||||||
|             for i, request in enumerate(requests[:request_count]): |             for i, request in enumerate(requests[:request_count]): | ||||||
|                 thread = HTTPUploader( |                 thread = HTTPUploader( | ||||||
|  | @ -1640,22 +1558,17 @@ class Speedtest(object): | ||||||
|                     opener=self._opener, |                     opener=self._opener, | ||||||
|                     shutdown_event=self._shutdown_event |                     shutdown_event=self._shutdown_event | ||||||
|                 ) |                 ) | ||||||
|                 while in_flight['threads'] >= max_threads: |  | ||||||
|                     timeit.time.sleep(0.001) |  | ||||||
|                 thread.start() |                 thread.start() | ||||||
|                 q.put(thread, True) |                 q.put(thread, True) | ||||||
|                 in_flight['threads'] += 1 |  | ||||||
|                 callback(i, request_count, start=True) |                 callback(i, request_count, start=True) | ||||||
| 
 | 
 | ||||||
|         finished = [] |         finished = [] | ||||||
| 
 | 
 | ||||||
|         def consumer(q, request_count): |         def consumer(q, request_count): | ||||||
|             _is_alive = thread_is_alive |  | ||||||
|             while len(finished) < request_count: |             while len(finished) < request_count: | ||||||
|                 thread = q.get(True) |                 thread = q.get(True) | ||||||
|                 while _is_alive(thread): |                 while thread.isAlive(): | ||||||
|                     thread.join(timeout=0.001) |                     thread.join(timeout=0.1) | ||||||
|                 in_flight['threads'] -= 1 |  | ||||||
|                 finished.append(thread.result) |                 finished.append(thread.result) | ||||||
|                 callback(thread.i, request_count, end=True) |                 callback(thread.i, request_count, end=True) | ||||||
| 
 | 
 | ||||||
|  | @ -1667,10 +1580,9 @@ class Speedtest(object): | ||||||
|         start = timeit.default_timer() |         start = timeit.default_timer() | ||||||
|         prod_thread.start() |         prod_thread.start() | ||||||
|         cons_thread.start() |         cons_thread.start() | ||||||
|         _is_alive = thread_is_alive |         while prod_thread.isAlive(): | ||||||
|         while _is_alive(prod_thread): |  | ||||||
|             prod_thread.join(timeout=0.1) |             prod_thread.join(timeout=0.1) | ||||||
|         while _is_alive(cons_thread): |         while cons_thread.isAlive(): | ||||||
|             cons_thread.join(timeout=0.1) |             cons_thread.join(timeout=0.1) | ||||||
| 
 | 
 | ||||||
|         stop = timeit.default_timer() |         stop = timeit.default_timer() | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue