
    SOgc                     
   S SK r S SKrS SKrS SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
r
S SKrS SKr S SKr\R                  rSr " S S\5      rSq\" 5       r\R.                  SS S:  r\R.                  SS S:  r\R.                  SS S	:  r S SKr S SKJs  Jr    S S
KJ!r"   S SK'J(r(J)r)J*r*J+r+J,r,J-r-J.r.J/r/J0r0J1r1   S SK3J4r4J5r5   S SK3J7r7   S SK3J8r8   S SK9J9r9   S SK;J;r;   S SK;J=r=   S SK?J@r@   S SKAJBrC  S SKAJDrE  \FrG\HrI\JrK S SKOJPrP  SrQ S SKSrSCSS rTS rU\(       a  \ R                  R                  rcO\(       a  \"R                  rc\(       a  \R                  R                  rgO\R                  R                  rg S SKiri \iR                  4rk\*\+\R                  \iR                  \54\k-   rp " S& S'\q5      rr " S( S)\r5      rs " S* S+\r5      rt " S, S-\r5      ru " S. S/\r5      rv " S0 S1\t5      rw " S2 S3\t5      rx " S4 S5\r5      ry " S6 S7\r5      rz " S8 S9\r5      r{ " S: S;\r5      r| " S< S=\r5      r} " S> S?\r5      r~ " S@ SA\r5      r " SB SC\r5      r " SD SE\r5      r\S4SF jr " SG SH\45      r\7(       a   " SI SJ\75      rSoSK jr " SL SM\,5      r " SN SO\,5      rSpSP jr " SQ SR\5      rSS rST rSU rSqSV jrSoSW jrSX rSY rSZ rS[ r " S\ S]\R                  5      r " S^ S_\5      r " S` Sa\R                  5      r " Sb Sc\5      r " Sd Se\5      rSf rSg rSrSh jrSi rSj rSsSk jrSl rSm r\Sn:X  a  \" 5         gg! \ a    Sr\r GNf = f! \ a     S SKr GN! \ a    Sr  GNf = ff = f! \ a     GNf = f! \ a    S SK#J$r%  S SKJ&r&  Sr  GNf = f! \ a    S SK2J(r(J)r)J*r*J+r+J,r,J-r-J.r.J/r/J0r0J1r1   GNf = f! \ a    S SK6J4r4J5r5   GNf = f! \ a     S SK6J7r7   GN! \ a    Sr7  GN&f = ff = f! \ a    Sr8 GN2f = f! \ a
    S SK:J9r9   GN>f = f! \ a
    S SK<J;r;   GNJf = f! \ a     S SK<J=r=   GNW! \ a    S SK>J=r=    GNgf = ff = f! \ a
    S SK@J@r@   GNwf = f! \ a    S SKLJMrC  S SKLJNrE  SrGSrISrK GNf = f! \ a#     S SKPJPrP  SrQ GN! \ a    S SKRJPrPJQrQ    GNf = ff = f! \ at    S SKVrVS S KRJWrWJXrX   " S! S"\W5      rY\Z" \VS#5      r[ \Y" \R                  5      r]\Y" \R                  5      r_O$! \` a    \R                  r]\R                  r_ Of = fS$ rTS% rU GNf = f! \l a    \m" 5       rk GNf = f! \ a    Sri\*\+\R                  \54rp GNf = f)t    Nz2.1.3c                   (    \ rS rSrSr\S 5       rSrg)FakeShutdownEvent*   z|Class to fake a threading.Event.isSet so that users of this module
are not required to register their own threading.Event()
c                      g)z#Dummy method to always return falseF r       N/Users/admin/workspace/ai/Jarvis/env/lib/python3.13/site-packages/speedtest.pyisSetFakeShutdownEvent.isSet/   s     r   r   N)__name__
__module____qualname____firstlineno____doc__staticmethodr
   __static_attributes__r   r   r	   r   r   *   s      r   r   F   )r      )r      )   r   )_Element)minidom)
ExpatError)
urlopenRequest	HTTPErrorURLErrorAbstractHTTPHandlerProxyHandlerHTTPDefaultErrorHandlerHTTPRedirectHandlerHTTPErrorProcessorOpenerDirector)HTTPConnectionBadStatusLine)HTTPSConnection)
FakeSocket)Queue)urlparse)parse_qs)md5)ArgumentParser)SUPPRESS)OptionParser)SUPPRESS_HELPintstringfloat)StringIO)r3   BytesIOc                 L     U R                  SS5      $ ! [         a    U s $ f = f)z)Encode value to utf-8 if possible for py2utf8strict)encodeAttributeErrorvs    r	   to_utf8r<      s,    	88FH-- 	H	s    ##c                    ^
 UR                  S[        R                  5      m
T
c  gU
4S jnSnUR                  SS5      nUb8  [        U[        5      (       a  SnO [        U[
        5      (       d  [        S5      eUR                  SS5      nUb8  [        U[        5      (       a  SnO [        U[
        5      (       d  [        S	5      eU(       a  [        S
5      eU(       d"  U  H  n[        U[        5      (       d  M  Sn  O   U(       a  [	        S5      n[	        S5      nOSnSnUc  UnUc  Un[        U 5       H  u  pU	(       a  U" U5        U" U5        M     U" U5        g)zThe new-style print function for Python 2.4 and 2.5.

Taken from https://pypi.python.org/pypi/six/

Modified to set encoding to UTF-8 always, and to flush after write
fileNc                 ,  > [        U [        5      (       d  [        U 5      n Sn[        T[        5      (       a;  [        U [        5      (       a&  Ub#  [        TSS 5      nUc  SnU R                  X5      n TR                  U 5        TR                  5         g )Nr6   errorsr7   )	
isinstance
basestringstrr>   unicodegetattrr8   writeflush)dataencodingr@   fps      r	   rF   print_.<locals>.write   sx    dJ//4yH2t$$tW--( Xt4>%F{{84HHTNHHJr   FsepTzsep must be None or a stringendzend must be None or a stringz$invalid keyword arguments to print()
 )popsysstdoutrA   rD   rC   	TypeError	enumerate)argskwargsrF   want_unicoderL   rM   argnewlinespaceirJ   s             @r	   print_r\      s=    ZZ

+:	 jj%?#w''#S)) >??jj%?#w''#S)) >??BCCc7++#'L  dmGCLEGE;C;CoFAc
#J & 	c
r   )TextIOWrapperFileIOc                   8   ^  \ rS rSrSrU 4S jrU 4S jrSrU =r$ )_Py3Utf8Output   zFUTF-8 encoded wrapper around stdout for py3, to override
ASCII stdout
c                 `   > [        UR                  5       S5      n[        [        U ]  USSS9  g )Nwr6   r7   )rI   r@   )r^   filenosuperr`   __init__)selffrV   buf	__class__s       r	   rf   _Py3Utf8Output.__init__   s2    S)C.$0 1 r   c                 L   > [         [        U ]  U5        U R                  5         g N)re   r`   rF   rG   )rg   srj   s     r	   rF   _Py3Utf8Output.write   s    .$-a0JJLr   r   )	r   r   r   r   r   rf   rF   r   __classcell__)rj   s   @r	   r`   r`      s    			 	r   r`   printc                     U $ )zNo-op encode to utf-8 for py3r   r:   s    r	   r<   r<      s    r   c                      UR                  S5      [        R                  :X  a
  [        US'   OUR                  S[        5      US'   [        U 0 UD6  g)z>Wrapper function for py3 to print, with a utf-8 encoded stdoutr>   N)getrQ   stderr_py3_utf8_stderr_py3_utf8_stdout
_py3_printrU   rV   s     r	   r\   r\      sB    ::f+-F6N#ZZ0@AF6ND#F#r   c                       \ rS rSrSrSrg)SpeedtestExceptioni)  zBase exception for this moduler   Nr   r   r   r   r   r   r   r   r	   r{   r{   )  s    (r   r{   c                       \ rS rSrSrSrg)SpeedtestCLIErrori-  z9Generic exception for raising errors during CLI operationr   Nr|   r   r   r	   r~   r~   -  s    Cr   r~   c                       \ rS rSrSrSrg)SpeedtestHTTPErrori1  z#Base HTTP exception for this moduler   Nr|   r   r   r	   r   r   1  s    -r   r   c                       \ rS rSrSrSrg)SpeedtestConfigErrori5  zConfiguration XML is invalidr   Nr|   r   r   r	   r   r   5  s    &r   r   c                       \ rS rSrSrSrg)SpeedtestServersErrori9  zServers XML is invalidr   Nr|   r   r   r	   r   r   9  s     r   r   c                       \ rS rSrSrSrg)ConfigRetrievalErrori=  zCould not retrieve config.phpr   Nr|   r   r   r	   r   r   =  s    'r   r   c                       \ rS rSrSrSrg)ServersRetrievalErroriA  z(Could not retrieve speedtest-servers.phpr   Nr|   r   r   r	   r   r   A  s    2r   r   c                       \ rS rSrSrSrg)InvalidServerIDTypeiE  z/Server ID used for filtering was not an integerr   Nr|   r   r   r	   r   r   E  s    9r   r   c                       \ rS rSrSrSrg)NoMatchedServersiI  z!No servers matched when filteringr   Nr|   r   r   r	   r   r   I  s    +r   r   c                       \ rS rSrSrSrg)SpeedtestMiniConnectFailureiM  z7Could not connect to the provided speedtest mini serverr   Nr|   r   r   r	   r   r   M  s    Ar   r   c                       \ rS rSrSrSrg)InvalidSpeedtestMiniServeriQ  zbServer provided as a speedtest mini server does not actually appear
to be a speedtest mini server
r   Nr|   r   r   r	   r   r   Q      r   r   c                       \ rS rSrSrSrg)ShareResultsConnectFailureiW  z6Could not connect to speedtest.net API to POST resultsr   Nr|   r   r   r	   r   r   W  s    @r   r   c                       \ rS rSrSrSrg)ShareResultsSubmitFailurei[  zJUnable to successfully POST results to speedtest.net API after
connection
r   Nr|   r   r   r	   r   r   [  r   r   r   c                       \ rS rSrSrSrg)SpeedtestUploadTimeoutia  zvtestlength configuration reached during upload
Used to ensure the upload halts when no additional data should be sent
r   Nr|   r   r   r	   r   r   a  r   r   r   c                       \ rS rSrSrSrg)SpeedtestBestServerFailureig  zUnable to determine best serverr   Nr|   r   r   r	   r   r   g  s    )r   r   c                       \ rS rSrSrSrg)SpeedtestMissingBestServerik  z?get_best_server not called or not able to determine best serverr   Nr|   r   r   r	   r   r   k  s    Ir   r   c                    U u  p4Sn[         R                  " X4S[         R                  5       Hq  nUu  pxpnSn [         R                   " XxU	5      nU[        La  UR	                  [        U5      5        U(       a  UR                  U5        UR                  U5        Us  $    Ub  Ue[         R                  " S5      e! [         R                   a$    [        5       nUb  UR                  5          M   M  f = f)a  Connect to *address* and return the socket object.

Convenience function.  Connect to *address* (a 2-tuple ``(host,
port)``) and return the socket object.  Passing the optional
*timeout* parameter will set the timeout on the socket instance
before attempting to connect.  If no *timeout* is supplied, the
global default timeout setting returned by :func:`getdefaulttimeout`
is used.  If *source_address* is set it must be a tuple of (host, port)
for the socket to bind as a source address before making the connection.
An host of '' or port 0 tells the OS to use the default.

Largely vendored from Python 2.7, modified to work with Python 2.4
Nr   z!getaddrinfo returns an empty list)socketgetaddrinfoSOCK_STREAM_GLOBAL_DEFAULT_TIMEOUT
settimeoutr2   bindconnecterrorget_exceptionclose)addresstimeoutsource_addresshostporterrresafsocktypeproto	canonnamesasocks                r	   create_connectionr   o  s      JD
C!!$a1C1CD-0*e	==u5D55g/		.)LLK E" 	ll>?? || 	/C

  	s   A$B==1C54C5c                   $    \ rS rSrSrS rS rSrg)SpeedtestHTTPConnectioni  zMCustom HTTPConnection to support source_address across
Python 2.4 - Python 3
c                     UR                  SS 5      nUR                  SS5      nS U l        [        R                  " U /UQ70 UD6  X0l        X@l        g Nr   r   
   )rP   _tunnel_hostr$   rf   r   r   rg   rU   rV   r   r   s        r	   rf    SpeedtestHTTPConnection.__init__  sN    $4d;**Y+ 6t6v6,r   c                 |    [         R                  " U R                  U R                  4U R                  U R
                  5      U l        U R                  (       a  U R                  5         gg! [        [        4 a?    [        U R                  U R                  4U R                  U R
                  5      U l         Nqf = f)z3Connect to the host and port specified in __init__.N)r   r   r   r   r   r   r   r9   rS   r   _tunnelrg   s    r	   r   SpeedtestHTTPConnection.connect  s    	00DII&##DI LLN  	* 	)DII&##DI	s   AA, ,AB;:B;r   r   r   r   N)r   r   r   r   r   rf   r   r   r   r   r	   r   r     s    	r   r   c                   (    \ rS rSrSrSrS rS rSrg)SpeedtestHTTPSConnectioni  zNCustom HTTPSConnection to support source_address across
Python 2.4 - Python 3
c                     UR                  SS 5      nUR                  SS5      nS U l        [        R                  " U /UQ70 UD6  X@l        X0l        g r   )rP   r   r&   rf   r   r   r   s        r	   rf   !SpeedtestHTTPSConnection.__init__  sN    #ZZ(8$?NjjB/G $D$$T;D;F;"L"0r   c                     [         R                  " U R                  U R                  4U R                  U R
                  5      U l        U R                  (       a  U R                  5         [        (       au   0 n[        [        S5      (       a0  U R                  (       a  U R                  US'   OU R                  US'   U R                  R                  " U R                  40 UD6U l        g[         (       a;   [!        U R                  [         R                  " U R                  5      5      U l        g[#        S5      e! [        [        4 a@    [        U R                  U R                  4U R                  U R
                  5      U l         GNAf = f! [         aU    [        R                  " U R                  5      U l         U R                  U R                  l         g! [         a      gf = ff = f! [         a    [#        S5      ef = f)z(Connect to a host on a given (SSL) port.
SSLContextserver_hostnamez?This version of Python does not support HTTPS/SSL functionalityN)r   r   r   r   r   r   r   r9   rS   r   r   sslhasattr_contextwrap_socketr   r'   r{   )rg   rV   s     r	   r    SpeedtestHTTPSConnection.connect  s   "44YY		*LL''	   sFsL11,,8<8I8IF#458<		F#45 $ 9 9$)) Nv NDI  *499fjj6K LDI )$ G #I. -YY		*LL''	& &  #		 :DI48II		1) 	 & ,( sJ   AD; 6A3F 69G0 ;AF
F/G->G
G)%G-(G))G-0Hr   N)	r   r   r   r   r   default_portrf   r   r   r   r   r	   r   r     s    	 		1.	r   r   c                     ^ ^^^ U UUU4S jnU$ )zCross Python 2.4 - Python 3 callable to build an ``HTTPConnection`` or
``HTTPSConnection`` with the args we need

Called from ``http(s)_open`` methods of ``SpeedtestHTTPHandler`` or
``SpeedtestHTTPSHandler``
c                 V   > UR                  TTS.5        T(       a  TUS'   T" U 40 UD6$ )Nr   r   context)update)r   rV   
connectionr   r   r   s     r	   inner _build_connection.<locals>.inner  s9    ,
 	  'F9$)&))r   r   )r   r   r   r   r   s   ```` r	   _build_connectionr     s    * * Lr   c                   @    \ rS rSrSrSS jrS r\R                  r	Sr
g)SpeedtestHTTPHandleri  zxCustom ``HTTPHandler`` that can build a ``HTTPConnection`` with the
args we need for ``source_address`` and ``timeout``
Nc                 H    [         R                  " X5        X l        X0l        g rm   )r   rf   r   r   )rg   
debuglevelr   r   s       r	   rf   SpeedtestHTTPHandler.__init__  s    $$T6,r   c                 l    U R                  [        [        U R                  U R                  5      U5      $ rm   )do_openr   r   r   r   rg   reqs     r	   	http_openSpeedtestHTTPHandler.http_open  s3    ||'##
 
 	
r   r   )r   Nr   )r   r   r   r   r   rf   r   r   do_request_http_requestr   r   r   r	   r   r     s    

 '22Lr   r   c                   D    \ rS rSrSr  SS jrS r\R                  r	Sr
g)SpeedtestHTTPSHandleri%  zzCustom ``HTTPSHandler`` that can build a ``HTTPSConnection`` with the
args we need for ``source_address`` and ``timeout``
Nc                 T    [         R                  " X5        X l        X0l        X@l        g rm   )r   rf   r   r   r   )rg   r   r   r   r   s        r	   rf   SpeedtestHTTPSHandler.__init__)  s     $$T6,r   c           	      ~    U R                  [        [        U R                  U R                  U R
                  S9U5      $ )N)r   )r   r   r   r   r   r   r   s     r	   
https_open SpeedtestHTTPSHandler.https_open0  s:    ||(##	 
 	
r   )r   r   r   )r   NNr   )r   r   r   r   r   rf   r   r   r   https_requestr   r   r   r	   r   r   %  s(     CG	
 (33Mr   r   c                 4   [        SU-  SS9  U (       a  U S4n[        SU< 3SS9  OSn[        5       [        UUS9[        UUS9[	        5       [        5       [        5       /n[        5       nS[        5       4/Ul	        U H  nUR                  U5        M     U$ )	zFunction similar to ``urllib2.build_opener`` that will build
an ``OpenerDirector`` with the explicit handlers we want,
``source_address`` for binding, ``timeout`` and our custom
`User-Agent`
zTimeout set to %dTdebugr   zBinding to source address: Nr   z
User-agent)printerr   r   r   r    r!   r"   r#   build_user_agent
addheadersadd_handler)r   r   source_address_tuplehandlersopenerhandlers         r	   build_openerr   >  s     ')6 .23GI	  $ 	,@%,	.-A&-	/!	H F&(8(:;<F7#  Mr   c                   $    \ rS rSrSrS rS rSrg)GzipDecodedResponseib  zA file-like object to decode a response encoded with the gzip
method, as described in RFC 1952.

Largely copied from ``xmlrpclib``/``xmlrpc.client`` and modified
to work for py2.4-py3
c                 t   [         (       d  [        S5      e[        =(       d    [        nU" 5       U l         UR                  S5      n[        U5      S:X  a  OU R                  R                  U5        M>  U R                  R                  S5        [         R                  R                  U SU R                  S9  g )NzEHTTP response body is gzip encoded, but gzip support is not available   r   rb)modefileobj)gzipr   r4   r3   ioreadlenrF   seekGzipFilerf   )rg   responseIOchunks       r	   rf   GzipDecodedResponse.__init__i  s     t$ &I J J $MM$'E5zQGGMM% 	 
 	Qt$@r   c                      [         R                  R                  U 5        U R                  R                  5         g ! U R                  R                  5         f = frm   )r   r  r   r  r   s    r	   r   GzipDecodedResponse.closey  s4    	MM%GGMMODGGMMOs	   < A)r  N)r   r   r   r   r   rf   r   r   r   r   r	   r   r   b  s    A r   r   c                  2    [         R                  " 5       S   $ )z_Helper function to work with py2.4-py3 for getting the current
exception in a try/except block
   )rQ   exc_infor   r   r	   r   r     s     <<>!r   c                    U u  p#Uu  pESn[         R                  " XB-
  5      n[         R                  " XS-
  5      n[         R                  " US-  5      [         R                  " US-  5      -  [         R                  " [         R                  " U5      5      [         R                  " [         R                  " U5      5      -  [         R                  " US-  5      -  [         R                  " US-  5      -  -   n	S[         R                  " [         R
                  " U	5      [         R
                  " SU	-
  5      5      -  n
Xj-  nU$ )z4Determine distance between 2 sets of [lat,lon] in kmi  r   r  )mathradianssincosatan2sqrt)origindestinationlat1lon1lat2lon2radiusdlatdlonacds               r	   distancer"    s     JDJDF<<$D<<$D	$(	dhhtax0	0	$,,t$	%	$,,t$	%
&(,(:
;	$(	

A 	
DJJtyy|TYYq1u%566A
AHr   c                      SS[         R                   " 5       < S[         R                  " 5       S   < S3S[         R                  " 5       -  SS[        -  4n S	R	                  U 5      n[        S
U-  SS9  U$ )z0Build a Mozilla/5.0 compatible User-Agent stringzMozilla/5.0(z; U; r   z; en-us)z	Python/%sz(KHTML, like Gecko)zspeedtest-cli/%srO   zUser-Agent: %sTr   )platformarchitecturepython_version__version__joinr   )ua_tuple
user_agents     r	   r   r     sr     	 ( 1 1 3 ( 5 5 7 :	<h--//[(H (#Jz)6r   c                 R   U(       d  0 nU S   S:X  a  S[        U5         nU< U < 3nOU nSU ;   a  SnOSnU< U< S[        [        R                  R                  5       S-  5      < SU< 3nUR	                  S	S
05        [        S[        U5         < SU< 3SS9  [        XUS9$ )zfBuild a urllib2 request object

This function automatically adds a User-Agent header to all requests

r   :)httphttps?&zx=  .zCache-Controlzno-cache)GETPOSTrO   Tr   )rH   headers)boolr0   timeittimer   r   r   )	urlrH   r6  bumpsecureschemeschemed_urldelim	final_urls	            r	   build_requestrA    s     
1v}"4<0 &,
cz "-e!$V[[%5%5%7$%>!?!%'I NN  tDz2I> 999r   c                    U(       a  UR                   nO[        n U" U 5      nU R                  5       UR                  5       :w  a  [	        SUR                  5       -  SS9  US4$ ! [
         a    [        5       nSU4s $ f = f)zqHelper function to catch common exceptions encountered when
establishing a connection with a HTTP/HTTPS request

zRedirected to %sTr   FN)openr   get_full_urlgeturlr   HTTP_ERRORSr   )requestr   _openuhes        r	   catch_requestrK    sy     7^!RYY[0&4DA5y OQws   AA% %B ?B c                      U R                   R                  nU" S5      S:X  a  [        U 5      $ U $ ! [         a    U R                  n N1f = f)zrHelper function to return either a Gzip reader if
``Content-Encoding`` is ``gzip`` otherwise the response itself

zcontent-encodingr   )r6  	getheaderr9   r   )r  rM  s     r	   get_response_streamrN    sT    '$$..	 #$."8,,O  '&&	's   1 A
	A
c                     U R                  U5      S   n[        [        UR                  R	                  5       5      5      $ )zRetrieve an attribute from an XML document and return it in a
consistent format

Only used with xml.dom.minidom, which is likely only to be used
with python versions older than 2.5
r   )getElementsByTagNamedictlist
attributesitems)domtag_nameelems      r	   get_attributes_by_tag_namerX    s6     ##H-a0DT__**,-..r   c                    ^  SU 4S jjnU$ )zFBuilt in callback function used by Thread classes for printing
status
c                   > TR                  5       (       a  g [        R                  R                  S5        U S-   U:X  a$  USL a  [        R                  R                  S5        [        R                  R	                  5         g )Nr3  r  TrN   )r
   rQ   rR   rF   rG   )currenttotalstartrM   shutdown_events       r	   r   print_dots.<locals>.inner  s[    !!

Q;%C4KJJT"

r   )FFr   r^  r   s   ` r	   
print_dotsra    s     Lr   c                      g rm   r   ry   s     r	   
do_nothingrc    s    r   c                   ,    \ rS rSrSr  SS jrS rSrg)HTTPDownloaderi  z!Thread class for retrieving a URLNc                    [         R                  R                  U 5        X l        S/U l        X0l        X@l        Xl        U(       a  UR                  U l	        O[        U l	        U(       a  X`l        g [        5       U l        g Nr   )	threadingThreadrf   rG  result	starttimer   r[   rC  _openerr   _shutdown_eventr   )rg   r[   rG  r]  r   r   r^  s          r	   rf   HTTPDownloader.__init__  s\    !!$'c!;;DL"DL#1 #4#6D r   c                     [         R                  " 5       U R                  -
  U R                  ::  Ga  U R	                  U R
                  5      nU R                  R                  5       (       d  [         R                  " 5       U R                  -
  U R                  ::  a  U R                  R                  [        UR                  S5      5      5        U R                  S   S:X  a  OQU R                  R                  5       (       d2  [         R                  " 5       U R                  -
  U R                  ::  a  M  UR                  5         g g ! [         a     g [         a     g f = f)N (  r   )r8  default_timerrk  r   rl  rG  rm  r
   rj  appendr  r  r   IOErrorrF  )rg   rh   s     r	   runHTTPDownloader.run'  s   	$$&7DLLHLL.//5577--/$..@%KK&&s166%='9:{{2!+  //5577--/$..@%
 	 I  	 		s   D1E 5E 
E	EE)rl  rm  r[   rG  rj  rk  r   NNr   r   r   r   r   rf   ru  r   r   r   r	   re  re    s    +:> $7$r   re  c                   H    \ rS rSrSrS
S jrS r\S 5       rSS jr	S r
S	rg)HTTPUploaderDatai8  zUFile like object to improve cutting off the upload once the timeout
has been reached
Nc                     Xl         X l        X0l        U(       a  X@l        O[	        5       U l        S U l        S/U l        g rg  )lengthr]  r   rm  r   _datar\  )rg   r|  r]  r   r^  s        r	   rf   HTTPUploaderData.__init__=  s5    
#1 #4#6D 
S
r   c                 (   Sn[        [        [        U R                  5      S-  5      5      n[        =(       d    [        n U" SX-  S[        U R                  5      S-
   -  R                  5       5      U l        g ! [         a    [        S5      ef = f)N$0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZg      B@zcontent1=%sr   	   zMInsufficient memory to pre-allocate upload data. Please use --no-pre-allocate)	r0   roundr|  r4   r3   r8   r}  MemoryErrorr~   )rg   chars
multiplierr  s       r	   pre_allocateHTTPUploaderData.pre_allocateK  s    6s4;;/$678
 
	$aDKK(81(<=>68DJ
  	#( 	s   9A; ;Bc                 \    U R                   (       d  U R                  5         U R                   $ rm   )r}  r  r   s    r	   rH   HTTPUploaderData.data[  s    zzzzr   c                 6   [         R                  " 5       U R                  -
  U R                  ::  a`  U R                  R                  5       (       dA  U R                  R                  U5      nU R                  R                  [        U5      5        U$ [        5       erm   )r8  rr  r]  r   rm  r
   rH   r  r\  rs  r  r   )rg   nr  s      r	   r  HTTPUploaderData.reada  sk    !!#djj0T\\A((..00IINN1%EJJc%j)L(**r   c                     U R                   $ rm   )r|  r   s    r	   __len__HTTPUploaderData.__len__j  s    {{r   )r}  rm  r|  r]  r   r\  rm   )rp  )r   r   r   r   r   rf   r  propertyrH   r  r  r   r   r   r	   rz  rz  8  s/       
+r   rz  c                   ,    \ rS rSrSr  SS jrS rSrg)HTTPUploaderin  zThread class for putting a URLNc                 F   [         R                  R                  U 5        X l        U=U R                  R                  l        U l        X@l        SU l        XPl	        Xl
        U(       a  UR                  U l        O[        U l        U(       a  Xpl        g [        5       U l        g rg  )rh  ri  rf   rG  rH   r]  rk  sizerj  r   r[   rC  rl  r   rm  r   )rg   r[   rG  r]  r  r   r   r^  s           r	   rf   HTTPUploader.__init__q  ss    !!$'388$.	!;;DL"DL#1 #4#6D r   c                    U R                   n [        R                  " 5       U R                  -
  U R                  ::  a  U R
                  R                  5       (       db   U R                  U5      nUR                  S5        UR                  5         [        U R                   R                  R                   5      U l        g SU l        g ! [         aY    [        U R                   R                  5       UR                  R                  U R                  5      S9nU R                  U5      n Nf = f! [$        [&        4 a1    [        U R                   R                  R                   5      U l         g [(         a
    SU l         g f = f)N)rH      r   )rG  r8  rr  rk  r   rm  r
   rl  rS   rA  rD  rH   r  r  r   sumr\  rj  rt  r   rF  )rg   rG  rh   s      r	   ru  HTTPUploader.run  s!   ,,	%%'$..8T\\I,,2244.W-A r
	!$,,"3"3"9"9: ! . ,DLL,E,E,G181B1B4991MOGW-A. /0 	7dll//556DK 	DK	sD   AD- C /AD- ?D- A D*'D- )D**D- ->F -F ?F )rl  rm  r[   rG  rj  r  rk  r   rw  rx  r   r   r	   r  r  n  s    (@D $7(r   r  c                   `    \ rS rSrSr  SS jrS rS rS r\	SS j5       r
SS	 jrSS
 jrSrg)SpeedtestResultsi  aT  Class for holding the results of a speedtest, including:

Download speed
Upload speed
Ping/Latency to test server
Data about server that the test was run against

Additionally this class can return a result data as a dictionary or CSV,
as well as submit a POST of the result data to the speedtest.net API
to get a share results image link.
Nc                 B   Xl         X l        X0l        Uc  0 U l        OX@l        U=(       d    0 U l        S U l        S[        R                  R                  5       R                  5       -  U l	        SU l
        SU l        U(       a  X`l        O[        5       U l        Xpl        g )Nz%sZr   )downloaduploadpingserverclient_sharedatetimeutcnow	isoformat	timestampbytes_received
bytes_sentrl  r   _secure)rg   r  r  r  r  r  r   r<  s           r	   rf   SpeedtestResults.__init__  s}     	>DK Kl!2!2!9!9!;!E!E!GG!L'>DLr   c                 4    [        U R                  5       5      $ rm   )reprrQ  r   s    r	   __repr__SpeedtestResults.__repr__  s    DIIK  r   c                 &   U R                   (       a  U R                   $ [        [        U R                  S-  S5      5      n[        [        U R                  S5      5      n[        [        U R
                  S-  S5      5      nSU R                  S   -  SU-  SSSU-  S	S
U-  SS[        U< SU< SU< SS< 3R                  5       5      R                  5       -  SSSSU R                  -  SU R                  -  SU R                  S   -  /nSS0n[        SSR                  U5      R                  5       XPR                  S9n[        X`R                   S9u  pxU(       a  [#        U5      eUR%                  5       n	UR&                  n
UR)                  5         [        U
5      S:w  a  [+        S5      e[-        U	R/                  5       5      nUR1                  S5      nU(       a  [3        U5      S:w  a  [+        S5      eSUS   -  U l         U R                   $ ) zBPOST data to the speedtest.net API to obtain a share results
link
     @@r   zrecommendedserverid=%sidzping=%szscreenresolution=zpromo=zdownload=%sz
screendpi=z	upload=%sztestmethod=httpzhash=%s-297aae72ztouchscreen=nonezstartmode=pingselectz
accuracy=1zbytesreceived=%szbytessent=%szserverid=%sRefererz*http://c.speedtest.net/flash/speedtest.swfz ://www.speedtest.net/api/api.phpr1  )rH   r6  r<  r      z)Could not submit results to speedtest.netresultidr  z&http://www.speedtest.net/result/%s.png)r  r0   r  r  r  r  r  r+   r8   	hexdigestr  r  rA  r)  r  rK  rl  r   r  coder   r   r*   decodert   r  )rg   r  r  r  api_datar6  rG  rh   rJ  r  r  qsargsr  s                r	   shareSpeedtestResults.share  s   
 ;;;;uT]]V3Q785A&'U4;;/34 %t{{4'88H$& "FHjB#VX''0y{3 "!4!44T__,DKK--#
( JK B%(XXh%7%>%>%@(/F W\\:,Q//668vv		t9+ -< = = (//+,::j)3x=A-+ -< = = ?!L{{r   c           
          U R                   U R                  U R                  U R                  U R                  U R
                  U R                  U R                  U R                  S.	$ )z Return dictionary of result data)	r  r  r  r  r  r  r  r  r  )	r  r  r  r  r  r  r  r  r  r   s    r	   rQ  SpeedtestResults.dict  sO     kkIIkk//"11[[kk

 
	
r   c                     / SQn[        5       n[        R                  " X SS9nUR                  U Vs/ s H  n[	        U5      PM     sn5        UR                  5       $ s  snf )zReturn CSV Headers)
z	Server IDSponsorzServer Name	TimestampDistancePingDownloadUploadSharez
IP Address 	delimiterlineterminator)r3   csvwriterwriterowr<   getvalue)r  rowoutr  r;   s        r	   
csv_headerSpeedtestResults.csv_header  sQ    DjCRHS1SS12||~ 2s   Ac                    U R                  5       n[        5       n[        R                  " X1SS9nUS   S   US   S   US   S   US   US   S   US	   US
   US   U R                  =(       d    SU R
                  S   /
nUR                  U Vs/ s H  n[        U5      PM     sn5        UR                  5       $ s  snf )zReturn data in CSV formatr  r  r  r  sponsornamer  r!  r  r  r  ip)	rQ  r3   r  r  r  r  r  r<   r  )rg   r  rH   r  r  r  r;   s          r	   r  SpeedtestResults.csv  s     yy{jCRHH~d#T(^I%>H~f%tK'8H~c"DL$z2BH~t{{0b$++d2CE 	S1SS12||~ 2s   B;c                     0 nU(       a  UR                  SSS.5        [        R                  " U R                  5       40 UD6$ )zReturn data in JSON format   T)indent	sort_keys)r   jsondumpsrQ  )rg   prettyrV   s      r	   r  SpeedtestResults.json)  s?     MM!  zz$))+000r   )rl  r  r  r  r  r  r  r  r  r  r  )r   r   r   NNNF,)F)r   r   r   r   r   rf   r  r  rQ  r   r  r  r  r   r   r   r	   r  r    sD    
 JN%*.!;z
  	1r   r  c                   ~    \ rS rSrSr  SS jr\S 5       rS rSS jr	S r
SS	 jrSS
 jr\S4S jr\SS4S jrSrg)	Speedtesti5  z>Class for performing standard speedtest.net testing operationsNc                 d   0 U l         X l        X0l        [        X#5      U l        X@l        U(       a  XPl        O[        5       U l        U R                  5         Ub  U R                   R                  U5        0 U l
        / U l        0 U l        [        U R                   S   U R                  US9U l        g )Nr  )r  r   r<  )config_source_address_timeoutr   rl  r  rm  r   
get_configr   serversclosest_bestr  results)rg   r  r   r   r<  r^  s         r	   rf   Speedtest.__init__8  s    -#N<#1 #4#6D KKv&
';;x(<<
r   c                 \    U R                   (       d  U R                  5         U R                   $ rm   )r  get_best_serverr   s    r	   bestSpeedtest.bestU  s    zz  "zzr   c           
         0 n[         (       a  SUS'   [        SXR                  S9n[        X R                  S9u  p4U(       a  [        U5      e/ n[        U5      n  UR                  UR                  S5      5        [        US   5      S	:X  a  OM6  UR                  5         UR                  5         [        UR                  5      S
:w  a  gSR!                  5       R#                  U5      n[%        SU-  SS9    [&        R(                  " U5      nUR/                  S5      R0                  n	UR/                  S5      R0                  n
UR/                  S5      R0                  nUR/                  S5      R0                  nU	S   R=                  S5       Vs/ s H  o(       d  M  [        U5      PM     nn[        US   5      n[        US   5      n/ SQnUUS-
  S / SQS.n[        US   5      n[        [>        R@                  " UU-  5      5      nU[        U
S   5      S.n[        US   5      [        U	S   5      S-  S.n[        US    5      [        U
S    5      S.nU RB                  RE                  UUUUUUUU-  S!.5         [G        US"   5      [G        US#   5      4U l$        [%        S&U RB                  -  SS9  U RB                  $ ! [        [        4 a    [        [        5       5      ef = f! [&        R*                   a    [        5       n[-        SU-  5      ef = f! [2         ar     [4        R6                  " U5      nO&! [8         a    [        5       n[-        SU-  5      ef = f[;        US5      n	[;        US5      n
[;        US5      n[;        US5      n GNf = fs  snf ! [J         a2    [-        S$URM                  S"5      < S%URM                  S#5      < 35      ef = f)'zWDownload the speedtest.net configuration and return only the data
we are interested in
r   Accept-Encodingz)://www.speedtest.net/speedtest-config.phpr6  r<  r  r  r   rq  r   r  Nr  zConfig XML:
%sTr   z)Malformed speedtest.net configuration: %szserver-configr  r  r  	ignoreidsr  ratiomaxchunkcount)i   i   i   i   i   i   i  p )
i^  i  i  r2  i  i  i	  i  i  i  )r  r  threadsperurlthreadsthreadcountr   
testlength)r  ignore_serverssizescountsr  r|  
upload_maxlatlonzUnknown location: lat=z lon=z
Config:
%r)'r   rA  r  rK  rl  r   rN  rs  r  OSErrorEOFErrorr   r  r   r0   r  r8   r)  r   ET
fromstring
ParseErrorr   findattribr9   DOMparseStringr   rX  splitr  ceilr  r   r2   lat_lon
ValueErrorrt   )rg   r6  rG  rI  rJ  configxml_liststream	configxmlrootserver_configr  r  r  r[   r  r  r  up_sizesr  
size_countupload_countr   r  r|  s                           r	   r  Speedtest.get_config[  s   
 4)/G%& K(/Fgll;&q))$R(<%%fkk$&78 >"%&!+  	

rww<3IIK$$^4	!I-T:	@}}Y/ !IIo6==Myy,33HYYx(//FYYx(//F" *+6<<SA
AqQFCFA 	 
 F7O$01
Kuqyz*+
 x)
499Z*%<=> #H_56
 &+,M-89A=
 &./H\23

 	,&3
 		!&-0%u2FGDL 	+48{{} X& <*=?;;<" == !O*?!C   	@y1 !O*?!C 
 7t_MM1$
CH/h?F/h?F	@
X  	&E"FJJu$57 	sa    K :K. A,L 
N N!N" $K+.-LL 
N)M ?N #M##3NN"<Oc                    Uc  / nUc  / nU R                   R                  5         X4 H%  n[        U5       H  u  pE [        U5      X4'   M     M'     / SQn0 n[        (       a  SUS'   / nU GH7  n	 [        U	< SU R                  S   S   < 3UU R                  S9n
[        XR                  S	9u  pU(       a  UR                  S
U-  5        [        5       e[        U5      n/ n  UR                  UR                  S5      5        ['        US   5      S:X  a  OM6  UR)                  5         UR)                  5         [        UR*                  5      S:w  a
  [        5       eSR-                  5       R/                  U5      n[1        SU-  SS9     [2        R4                  " U5      n[;        US5      nU H  n URN                  nU(       a   [        URY                  S5      5      U;  a  M7  [        URY                  S5      5      U R                  S   ;   d  [        URY                  S5      5      U;   a  M   [[        U R\                  [_        URY                  S5      5      [_        URY                  S5      5      45      nUUS'    U R                   U   R                  U5        M       O   U(       d  U(       a  U R                   (       d
  [e        5       eU R                   $ ! [         a    [        SU-  5      ef = f! [         ["        4 a    [        [%        5       5      ef = f! [2        R6                   a    [%        5       n[9        SU-  5      ef = f! [<         aS     [>        R@                  " U5      nO&! [B         a    [%        5       n[9        SU-  5      ef = fURE                  S5      n GNf = f! [F        [H        RJ                  RL                  RB                  4 a    [        5       ef = f! [<         a0    [Q        [S        URT                  RW                  5       5      5      n GNdf = f! [`         a     GM  f = f! [b         a    U/U R                   U'    GM  f = f! [         a     GM  f = f)zRetrieve a the list of speedtest.net servers, optionally filtered
to servers matching those specified in the ``servers`` argument
z)%s is an invalid server type, must be int)z1://www.speedtest.net/speedtest-servers-static.phpz3http://c.speedtest.net/speedtest-servers-static.phpz*://www.speedtest.net/speedtest-servers.phpz,http://c.speedtest.net/speedtest-servers.phpr   r  z	?threads=r  r  r  r  %sr   rq  r   r  r  zServers XML:
%sTr   z'Malformed speedtest.net server list: %sr  r  r  r  r  r!  )3r  clearrT   r0   r  r   r   rA  r  r  rK  rl  rs  r   rN  r  r  r  r   r  r   r  r8   r)  r   r  r  r  r   
etree_iterr9   r  r  r   rP  SyntaxErrorxmlparsersexpatr
  rQ  rR  rS  rT  rt   r"  r  r2   	ExceptionKeyErrorr   )rg   r  excludeserver_listr[   rn   urlsr6  r@   r:  rG  rI  rJ  r  serversxml_list
serversxmlr  elementsr  r
  r!  s                        r	   get_serversSpeedtest.get_servers  s,    ?G?G#-K!+.%(VKN / .
 4)/G%&CU''*'+{{9'=j'IK#<<	 &gllCMM$(+/11,R0"$E'..v{{4/@A ?2./14  
rww<3&/11YY[--o>
*Z7tD2G#%==#<D $.dH#= 'FG!' 3vzz$'7#8#G FJJt,-=M1NN"6::d#34? !$T\\&+FJJu,=&>&+FJJu,=&>&@A #$F3K3Q..v6/ '6 g p w"$$||Y " -CaG H $X. E3MODDE&  "}}  -A"7 IA M#  * G#&??:#>D)  -A"7 IA M# 
 $(#<#<X#FG $S[[%6%6%A%AB 2/112 * G!%d6+<+<+B+B+D&E!FG % ! ! $ 3+1(Q3
 ) s  K0A4Q% K8BQL"M.Q4O+ A2Q3AP(;QP:QK58$LQ-MM
N,M10N,1#NN,(N/)Q+N,,N//9O((Q+6P%!Q$P%%Q(
P72Q6P77Q:QQQQ
Q+*Q+c                    [        U5      n[        R                  R                  US   5      u  p4U(       a   [        R                  R	                  U5      nOUn[        U5      n[        X`R                  S9u  pxU(       a  [        SU-  5      eUR                  5       n	UR                  5         [        R                  " SU	R                  5       5      n
U
(       d  S H  n U R                  R                  U< SU< 35      nUR                  5       R                  5       R                  5       nUR                   S:X  aB  [#        UR%                  5       5      S:X  a#  [        R&                  " S	U5      (       a  U/n
  OM  M  M     U(       a  U
(       d  [+        S
U-  5      eSUS   SUR-                  S5      < SU
S   < 3SSS./U l        U R.                  $ ! [(         a     GM	  f = f)zQInstead of querying for a list of servers, set a link to a
speedtest mini server
r   r  zFailed to connect to %szupload_?[Ee]xtension: "([^"]+)")phpaspaspxjspz/speedtest/upload.r  r  z
size=[0-9]z!Invalid Speedtest Mini Server: %szSpeedtest Minir   /)r  r  r!  r:  latencyr  )r)   ospathsplitextdirnamerA  rK  rl  r   r  r   refindallr  rC  stripr  r  
splitlinesmatchr"  r   rstripr  )rg   r  urlpartsr  extr:  rG  rI  rJ  text	extensionrh   rH   s                r	   set_mini_serverSpeedtest.set_mini_serverM  s   
 F#GG$$Xa[1	''//&)CC$gll;-.G.4/5 6 6 779DHHJJJ@#{{}.	4))47=A 668>>+224D# 12a7HH\488%(E	 9 8 & 5 y, .24:.; < < (QK/2zz#	!M
  ||- ! s    "G
G&%G&c                 z   U R                   (       d  U R                  5         [        U R                   R                  5       5       HQ  nU R                   U    H9  nU R                  R                  U5        [        U R                  5      U:X  d  M9    O   MQ    O   [        SU R                  -  SS9  U R                  $ )zPLimit servers to the closest speedtest.net servers based on
geographic distance
zClosest Servers:
%rTr   )r  r*  sortedkeysr  rs  r  r   )rg   limitr!  rn   s       r	   get_closest_serversSpeedtest.get_closest_servers  s    
 ||))+,A\\!_##A&t||$- %
  - 	&5TB||r   c                    U(       d-  U R                   (       d  U R                  5       nU R                   nU R                  (       a  U R                  S4nOSn[        5       n0 nU GH  n/ n[        R
                  R                  US   5      n[        [        R                  R                  5       S-  5      nU< SU< 3n	[        SS5       GH  n
U	< SU
< 3n[        S< S	U< 3S
S9  [        U	5      n US   S:X  a  [        US   US9nO[        US   US9nSU0nUS   < SUS   < 3n[        R                  " 5       nUR!                  SXS9  UR#                  5       n[        R                  " 5       U-
  nUR+                  S5      n[        UR,                  5      S:X  a&  USR/                  5       :X  a  UR)                  U5        OUR)                  S5        UR1                  5         GM"     [3        [5        U5      S-  S-  S5      nXTU'   GM      [7        UR9                  5       5      S   nUU   nUUS'   UU R>                  l         UU R>                  l!        U RD                  RG                  U5        [        SU-  S
S9  U$ ! [$         a-    ['        5       n[        SU-  S
S9  UR)                  S5         GM  f = f! [:         a    [=        S5      ef = f)z^Perform a speedtest.net "ping" to determine which speedtest.net
server has the lowest latency
r   Nr:  r2  z/latency.txt?x=r   r3  r4  rO   Tr   r/  r  )r   z
User-Agentr   r0  r  )r6  z	ERROR: %ri  r  r  z	test=testr   r  z-Unable to connect to servers to test latency.r2  zBest Server:
%r)$r  rG  r  r   r3  r4  r6  r0   r8  r9  ranger   r)   r   r   rr  rG  getresponserF  r   rs  r  statusr8   r   r  r  rD  rE  
IndexErrorr   r  r  r  r  r   )rg   r  r   r+  r  r  cumr:  stamplatency_urlr[   this_latency_urlr=  hr6  r4  r]  rr\  rJ  r?  avgfastestr  s                           r	   r  Speedtest.get_best_server  s   
 <<224llG$($8$8!#< #' %'
FC''//&-0C((*T12E36>K1a[.91#= 5*:;"$#K0{g-4$QK+?
 4$QK+?  ,Z8G&.qk8A;?D"002EIIeTI;A#113e;E vvayqxx=C'DK4F4F4H,HJJu%JJt$	C !F SA/3C!CLS V	>W\\^,Q/G w!Y#"

$"T)6; # %AK!O48JJt$	$  	>, .= > >	>s   6BJK 2J>=J>Kc           
        ^ ^^^^^ / nT R                   S   S    Hm  n[        ST R                   S   S   5       HJ  nUR                  [        R                  R                  T R                  S   5      < SU< SU< S35        ML     Mo     [        U5      n/ n[        U5       H(  u  pUR                  [        XT R                  S	95        M*     U=(       d    T R                   S
   S   mS
S0mUUUU U4S jn
/ mUUU4S jn[        T5      n[        R                  " U
XU4S9n[        R                  " UX4S9n[        R                  " 5       mUR!                  5         UR!                  5         ["        nU" U5      (       a  UR%                  SS9  U" U5      (       a  M  U" U5      (       a  UR%                  SS9  U" U5      (       a  M  [        R                  " 5       n['        T5      T R(                  l        T R(                  R*                  UT-
  -  S-  T R(                  l        T R(                  R,                  S:  a  ST R                   S
   S'   T R(                  R,                  $ )zTest download speed against speedtest.net

A ``threads`` value of ``None`` will fall back to those dictated
by the speedtest.net configuration
r  r  r   r   r:  z/randomxz.jpg)r;  r<  r  c           
      d  > [        U5       H  u  p4[        UUT
T	R                  S   S   T	R                  T	R                  S9nTS   T:  a*  [
        R                  R                  S5        TS   T:  a  M*  UR                  5         U R                  US5        TS==   S-  ss'   T" X2SS9  M     g )	Nr|  r  r   r^  r  MbP?Tr  r]  )
rT   re  r  rl  rm  r8  r9  sleepr]  putqrequestsrequest_countr[   rG  threadcallback	in_flightmax_threadsrg   r]  s         r	   producer$Speedtest.download.<locals>.producer  s    '1
'KK)*5<<#'#7#7  	*k9KK%%e,  	*k9fd#)$)$6 2r   c                 R  > [         n[        T5      U:  a  U R                  S5      nU" U5      (       a  UR                  SS9  U" U5      (       a  M  TS==   S-  ss'   TR	                  [        UR                  5      5        T" UR                  USS9  [        T5      U:  a  M  g g NTr[  r   r  r  rM   )thread_is_aliver  rt   r)  rs  r  rj  r[   r`  rb  	_is_aliverc  rd  finishedre  s       r	   consumer$Speedtest.download.<locals>.consumer  s    'Ih--/t''KKK.  '')$)$FMM 23=d; h--/r   targetrU   r[  rk         @i    r  )r  rJ  rs  r3  r4  r6  r  r  rT   rA  r  r(   rh  ri  r8  rr  r]  rm  r)  r  r  r  r  )rg   rd  r  r&  r  _rb  ra  r[   r:  rg  rq  r`  prod_threadcons_threadro  stoprp  re  rf  r]  s   ``               @@@@r	   r  Speedtest.download  s     KK(4D1dkk(3J?@WW__TYYu-=>dL M A 5
 D	oFAOOc$,,? &
 CY!7
!CN		7 	7" 	< +&&h-.-,HJ&&h-.,>@$$&#	$$U+ $$$$U+ $$ ##%&)(m#\\((D5L9S@ 	 <<  6)/0DKK	"8,||$$$r   Tc           
        ^ ^^^^^ / nT R                   S   S    H7  n[        ST R                   S   S   5       H  nUR                  U5        M     M9     T R                   S   n/ n[        U5       Hz  u  p[	        UST R                   S   S   T R
                  S9n
U(       a  U
R                  5         SU0nUR                  [        T R                  S	   U
T R                  US
9U45        M|     U=(       d    T R                   S   S   mSS0mUUUU U4S jn/ mUUU4S jn[        U=(       d    T R                   S   S   5      n[        R                  " UXU4S9n[        R                  " UX4S9n[        R                  " 5       mUR                  5         UR                  5         [         nU" U5      (       a  UR#                  SS9  U" U5      (       a  M  U" U5      (       a  UR#                  SS9  U" U5      (       a  M  [        R                  " 5       n[%        T5      T R&                  l        T R&                  R(                  UT-
  -  S-  T R&                  l        T R&                  R*                  $ )zTest upload speed against speedtest.net

A ``threads`` value of ``None`` will fall back to those dictated
by the speedtest.net configuration
r  r  r   r   r  r|  )r^  zContent-lengthr:  )r<  r6  r  c                 x  > [        US U 5       H  u  p4[        UUS   T
US   T	R                  S   S   T	R                  T	R                  S9nTS   T:  a*  [
        R                  R                  S5        TS   T:  a  M*  UR                  5         U R                  US5        TS==   S-  ss'   T" X2SS	9  M     g )
Nr   r  r|  r  rZ  r  r[  Tr\  )
rT   r  r  rl  rm  r8  r9  r]  r]  r^  r_  s         r	   rg  "Speedtest.upload.<locals>.producerW  s    '-(@A
%AJAJKK)(3<<#'#7#7  	*k9KK%%e,  	*k9fd#)$)$6 Br   c                 @  > [         n[        T5      U:  a  U R                  S5      nU" U5      (       a  UR                  SS9  U" U5      (       a  M  TS==   S-  ss'   TR	                  UR
                  5        T" UR                  USS9  [        T5      U:  a  M  g g rj  )rm  r  rt   r)  rs  rj  r[   rn  s       r	   rq  "Speedtest.upload.<locals>.consumerk  s    'Ih--/t''KKK.  '')$)$.=d; h--/r   rs  g?rk  ru  )r  rJ  rs  rT   rz  rm  r  rA  r  r  r(   rh  ri  r8  rr  r]  rm  r)  r  r  r  r  )rg   rd  r  r  r  r  rw  rb  ra  r[   rH   r6  rg  rq  r`  rx  ry  ro  rz  rp  re  rf  r]  s   ``                 @@@@r	   r  Speedtest.upload.  sN    KK(2D1dkk(3H=>T" ? 3
 L1 'GA $H%h/#33	D !!#'.GOO!$))E"2D*13 (* AY!7!AN		7 	7$ 	< '=T[[3H=>&&h-.-,HJ&&h-.,>@$$&#	$$S) $$$$S) $$ ##%"%h-\\$$u5< 	 ||"""r   )r  rl  r  rm  r  r  r  r  r  r  r  )NNr   FNrw  )r   rm   )r   r   r   r   r   rf   r  r  r  r*  rA  rG  r  rc  r  r  r   r   r   r	   r  r  5  sa    HAC.2
:  
rh||4l(JX !+D I%V )tT Z#r   r  c                    ^  U 4S jnU$ )zOCatch Ctrl-C key sequence and set a SHUTDOWN_EVENT for our threaded
operations
c                 f   > TR                  5         [        SSS9  [        R                  " S5        g )N
Cancelling...Tr   r   )setr   rQ   exit)signumframer^  s     r	   r   ctrl_c.<locals>.inner  s%    !.r   r   r`  s   ` r	   ctrl_cr    s     Lr   c                      [        S[        -  5        [        S[        R                  R	                  SS5      -  5        [        R
                  " S5        g)zPrint the versionzspeedtest-cli %sz	Python %srN   r  r   N)r   r(  rQ   versionreplacer  r   r   r	   r  r    s;     ,-K#++--dB778HHQKr   c                 h    [        [        R                  U S95        [        R                  " S5        g)zPrint the CSV Headersr  r   N)r   r  r  rQ   r  r  s    r	   r  r    s&     '')'<=HHQKr   c            	         Sn [        U S9n UR                  Ul        UR                  SSSSSSS	9  UR                  S
SSSSSS	9  UR                  SSSSS9  UR                  SSSSSSS9  UR                  SSSS9  UR                  SSSSS9  UR                  SSSSS9  UR                  SS [        S!S"9  UR                  S#SSS$S9  UR                  S%SSS&S9  UR                  S'SS(S9  UR                  S)[
        S*S+S,9  UR                  S-[
        S*S.S,9  UR                  S/S0S19  UR                  S2S3S19  UR                  S4S5[        S6S"9  UR                  S7SS8S9  UR                  S9S:SSSS;S<9  UR                  S=SS>S9  UR                  S?S[        [        S@9  UR                  5       n[        U[        5      (       a  USA   nU$ UnU$ ! [         a     GNf = f)BzAFunction to handle building and parsing of command line argumentszCommand line interface for testing internet bandwidth using speedtest.net.
--------------------------------------------------------------------------
https://github.com/sivel/speedtest-cli)descriptionz--no-downloadr  Tstore_constFzDo not perform download test)destdefaultactionconsthelpz--no-uploadr  zDo not perform upload testz--single
store_truezYOnly use a single connection instead of multiple. This simulates a typical file transfer.)r  r  r  z--bytesunits)byterv  )bitr  zxDisplay values in bytes instead of bits. Does not affect the image generated by --share, nor output from --json or --csv)r  r  r  r  r  z--sharez]Generate and provide a URL to the speedtest.net share results image, not displayed with --csv)r  r  z--simplez4Suppress verbose output, only show basic information)r  r  r  z--csvzvSuppress verbose output, only show basic information in CSV format. Speeds listed in bit/s and not affected by --bytesz--csv-delimiterr  z<Single character delimiter to use in CSV output. Default ",")r  typer  z--csv-headerzPrint CSV headersz--jsonzwSuppress verbose output, only show basic information in JSON format. Speeds listed in bit/s and not affected by --bytesz--listz:Display a list of speedtest.net servers sorted by distancez--serverrs  zCSpecify a server ID to test against. Can be supplied multiple times)r  r  r  z	--excludez?Exclude a server from selection. Can be supplied multiple timesz--miniz URL of the Speedtest Mini server)r  z--sourcezSource IP address to bind toz	--timeoutr   z#HTTP timeout in seconds. Default 10z--securezPUse HTTPS instead of HTTP when communicating with speedtest.net operated serversz--no-pre-allocater  zDo not pre allocate upload data. Pre allocation is enabled by default to improve upload performance. To support systems with insufficient memory, use this option to avoid a MemoryError)r  r  r  r  r  z	--versionz Show the version number and exitz--debug)r  r  r  r   )	ArgParser
add_optionadd_argumentr9   PARSER_TYPE_STRPARSER_TYPE_INTPARSER_TYPE_FLOATARG_SUPPRESS
parse_argsrA   tuple)r  parseroptionsrU   s       r	   r  r    s   	1  ;/F$// j$,E;  = Hd,E9  ; 
E,)  * 	):;  <
 	,M  N 
<+  , eA  B )3_3  4 |U0  2
uA  B 2  3 
7  8 /(7  8 'IJ

)GH
R6GB  D

<C  D +.,d%+  , L?  A
	,)<  A !G'5!!qz K KK  s   G 
GGc                     S[         4S[        4S.nUR                  5        H4  u  p#[        XS5      (       d  M  US   b  M   [	        US   < SU< S	35      e   g)
zCheck if an argument was provided that depends on a module that may
not be part of the Python standard library.

If such an argument is supplied, and the module does not exist, exit
with an error stating which module is missing.
zjson/simplejson python modulezSSL support)r  r<  Fr  Nr   z is not installed. --z is unavailable)r  r&   rT  rE   
SystemExit)rU   optional_argsrX   infos       r	   validate_optional_argsr    sb     1$7 /2M
 #((*	4e$$a.21gs< = = +r   c                     U(       a  [         (       d  gU(       a/  [        R                  R                  5       (       a  SU -  nOSU -  nOU nU(       a  [        R                  US'   U(       d  [        U40 UD6  gg)z4Helper function print a string with various featuresNz[1;30mDEBUG: %s[0mz	DEBUG: %sr>   )DEBUGrQ   rR   isattyru   r\   )r1   quietr   r   rV   r  s         r	   r   r     sb     UU::.7C&Cvsf r   c            	      L   [         R                  " 5       n [        R                  " [        R                  [	        U 5      5        [        5       nUR                  (       a
  [        5         UR                  (       d  UR                  (       d  [        S5      e[        UR                  5      S:w  a  [        S5      eUR                  (       a  [        UR                  5        [        U5        [        USS5      nUS:X  a  SnU(       a  SqUR                   (       d"  UR"                  (       d  UR$                  (       a  SnOSnUR"                  (       d  UR$                  (       a  SnOSnU(       d  U(       a  [&        nO[)        U 5      n[+        SU5         [-        UR.                  UR0                  UR2                  S	9nUR:                  (       am   UR=                  5         [A        URB                  RE                  5       5       H  u  pxU H  n	SU	-  n
 [+        U
5        M     M!     [L        RN                  " S5        [+        SURP                  S   -  U5        URR                  (       d  [+        SU5         UR=                  URT                  URV                  S9  URT                  (       a&  [        URT                  5      S:X  a  [+        SU5        O[+        SU5        UR_                  5         O;URR                  (       a*  UR_                  URa                  URR                  5      5        URb                  n[+        SURT                  -  U5        UR                  (       as  [+        SUS[e        U5         S9  UR                  USURf                     S9  [+        S UR                  S!-  S!-  URh                  S   -  URh                  S   4-  U5        O[+        S"U5        UR                  (       a~  [+        S#US[e        U5         S9  UR                  UURj                  SURf                     S$9  [+        S%UR                  S!-  S!-  URh                  S   -  URh                  S   4-  U5        O[+        S&U5        [+        S'URm                  5       -  SS(9  UR                   (       d!  URn                  (       a  URo                  5         UR                   (       ax  [+        S)URp                  UR                  S!-  S!-  URh                  S   -  URh                  S   UR                  S!-  S!-  URh                  S   -  URh                  S   4-  5        O^UR"                  (       a#  [+        UR#                  UR                  S*95        O*UR$                  (       a  [+        UR%                  5       5        URn                  (       a%  U(       d  [+        S+URo                  5       -  5        g,g,g,! [4        4[6        -    a    [+        S
SS9  [        [9        5       5      ef = f! [>        4[6        -    a    [+        SSS9  [        [9        5       5      ef = f! [F         a.    [9        5       nURH                  [H        RJ                  :w  a  e  GMw  f = f! [X         a/    [        SSR[                  S URT                   5       5      -  5      e[>        4[6        -    a    [+        SSS9  [        [9        5       5      e[\         a/    [        SSR[                  S URT                   5       5      -  5      ef = f)-zRun the full speedtest.net testz0Cannot supply both --no-download and --no-uploadr  z*--csv-delimiter must be a single characterr   FSUPPRESSHELPTz)Retrieving speedtest.net configuration...)r   r   r<  z'Cannot retrieve speedtest configurationr  z%Cannot retrieve speedtest server listz:%(id)5s) %(sponsor)s (%(name)s, %(country)s) [%(d)0.2f km]r   z Testing from %(isp)s (%(ip)s)...r  z'Retrieving speedtest.net server list...)r  r$  zNo matched servers: %sz, c              3   ,   #    U  H
  nS U-  v   M     g7fr  Nr   .0rn   s     r	   	<genexpr>shell.<locals>.<genexpr>z  s     8Kq$(K   z,%s is an invalid server type, must be an intc              3   ,   #    U  H
  nS U-  v   M     g7fr  r   r  s     r	   r  r    s     'F+Qq+r  z1Retrieving information for the selected server...z&Selecting best server based on ping...z>Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s mszTesting download speed)r  rN   rl  )Nr  )rd  r  zDownload: %0.2f M%s/sr  zSkipping download testzTesting upload speed)rd  r  r  zUpload: %0.2f M%s/szSkipping upload testzResults:
%rr   z5Ping: %s ms
Download: %0.2f M%s/s
Upload: %0.2f M%s/sr  zShare results: %sN)9rh  EventsignalSIGINTr  r  r  r  r  r~   r  csv_delimiterr  r  rE   r  simpler  r  rc  ra  r   r  sourcer   r<  r   rF  r   rR  r*  r   rD  r  rT  rt  errnoEPIPErQ   r  r  minir  r$  r   r)  r   r  rA  r  r7  singler  r  rQ  r  r  )r^  rU   r   r  machine_formatrd  	speedtestrw  r  r  linerJ  r  s                r	   shellr  "  s    __&N
MM&--!78<D ||	== !. / 	/ 4!# LMM4%%&4 D'5)E{{dhh$))xx499 n-7?1;;LL;;
	 yy	5!!#
 !!2!2!8!8!:;JA!(*01DM	 " < 	.1A1A(1KK 9995A	!!$++t||!L ;;3t{{+q0GO<eD!!#	!!)";";DII"FGG &~~./46 }}(%tE{+	-dkk* 	 	
 	'""V+f4

1EA   	
 	(%0{{&tE{+	-**dkk* 	 	

 	%..6)F2djjmCA   	
 	&.NW\\^+48;;4::{{I""V+f4

1EA..6)F2djjmCA	   	! 
d&8&89:	zz.#gmmo56 )zO !"[0 19F001 &'+5 	5;4H#MO44	5  %Aww%++- .   	#(		8DKK889  &'+5 	5;4H#MO44" 	#"ii'F$++'FFG 	s7   )W$ X Y
6$Z $0X0Y
3ZZB\#c                       [        5         g ! [         a    [        SSS9   g [        [        4 a=    [        5       n [        U SS5      S;  a  SU -  nU(       d  SU -  n[	        S	U-  5      e g f = f)
Nr  Tr  r  r  )r   r   r  z%rz	ERROR: %s)r  KeyboardInterruptr   r{   r  r   rE   )rJ  msgs     r	   mainr    su    0 /!.
+ 0O1fa .(CQh[3.//	 /0s   
 A/A	A/.A/__main__rm   )Nr   )NN0Fr  )FFF)r3  r7  r  rQ   r  r  r  r   r8  r  r%  rh  xml.parsers.expatr  r   r  	GZIP_BASEImportErrorobjectr(  r   r  r   version_infoPY25PLUSPY26PLUSPY32PLUSr  
simplejsonxml.etree.ElementTreeetreeElementTreer  r   
ET_Elementxml.domr   r  r   urllib2r   r   r   r   r   r   r    r!   r"   r#   urllib.requesthttplibr$   r%   http.clientr&   r'   r(   queuer)   urllib.parser*   cgihashlibr+   argparser,   r  r-   r  r0   r  rC   r  r2   r  optparser.   r/   	cStringIOr3   r4   r  __builtin__r<   r\   builtinsr]   r^   r`   rE   rx   rR   rw   ru   rv   r  Elementiterr  getiteratorri  is_aliverm  isAliver   CertificateError
CERT_ERRORr9   r  r   SSLErrorrF  r"  r{   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r"  r   rA  rK  rN  rX  ra  rc  re  rz  r  r  r  r  r  r  r  r  r   r  r  r   r   r   r	   <module>r     sQ  $ 
 	 
 
         I
   	 ( BQ6)BQ6)BQ6)	&&@	D= = =:5'"&!!! 41OO)"GpV 	;z J''J&&//O&&..OE**,

 
HfllCLL-H	 ) )D* D.+ .'- '!. !(- (3. 3:, :,) ,B"4 B!3 A!3 A 2 / *!3 *J!3 J (?%)&@Rn D ?? ?D$3. 3,4/ 42!H) <& !:H*"/	#Y%% #L3v 3l-9## -`T1v T1nS	# S	#lSl=$*_7D0 zF a=  DI8  !    &,	B  DD D D DD  :99:
  //   J
  
  &%%&
  !!)) !  !!     26OO   ))% )(()	)  ($(   7+J&)#**5)#**5 & ::::	&$E($@  W
  E
ChmDKEs  M M 	N "M9 )N! O O O? P  P! 'P4 .Q 5Q/ R R: U T7 U 
MMM6M%%M2-M61M22M69N?N NN NN!OOOOO<"O++O83O<7O88O<?P
PPP!P10P14Q;QQQQQQ,+Q,/R
RR7R  R3.R72R33R7:&T4!$TT4T'$T4&T''	T43T47UU UU U'&U'