
    <iFc                     R   S 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	JrJrJrJr   SSKJr  Sr\R,                  " SSSSS	S
SSS5	      rSrSrSq\R6                  S\R8                  S\R:                  S\R<                  S\R>                  S\R@                  S\RB                  S\RD                  S\RF                  S0	r$\R6                  S\R8                  S\R:                  S\R<                  S\R>                  S\R@                  S\RB                  S\RD                  S\RF                  S 0	r% " S! S"\RL                  " S"/ S#Q5      5      r'S3S$ jr(S4S% jr)S5S& jr*S' r+S( r,S6S) jr-S6S* jr.S+ r/S, r0S- r1S. r2S/ r3S0 r4S1 r5S2 r6\*r7g! \ a    SSKr GNcf = f)7at  
Connection and networking based utility functions.

**Module Overview:**

::

  download - download from a given url
  get_connections - quieries the connections belonging to a given process
  system_resolvers - provides connection resolution methods that are likely to be available
  port_usage - brief description of the common usage for a port

  is_valid_ipv4_address - checks if a string is a valid IPv4 address
  is_valid_ipv6_address - checks if a string is a valid IPv6 address
  is_valid_port - checks if something is a valid representation for a port
  is_private_address - checks if an IPv4 address belongs to a private range or not

  address_to_int - provides an integer representation of an IP address

  expand_ipv6_address - provides an IPv6 address with its collapsed portions expanded
  get_mask_ipv4 - provides the mask representation for a given number of bits
  get_mask_ipv6 - provides the IPv6 mask representation for a given number of bits

.. data:: Resolver (enum)

  Method for resolving a process' connections.

  .. versionadded:: 1.1.0

  .. versionchanged:: 1.4.0
     Added **NETSTAT_WINDOWS**.

  .. versionchanged:: 1.6.0
     Added **BSD_FSTAT**.

  .. deprecated:: 1.6.0
     The SOCKSTAT connection resolver is proving to be unreliable
     (:trac:`23057`), and will be dropped in the 2.0.0 release unless fixed.

  ====================  ===========
  Resolver              Description
  ====================  ===========
  **PROC**              /proc contents
  **NETSTAT**           netstat
  **NETSTAT_WINDOWS**   netstat command under Windows
  **SS**                ss command
  **LSOF**              lsof command
  **SOCKSTAT**          sockstat command under \*nix
  **BSD_SOCKSTAT**      sockstat command under FreeBSD
  **BSD_PROCSTAT**      procstat command under FreeBSD
  **BSD_FSTAT**         fstat command under OpenBSD
  ====================  ===========
    N)confenumlog	str_toolsF)PROCproc)NETSTATnetstat)NETSTAT_WINDOWSznetstat (windows))SSss)LSOFlsof)SOCKSTATsockstat)BSD_SOCKSTATzsockstat (bsd))BSD_PROCSTATzprocstat (bsd))	BSD_FSTATzfstat (bsd)z255.255.255.255z'FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF znetstat -npWznetstat -anozss -nptuz
lsof -wnPir   zsockstat -4czprocstat -f {pid}zfstat -p {pid}zF^{protocol}\s+.*\s+{local}\s+{remote}\s+ESTABLISHED\s+{pid}/{name}\s*$z=^\s*{protocol}\s+{local}\s+{remote}\s+ESTABLISHED\s+{pid}\s*$ze^{protocol}\s+ESTAB\s+.*\s+{local}\s+{remote}\s+users:\(\("{name}",(?:pid=)?{pid},(?:fd=)?[0-9]+\)\)$zF^{name}\s+{pid}\s+.*\s+{protocol}\s+{local}->{remote} \(ESTABLISHED\)$zG^\S+\s+{name}\s+{pid}\s+{protocol}4\s+{local}\s+{remote}\s+ESTABLISHED$z?^\S+\s+{name}\s+{pid}\s+\S+\s+{protocol}4\s+{local}\s+{remote}$z:^\s*{pid}\s+{name}\s+.*\s+{protocol}\s+{local}\s+{remote}$zO^\S+\s+{name}\s+{pid}\s+.*\s+{protocol}\s+\S+\s+{local}\s+[-<]-[->]\s+{remote}$c                       \ rS rSrSrSrg)
Connection   a  
Network connection information.

.. versionchanged:: 1.5.0
   Added the **is_ipv6** attribute.

:var str local_address: ip address the connection originates from
:var int local_port: port the connection originates from
:var str remote_address: destionation ip address
:var int remote_port: destination port
:var str protocol: protocol of the connection ('tcp', 'udp', etc)
:var bool is_ipv6: addresses are ipv6 if true, and ipv4 otherwise
 N)__name__
__module____qualname____firstlineno____doc____static_attributes__r       N/home/james-whalen/.local/lib/python3.13/site-packages/stem/util/connection.pyr   r      s    r    r   )local_address
local_portremote_addressremote_portprotocolis_ipv6c                 `   Uc  Sn[         R                   " 5       n [        R                  " XS9R                  5       $ ! [        R
                   a3  n[        R                  " X[        R                  " 5       S   U5      eSnAf  [        R                  " 5       SS u  pEUb  U[         R                   " 5       U-
  -  nUS:  a5  Ub  US:  a,  [        R                  " SXU4-  5        [        XUS-
  5      s $ [        R                  " SU < S	U< 35        [        R                  " XU5      e= f)
a  
Download from the given url.

.. versionadded:: 1.8.0

:param str url: uncompressed url to download from
:param int timeout: timeout when connection becomes idle, no timeout applied
  if **None**
:param int retires: maximum attempts to impose

:returns: **bytes** content of the given url

:raises:
  * :class:`~stem.DownloadTimeout` if our request timed out
  * :class:`~stem.DownloadFailed` if our request fails
Nr   )timeout         z5Failed to download from %s (%i retries remaining): %szFailed to download from : )timeurlliburlopenreadsocketr)   stemDownloadTimeoutsysexc_infor   debugdownloadDownloadFailed)urlr)   retries
start_timeexc
stacktraces         r!   r8   r8      s    $ _Gyy{*6>>#16688	 E


s):G
DD6llnQq)OCz))g{7Q;	iiG3Y\J]]^cGaK00	iiC=>*55s   !> D-.B  A6D-85D-c                 2  ^ U (       d"  [        5       nU(       a  US   n O[        S5      eU(       d  U(       d  [        S5      eS mT" S5        T" SU < SU< SU< 35        [        U[        5      (       a   [        U5      nUc  [        R                  R                  R                  US5      n[        U5      S:X  aH  U [        R                  [        R                  [        R                  4;   a  [        SU< SU < S35      eO\[        U5      S:X  a  US   nOGU [        R                  [        R                  [        R                  4;   a  [        SU< SU < S35      eU [        R                  :X  a'  [        R                  R                  R!                  US9$ ["        U    R%                  US9n [        R                  R                  R'                  U5      n[*        U    R%                  SSSU(       a  UOSU(       a  UOSS9nT" SU-  5        T" SSR-                  U5      -  5        / n	[.        R0                  " U5      n
U4S jnU H  nU
R3                  U5      nU(       d  M  UR5                  5       nU" SUS   U5      u  nnU" S US    U5      u  nnU(       a  U(       a  U(       a  U(       d  Mk  US!   R7                  5       nUS":X  a  S#nUS$;  a  T" S%U< S&U< 35        M  [9        UUUUU[;        U5      5      nU	R=                  U5        T" [	        U5      5        M     T" S'[        U	5      -  5        U	(       d  [        S(U-  5      eU	$ ! [         a    [        S	U-  5      ef = f! [(         a  n[        SU< SU< 35      eS
nAff = f))a  
Retrieves a list of the current connections for a given process. This
provides a list of :class:`~stem.util.connection.Connection`. Note that
addresses may be IPv4 *or* IPv6 depending on what the platform supports.

.. versionadded:: 1.1.0

.. versionchanged:: 1.5.0
   Made our resolver argument optional.

.. versionchanged:: 1.5.0
   IPv6 support when resolving via proc, netstat, lsof, or ss.

:param Resolver resolver: method of connection resolution to use, if not
  provided then one is picked from among those that should likely be
  available for the system
:param int process_pid: pid of the process to retrieve
:param str process_name: name of the process to retrieve

:returns: **list** of :class:`~stem.util.connection.Connection` instances

:raises:
  * **ValueError** if neither a process_pid nor process_name is provided

  * **IOError** if no connections are available or resolution fails
    (generally they're indistinguishable). The common causes are the
    command being unavailable or permissions.
r   z)Unable to determine a connection resolverzAYou must provide a pid or process name to provide connections forc                 H    [         (       a  [        R                  " U 5        g g N)LOG_CONNECTION_RESOLUTIONr   r7   )msgs    r!   _logget_connections.<locals>._log  s      	iin !r    zP================================================================================z#Querying connections for resolver: z, pid: z, name: zProcess pid was non-numeric: %sNTz Unable to determine the pid of 'z'. z- requires the pid to provide the connections.r+   z"There's multiple processes named 'z2 requires a single pid to provide the connections.)pidzUnable to query '': z(?P<protocol>\S+)z(?P<local>[\[\]0-9a-f.:]+)z(?P<remote>[\[\]0-9a-f.:]+)z[0-9]*z\S*)r&   localremoterF   namezResolver regex: %szResolver results:
%s
c                 \  > UR                  SS5      u  p4[        U5      (       d$  [        USS9(       d  T" SU < SU< SU< 35        g[        U5      (       d  T" SU < S	U< SU< 35        gT" S
U< SU< SU< 35        UR	                  S5      R                  S5      [        U5      4$ )N:r+   T)allow_bracketszInvalid z
 address (): NNz port (zValid r-   [])rsplitis_valid_ipv4_addressis_valid_ipv6_addressis_valid_portlstriprstripint)	addr_typeaddr_strlineaddrportrD   s        r!   _parse_address_str+get_connections.<locals>._parse_address_str3  s    a(JD &&/DT\`/a
ItTBC4  
D$?@
dD12[[$$S)3t944r    rH   rI   r&   tcp6tcp)rb   udpzUnrecognized protocol (rO   z%i connections foundzNo results found using: %s)system_resolversIOError
ValueError
isinstancestrrY   r3   utilsystempid_by_namelenResolverr   r   r   r   connectionsRESOLVER_COMMANDformatcallOSErrorRESOLVER_FILTERjoinrecompilematch	groupdictlowerr   rU   append)resolverprocess_pidprocess_nameavailable_resolversall_pidsresolver_commandresultsr=   resolver_regex_strrn   resolver_regexr_   r\   rw   attr
local_addrr#   remote_addrr%   r&   connrD   s                        @r!   get_connectionsr      sd   < 
*,$Q'h?@@	\
X
YY x.X{\hijS!!H$k yy++L$?H
8}	h..x?T?TU	Up|  G  H  I  	I 
V	X!	QKk	h..x?T?TU	U  xD  FN  O  P  	P99>>%%K%88%h/66[6IHii##$45G 'x077#*,$+('<V 8  0017!334+::01.5 d  &Eu__d1'4=$Oj*!3Hd8nd!Sk;ZKKj!'')h	V			'4@A
J[(TijtTuvd
3t9o/ 2 K 001	
.1AA
BB	e  H8;FGGH, 
 H
0@#F
GGHs$   9M 6)M4 M14
N>NNc                    U cE  [         R                  R                  R                  5       (       a  Sn O[        R                  " 5       n U S:X  a  [
        R                  /nOU S:X  a  [
        R                  /nOU S:X  a  [
        R                  /nOtU S:X  a0  [
        R                  [
        R                  [
        R                  /nO>[
        R                  [
        R                  [
        R                  [
        R                  /nU Vs/ s H<  n[         R                  R                  R                  [        U   5      (       d  M:  UPM>     nn[         R                  R                   R                  5       (       ah  ["        R$                  " S["        R&                  5      (       a>  ["        R$                  " S["        R&                  5      (       a  [
        R(                  /U-   nU$ s  snf )a  
Provides the types of connection resolvers likely to be available on this platform.

.. versionadded:: 1.1.0

.. versionchanged:: 1.3.0
   Renamed from get_system_resolvers() to system_resolvers(). The old name
   still works as an alias, but will be dropped in Stem version 2.0.0.

:param str system: system to get resolvers for, this is determined by
  platform.system() if not provided

:returns: **list** of :data:`~stem.util.connection.Resolver` instances available on this platform
GentooWindowsDarwinOpenBSDFreeBSDz/proc/net/tcpz/proc/net/udp)r3   ri   rj   	is_gentooplatformrm   r   r   r   r   r   r	   r   r   is_availablero   r   osaccessR_OKr   )rj   	resolversrs      r!   rd   rd   a  sQ     ^yy!!##f fy))*II##$I
 &&(=(=x}}MI !!8#4#4hmmX[[QI $Z)Qtyy'7'7'D'DEUVWEX'Yq))Z 
YY^^  ""ryy"'''J'JryyYhjljqjqOrOr)+I	 [s   	9G%G%c                 B   [         Gc  [        R                  " 5       n[        R                  R                  [        R                  R                  [        5      S5      n UR                  U5        0 nUR                  S0 5      R                  5        H}  u  pEUR                  5       (       a  XS[        U5      '   M)  SU;   aB  UR                  SS5      u  pg[        [        U5      [        U5      S-   5       H  nXSU'   M	     Mq  [        SU-  5      e   Uq [         (       d  g['        U [(        5      (       a   U R                  5       (       a  [        U 5      n [         R                  U 5      $ ! [          a(  n	["        R$                  " SU< SU	< 35         Sn	A	NSn	A	ff = f)	z
Provides the common use of a given port. For example, 'HTTP' for port 80 or
'SSH' for 22.

.. versionadded:: 1.2.0

:param int port: port number to look up

:returns: **str** with a description for the port, **None** if none is known
Nz	ports.cfgr^   -r+   z'%s' is an invalid keyz>BUG: stem failed to load its internal port descriptions from 'rG   )	PORT_USESr   Configr   pathrt   dirname__file__loadgetitemsisdigitrY   splitrangerf   	Exceptionr   warnrg   rh   )
r^   configconfig_path	port_useskeyvaluemin_portmax_port
port_entryr=   s
             r!   
port_usager     sB    [[]F'',,rwwx8+FKmkk+i

62.446*#;;==$3s8	CZ"yya0
(!#h-X1BCj$)j! D 3c9:
: 7 i 
ct||~~t9D	t	  m	hhZegjkllms    B6E, ,
F6FFc                    [        U [        5      (       a  [        R                  " U 5      n O%[        R
                  R                  U 5      (       d  gU R                  S5      S:w  a  gU R                  S5       HT  nUR                  5       (       a  [        U5      S:  d  [        U5      S:  a    gUS   S:X  d  MC  [        U5      S:  d  MT    g   g)	z
Checks if a string is a valid IPv4 address.

:param str address: string to be checked

:returns: **True** if input is a valid IPv4 address, **False** otherwise
F.r,   r      0r+   T)rg   bytesr   _to_unicoder3   ri   _is_strcountr   r   rY   rl   )addressentrys     r!   rT   rT     s     ##G,G99W%% ]]31 }}S!e==??c%j1nE
S0@	qSSZ!^	 " 
r    c                 P   [        U [        5      (       a  [        R                  " U 5      n O%[        R
                  R                  U 5      (       d  gU(       a1  U R                  S5      (       a  U R                  S5      (       a  U SS n U R                  S5      S:X  a  U R                  SS	U R                  S5      5      S-   nU R                  SUS-   5      nUS:X  a  S
n[        XU 5      (       d  gUS	:w  a  U S
US-
   OS
SU(       a  XS-   S
 OS
/nSR                  [        S
U5      5      n U R                  S5      nUS:  a  gUS:w  a  SU ;  a  gU R                  S5      S:  d  SU ;   a  gU R                  S5       H!  n[         R"                  " SU5      (       a  M!    g   g)z
Checks if a string is a valid IPv6 address.

:param str address: string to be checked
:param bool allow_brackets: ignore brackets which form '[address]'

:returns: **True** if input is a valid IPv6 address, **False** otherwise
FrQ   rR   r+   r   r,   rM   r   Nzff:ff   ::z:::z^[0-9a-fA-f]{0,4}$T)rg   r   r   r   r3   ri   r   
startswithendswithr   rfindfindrT   rt   filterr   ru   rw   )r   rN   
ipv4_startipv4_end	addr_compcolon_countr   s          r!   rU   rU     s    ##G,G99W%%#7#3#3C#8#8"g]]31 sAw||C'89A=J||Ca0H2~h H!=>>-71_*q.)$ksQXdeYeYfQgy}~IhhvdI./G c"+1_aD/}}TQ%7"2}}S!e88(%00 " 
r    c                 2    [        U 5      n[        U5      [        U 5      :w  a  gU(       a  US:X  a  gUS:  =(       a    US:  $ ! [         a<    [        U [        [
        45      (       a  U  H  n[        X15      (       a  M     g    g g[         a     gf = f)a!  
Checks if a string or int is a valid port number.

:param list,str,int entry: string, integer or list to be checked
:param bool allow_zero: accept port number of zero (reserved by definition)

:returns: **True** if input is an integer and within the valid port range, **False** otherwise
Fr   Ti   )rY   rh   	TypeErrorrg   tuplelistrV   rf   )r   
allow_zeror   r^   s       r!   rV   rV     s    JE
5zSZ	
QY(55=(	 %%''$T..  	 s-   #A A A 8BBB
	BBc                 F   [        U 5      (       d  [        SU -  5      eU R                  S5      (       d,  U R                  S5      (       d  U R                  S5      (       a  gU R                  S5      (       a*  [        U R	                  S5      S   5      nUS	:  a  US
::  a  gg)a  
Checks if the IPv4 address is in a range belonging to the local network or
loopback. These include:

  * Private ranges: 10.*, 172.16.* - 172.31.*, 192.168.*
  * Loopback: 127.*

.. versionadded:: 1.1.0

:param str address: string to be checked

:returns: **True** if input is in a private range, **False** otherwise

:raises: **ValueError** if the address isn't a valid IPv4 address
z'%s' isn't a valid IPv4 addressz10.z192.168.z127.Tz172.r   r+         F)rT   rf   r   rY   r   )r   second_octets     r!   is_private_addressr   6  s    " 
w	'	'
6@
AA '"4"4Z"@"@GDVDVW]D^D^ w}}S)!,-Lrlb0	r    c                 ,    [        [        U 5      S5      $ )z
Provides an integer representation of a IPv4 or IPv6 address that can be used
for sorting.

.. versionadded:: 1.5.0

:param str address: IPv4 or IPv6 address

:returns: **int** representation of the address
r*   )rY   _address_to_binary)r   s    r!   address_to_intr   Z  s     
(!	,,r    c           
      T   [        U 5      (       d  [        SU -  5      eU R                  S5      S:X  a  U R                  SSU R	                  S5      5      S-   nU R	                  SUS-   5      nUS:X  a  Sn[        XU 5      n[        S	5       Vs/ s H  oCS
U-  S
US-   -   PM     nnSR                  U Vs/ s H  nS[        US	5      -  PM     sn5      nUS:w  a  U SUS-
   OSXr(       a  XS-   S OS/nSR                  [        SU5      5      n SU ;   a,  SU R                  S5      -
  n	U R                  SSSU	-  -   5      n [        S5       HJ  n
U
S-  nU
S:w  a  U R                  SU5      O
[        U 5      nSX-
  -
  nUS:  d  M:  U SU SU-  -   XS -   n ML     U $ s  snf s  snf )a  
Expands abbreviated IPv6 addresses to their full colon separated hex format.
For instance...

::

  >>> expand_ipv6_address('2001:db8::ff00:42:8329')
  '2001:0db8:0000:0000:0000:ff00:0042:8329'

  >>> expand_ipv6_address('::')
  '0000:0000:0000:0000:0000:0000:0000:0000'

  >>> expand_ipv6_address('::ffff:5.9.158.75')
  '0000:0000:0000:0000:0000:ffff:0509:9e4b'

:param str address: IPv6 address to be expanded

:raises: **ValueError** if the address can't be expanded due to being malformed
z'%s' isn't a valid IPv6 addressr   r,   rM   r   r+   r   Nr*   r   %04xr   r            r   )rU   rf   r   r   r   r   r   rt   rY   r   replaceindexrl   )r   r   r   ipv4_bini	groupingsgroupipv6_snippetr   missing_groupsr   startendmissing_zeross                 r!   expand_ipv6_addressr   l  s   * 
w	'	'
6@
AA ]]31sAw||C'89A=J||Ca0H2~h "'X">?H8=aA1"q&q1u.IA88KVc%m3KLL-71_*q.)$pxV]ij^j^kVl  C  DIhhvdI./G 
W_s++NoodD3+?$?@G QxeAIE',z'--U
#s7|C%Mq#"55Gg  
.+ BKs   F 8F%c                 H   U S:  d  U S:  a  [        SU -  5      eU S:X  a  [        $ [        SU -  S-
  S5      SSS2   n[        S5       Vs/ s H  o!S	U-  S	US-   -   PM     nnS
R	                  U Vs/ s H  n[        [        US5      5      PM     sn5      $ s  snf s  snf )a  
Provides the IPv4 mask for a given number of bits, in the dotted-quad format.

:param int bits: number of bits to be converted

:returns: **str** with the subnet mask representation for this many bits

:raises: **ValueError** if given a number of bits outside the range of 0-32
    r   z$A mask can only be 0-32 bits, got %ir*   r+   Nr   r   r   r   )rf   FULL_IPv4_MASK_get_binaryr   rt   rh   rY   )bitsmask_binr   octetsoctets        r!   get_mask_ipv4r     s     
BY$(
;dB
CCrz dQ+DbD1( 27q:AQU1A;'&: 
6:6%3s5!}%6:	;; ; ;s   B4Bc           
      X   U S:  d  U S:  a  [        SU -  5      eU S:X  a  [        $ [        SU -  S-
  S5      SSS2   n[        S5       Vs/ s H  o!S	U-  S	US-   -   PM     nnS
R	                  U Vs/ s H  nS[        US5      -  PM     sn5      R                  5       $ s  snf s  snf )a   
Provides the IPv6 mask for a given number of bits, in the hex colon-delimited
format.

:param int bits: number of bits to be converted

:returns: **str** with the subnet mask representation for this many bits

:raises: **ValueError** if given a number of bits outside the range of 0-128
   r   z%A mask can only be 0-128 bits, got %ir*   r+   Nr   r   r   rM   r   )rf   FULL_IPv6_MASKr   r   rt   rY   upper)r   r   r   r   r   s        r!   get_mask_ipv6r     s     
CZ4!8
<tC
DDs{ dQ,TrT2( 7<Ah?hQrQU|,h)? 
yAye6CqM)yA	B	H	H	JJ @ Bs   B"4B'c                     [        U 5      (       d  [        SU -  5      e[        U 5      n[        R                  " SU5      nU(       a  S[        UR                  5       S   5      -
  $ [        SU -  5      e)a-  
Provides the number of bits that an IPv4 subnet mask represents. Note that
not all masks can be represented by a bit count.

:param str mask: mask to be converted

:returns: **int** with the number of bits represented by the mask

:raises: **ValueError** if the mask is invalid or can't be converted
z'%s' is an invalid subnet maskz
^(1*)(0*)$r   r+   z)Unable to convert mask to a bit count: %s)rT   rf   r   ru   rw   rl   groups)maskr   
mask_matchs      r!   _get_masked_bitsr     sn     
t	$	$
5<
==  %(xxh/*J%%'*+++
@4G
HHr    c           	          SR                  [        US-
  SS5       Vs/ s H  n[        X-	  S-  5      PM     sn5      $ s  snf )z
Provides the given value as a binary string, padded with zeros to the given
number of bits.

:param int value: value to be converted
:param int bits: number of bits to pad to
r   r+   r   )rt   r   rh   )r   r   ys      r!   r   r     s@     
taxR1HI1HA#uzQ&'1HI	JJIs   ?c                    [        U 5      (       aD  SR                  U R                  S5       Vs/ s H  n[        [	        U5      S5      PM     sn5      $ [        U 5      (       aP  [        U 5      n SR                  U R                  S5       Vs/ s H  n[        [	        US5      S5      PM     sn5      $ [        SU -  5      es  snf s  snf )z
Provides the binary value for an IPv4 or IPv6 address.

:returns: **str** with the binary representation of this address

:raises: **ValueError** if address is neither an IPv4 nor IPv6 address
r   r   r   rM   r   z''%s' is neither an IPv4 or IPv6 address)rT   rt   r   r   rY   rU   r   rf   )r   r   groupings      r!   r   r     s     7##77GMM#<NO<N5KE
A.<NOPPW%%!'*G77w}}UXGYZGY8KHb 126GYZ[[
>H
II P [s   C CrP   )NNNrA   )F)8r   collectionsr   r   ru   r2   r5   r.   r3   	stem.utilstem.util.procstem.util.systemr   r   r   r   urllib.requestrequestr/   ImportErrorurllib2rB   Enumrm   r   r   r   r   r	   r   r   r   r   r   r   r   ro   rs   
namedtupler   r8   r   rd   r   rT   rU   rV   r   r   r   r   r   r   r   r   get_system_resolversr   r    r!   <module>r     s  4l  	  	  
      0 0! " 99*$$
 #:	 -- N N ++z --
Z  , &3 : -- b a ++ --_ e b [ q3:''  7N  O  &6REP0f+\:4n@!H-$:z<4K6I2
K J, ( c  s   F 
F&%F&