
    gr                        d dl Z d dlZd dlZd dlZd dlmZ d dlmZmZ d dlm	Z	 d dl
mZmZmZmZmZ d dlmZmZmZmZmZmZmZ d dlmZ d dlmZmZ d d	lmZmZ d d
l m!Z!m"Z" d dl#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z) d dl*m+Z+m,Z,m-Z-m.Z. d dl/m0Z0 d dl1m2Z2  ejf                         Z4 ejj                   ejl                  e7            Z8dZ9dZ:dZ;e)jx                  jz                  e2j|                  ej~                  z   e2j                  z   e)j                  jz                  e2j                  ej                  z   e2j                  z   e)j                  jz                  e2j                  ej                  z   e2j                  z   e)j                  jz                  e2j                  ej                  z   e2j                  z   e)j                  jz                  e2j                  ej                  z   e2j                  z   e&j                  jz                  e2j|                  ej                  z   e2j                  z   e&j                  jz                  e2j                  ej                  z   e2j                  z   e9e2j|                  ej                  z   e2j                  z   e:e2j|                  ej                  z   e2j                  z   e;e2j|                  ej                  z   e2j                  z   i
ZSdZTdZUdj                  ej                  ej                  ej                  ej                        Z[dZ\dZ]i ddddd ej                         dddd d!dd"dd#dd$g d%e(j                  jz                  d&ej                  d'i d(g d)d*d*d*g e)j                  jz                  d+d,d*d*d*g d-d.d Z`d/ Zad0eebef   fd1Zcd2ed0eebef   fd3Zdd2ed0eebef   fd4Zed0eebef   fd5ZfdHd2ed6egd0eebef   fd7Zhd8eeebef      d9ebd0eebef   fd:Zi	 dHd;ebd6egd0eeebef   ejf   fd<Zkd=ebd0ebfd>Zld?eeeb      d0ebfd@Zm	 dIdAeeebebf      dBeeb   d0eeb   fdCZnd"ee   d0ebfdDZodHdEeebef   d6egd0ebfdFZpdG Zqy)J    N)OrderedDict)datetimetimezone)Enum)AnyDictListOptionalTuple)event_logger
exceptions	livepatchlockmessagesutilversion)_is_attached)UA_CONFIGURABLE_KEYSUAConfig)get_available_resourcesget_contract_information)ATTACH_FAIL_DATE_FORMATPRINT_WRAP_WIDTH)entitlement_factory)ContractStatusUserFacingAvailabilityUserFacingConfigStatusUserFacingStatus)machine_tokennoticesstate_filesuser_config_file)Notice)TxtColor	essentialstandardadvancedz({name: <17}{available: <11}{description}zJ{name: <17}{available: <11}{entitled: <11}{auto_enabled: <16}{description}z4{name: <17}{entitled: <10}{status: <13}{description}nameentitledstatusdescriptionz4{name: <17}{entitled: <19}{status: <22}{description}z={marker} {name: <15}{entitled: <19}{status: <22}{description}_doczUContent provided in json response is currently considered Experimental and may change_schema_versionz0.1r   
machine_idattachedF	effectiveexpiresoriginservicesexecution_statusexecution_detailsfeaturesr    contract idr)   
created_atproductstech_support_levelaccountr)   r;   r<   external_account_ids	simulatedc                     | j                         D cg c]p  }|j                  j                  s|j                  j                  n|j                  j                  |j
                  j                  |j
                  j                  dr c}S c c}w )N)r)   reason_codereason)blocking_incompatible_servicesentitlement
is_variantr)   variant_name	named_msgmsg)entservices     1/usr/lib/python3/dist-packages/uaclient/status.py_get_blocked_by_servicesrO      s~     99;  **55 ##((((55",,11''++	
  s   A5Breturnc           
      "   d }d}| j                         }| j                         }| j                  |v rdnd}i }|t        j                  k(  rt
        j                  }	n| j                  |v r t
        j                  }	|| j                     }n| j                         \  }	}
|	t
        j                  k(  r|
j                  |
j                  d}n|
r|
j                  }|	t
        j                  k(  rd}| j                  r?| j                  j                         D ci c]  \  }}|t         ||      ||       }}}t        |       }| j                  | j                   |j"                  |	j"                  |||||d	}| j$                  s||d<   |S c c}}w )Nr9   noyes)codemessage)cfg)	r)   r,   r*   r+   status_detailsdescription_override	available
blocked_bywarningvariants)status_description_overridecontract_statusr)   r   
UNENTITLEDr   UNAVAILABLEINAPPLICABLEuser_facing_statusWARNINGrK   r\   items_attached_service_statusrO   presentation_namer,   valuerH   )rL   inapplicable_resourcesrV   r[   rW   rX   r^   rY   r\   
ent_statusdetailsrI   variant_clsrZ   service_statuss                  rN   re   re      s    GN::<))+O$::IH.333%11
88--)66J#9#((#C "%"8"8":J-555#LL&{{ !(-::: 	|| 69\\5G5G5I 2k !":#,.#   *#.J %%#))""( 4 
N >>%-z"5s   FrV   c                     t        j                  t        j                         t        j                  t        j                         t        |       j                  r#t        j                  t        j                         t        j                  t              }t        j                  |       }|j                  d   }|d   }t        j                  j                  }|j!                  |d   d|j#                  d      t        j$                         xs g |d   |d   |j#                  dd	      |j#                  d
g       |d|j&                  d   |j&                  d   |j&                  j#                  dd	      |j&                  j#                  dg       dd       |j#                  d      r|j(                  |d<   |j#                  d      r|d   |d<   |j                  j#                  d      }|st+        |       }t-        |d       D ci c](  }|j#                  d      s|d   |j#                  d      * }}|D ]?  }	 t/        | |j#                  dd	            }	|d   j5                  t7        |	||              A |d   j9                  d        |j;                         j#                  di       j#                  d      }
|
r+|
j#                  di       j#                  d      }|r||d   d <   |S c c}w # t0        j2                  $ r Y w xY w)!z8Return configuration of attached status as a dictionary.machineTokenInfocontractInfo	machineIdTr3   r;   r)   	createdAtr9   r=   r:   externalAccountIDsr@   )r/   r0   r3   r    r8   r?   effectiveTor2   effectiveFromr1   availableResourcesc                 &    | j                  dd      S Nr)   r9   getxs    rN   <lambda>z"_attached_status.<locals>.<lambda>  s    fb8I     keyrY   r,   rV   r)   r4   c                 &    | j                  dd      S rw   rx   rz   s    rN   r|   z"_attached_status.<locals>.<lambda>      AEE&",= r}   supportrG   affordancessupportLevelr8   r>   )r    remover#   AUTO_ATTACH_RETRY_FULL_NOTICEAUTO_ATTACH_RETRY_TOTAL_FAILUREr   is_attached_and_contract_validCONTRACT_EXPIREDcopydeepcopyDEFAULT_STATUSr   get_machine_token_filer   ra   rg   updatery   listr?   contract_expiry_datetimer   sortedr   r   EntitlementNotFoundErrorappendre   sortentitlements)rV   responsemachine_token_filern   ro   r>   	resourcesresourcerh   rL   r   r   s               rN   _attached_statusr      s   NN6778NN699:C77v../}}^,H&==cB)778JK#N3L)66<<OO*;7"&&x0||~+"4($V,*..{B?(,,Z<&8 +226:(006088<<["M(:(B(B(F(F(")		
. &0II( ,_ ="00445IJI+C0	 y.IJ||K( 	(,,}55   
	%#HLL4LMC 	##$S*@#F	

 Z"=> 	'')--i<@@O  {{="599.I9EHZ !56O1 22 		s   -K2 K77LLc           	         t        j                  t              }t        |       }|D ]  }|j	                  d      rt
        j                  j                  }nt
        j                  j                  }	 t        | |j	                  dd            }|j                  dk(  r@t        j                          t        j"                  j$                  k(  r|j'                         }nd}|d	   j)                  |j	                  d
|d         |j*                  ||d        |d	   j-                  d        |S # t        j                  $ r* t        j                  d|j	                  dd             Y Dw xY w)z#Return unattached status as a dict.rY   r)   r9   r   z@Ignoring availability of unknown service %s from contract serverzwithout a 'name' keyr   Nr4   presentedAs)r)   r,   rX   rY   c                 &    | j                  dd      S rw   rx   rz   s    rN   r|   z$_unattached_status.<locals>.<lambda>G  r   r}   r~   )r   r   r   r   ry   r   	AVAILABLErg   r`   r   r   r   LOGdebugr)   r   on_supported_kernelLivepatchSupportUNSUPPORTEDr]   r   r,   r   )rV   r   r   r   rY   rL   descr_overrides          rN   _unattached_statusr     sK    }}^,H',I "
<<$.88>>I.::@@I		%#HLL4LMC HH#--/))556 !<<>N!N## ]HV4DE"(6&		
7"
F Z"=>O; 22 	IIV%;<
 	s   1D//9E,+E,c                    t         }|j                  j                  }t        j                  }t        j                         \  }}t        j                         xs g }|dkD  r8|j                  j                  }t        j                  j                  ||      }nRt        j                  j                  r8|j                  j                  }d}t        j                   j                  |      }|||| j"                  | j$                  | j&                  d}t(        j*                  j,                  j/                         }	t0        D ]B  }
t3        | |
      s|	|
   t5        | |
      }t7        |t8              r|j                  }||	|
<   D |	|d   d<   |S )aG  Return a dict with execution_status, execution_details and notices.

    Values for execution_status will be one of UserFacingConfigStatus
    enum:
        inactive, active, reboot-required
    execution_details will provide more details about that state.
    notices is a list of tuples with label and description items.
    r   )pidlock_holderzconfiguration changes)	operation)r5   r6   r    config_pathconfigr7   r   	ua_config)r   INACTIVErg   r   NO_ACTIVE_OPERATIONSr   check_lock_infor    r   ACTIVE	LOCK_HELDformatr!   reboot_cmd_marker_file
is_presentREBOOTREQUIREDENABLE_REBOOT_REQUIRED_TMPLcfg_pathrV   r7   r"   user_configpublic_configto_dictr   hasattrgetattr
isinstancer   )rV   
userStatus
status_valstatus_desclock_pidr   notices_listr   retr   r   vals               rN   _get_config_statusr   L  sh    (J$$**J//K"224X{<<>'RL!|&&,,
((//k 0 
 
	+	+	6	6..44
+	::AA B 
 '(||''LLC !,,::BBDI# !33!7#s#C#t$ii IcN! "+CM+Jr}   show_allc                 x   t        |       j                  rt        |       }nt        |       }|j	                  t        |              t        j                         rt        j                  j                  |       |s9|j                  dg       D cg c]  }|j                  dd      dk(  r| }}||d<   |S c c}w )a  Return status as a dict, using a cache for non-root users

    When unattached, get available resources from the contract service
    to report detailed availability of different resources for this
    machine.

    Write the status-cache when called by root.
    r4   rY   rS   )r   is_attachedr   r   r   r   r   we_are_currently_rootr!   status_cache_filewritery   )rV   r   r   rM   available_servicess        rN   r+   r+   {  s     C$$#C(%c*OO&s+,!!#%%++H5 $<<
B7
{{;.%7 
 

  2O
s   B7r   entitlement_namec                     | D ]d  }|j                  d      |k(  s|j                  d      rdnd|j                  di       j                  d      rdnd|j                  di       dc S  ddi dS )	z0Extract information from the entitlements array.typer*   rS   rR   obligationsenableByDefaultr   )r*   auto_enabledr   rx   )r   r   rG   s      rN   _get_entitlement_informationr     s     $ ??6"&66%0__Z%@Ed #}b9==)  *}bA
 
 d2FFr}   tokenc           
      B	   d}t        j                  t              }	 t        | |      }|j                  di       }|j                  di       }|j                  |j                  dd      |j                  d	d      |j                  d
d      |j                  dg       d|j                  d	d      |j                  d      |j                  d
d      |j                  dg       ddd       t        j                  t        j                        }	|j                  d      r|j                  d      |d<   |d   }
|
|	z
  }|j                         dk  rt         j"                  j%                  |d   d   |
j'                  t(                    }t*        j-                  |j.                  |j0                         t*        j3                  t         j4                  dz   |j.                  z   dz          d}|j                  d      r|j                  d      |d<   |d   }|	|z
  }|j                         dk  rt         j6                  j%                  |d   d   |j'                  t(                    }t*        j-                  |j.                  |j0                         t*        j3                  t         j4                  dz   |j.                  z   dz          d}t9        |       }t;        |d       D cg c]  }|d   s|d	    }}|j                  dg       }|D ]  }|j                  d	d      }	 t=        | |      }tA        ||      }|d   jC                  |j                  d |j0                        |jD                  |d!   |d"   |j0                  |vrd#nd$d%        |d   jG                  d&        tA        |d'      }|d!   r|d(   j                  d)      }|r||d   d*<   |j                  tI        |              |s9|j                  dg       D cg c]  }|j                  dd#      d#k(  r| }}||d<   ||fS # t        j
                  $ r6}t        |d      r#|j                  dk(  rt	        j                         |d}~ww xY wc c}w # t        j>                  $ r Y w xY wc c}w )+zGet a status dictionary based on a token.

    Returns a tuple with the status dictionary and an integer value - 0 for
    success, 1 for failure
    r   rT   i  Nro   accountInfor;   r9   r)   rq   r=   )r;   r)   r<   r=   rr   r@   T)r8   r?   rB   rs   r2   r8   )contract_iddate)	error_msg
error_code
   rt   r1   c                     | d   S )Nr)    rz   s    rN   r|   z!simulate_status.<locals>.<lambda>  s
    &	 r}   r~   rY   resourceEntitlementsr   r4   r   r*   r   rS   rR   )r)   r,   r*   r   rY   c                 &    | j                  dd      S rw   rx   rz   s    rN   r|   z!simulate_status.<locals>.<lambda>  r   r}   r   r   r   r>   )%r   r   r   r   r   ContractAPIErrorr   rT   AttachInvalidTokenErrorry   r   r   nowr   utctotal_secondsr   E_ATTACH_FORBIDDEN_EXPIREDr   strftimer   eventerrorrK   r)   infoSTATUS_TOKEN_NOT_VALIDE_ATTACH_FORBIDDEN_NOT_YETr   r   r   r   r   r   r,   r   r   )rV   r   r   r   r   contract_informationecontract_infoaccount_infor   expiration_datetimedeltarU   effective_datetimer   r   rh   r   r   rL   entitlement_informationr   r   rM   r   s                            rN   simulate_statusr     s    C}}^,H7UC ),,^R@M'++M2>LOO $''b1%))&"5+//R@)--j"=	 %((4"&&t,*..{B?(4(8(8(")	 	
( ,,x||
$C'+//>&y1#c) A%99@@$Z06(112IJ A G KK'++',,KGJJ//$6DtK C) - 1 1/ B%k2(( A%99@@$Z06'001HI A G KK'++',,KGJJ//$6DtK C',I y.AB$ 	  !$$%;R@L 
#<<3	%#4DEC #?*#
 	## ]CHH="3J? 7 G XX-CCE
	

( Z"=>*<CGz}-11.A9EHZ !56OO&s+, $<<
B7
{{;.%7 
 

  2S=Q && 1f!&&C-4466v 22 		6
s5   P1 'Q=$RR1Q:1Q55Q:RRstringc                 n    t         j                  j                         rt        j	                  | |       S | S )z=Return colorized string if using a tty, else original string.)sysstdoutisattySTATUS_HUMANIZE_COLORIZEry   )r   s    rN   for_human_colorizedr   %  s5     :: 	!$$VV4 r}   commandsc                 $   d}| D ]  }|r|dz  }|dj                  |      z  } dj                  t        j                  |t        dz
  d            }d|v rd	}d
}nd}d}dj	                  t
        j                  |||t
        j                        S )Nr9   z &&  z \
   z  )widthsubsequent_indentr   z{
  z
}z{ z }z%{color}{prefix}{content}{suffix}{end})colorprefixcontentsuffixend)jointextwrapwrapr   r   r$   DISABLEGREYENDC)r   r  cmdwrapped_contentr  r  s         rN   colorize_commandsr  .  s    G !vG388C= ! ll,q0T	
O
 299""MM :  r}   column_dataheaderc           	      d   g }|r|j                  |       t        | D cg c]  }t        |d          c}      }|dkD  r?dj                  |      }|j	                  | D cg c]  } |j                  |  c}       |S |j	                  | D cg c]  }|d   	 c}       |S c c}w c c}w c c}w )zReturn a list of content lines to print to console for a section

    Content lines will be center-aligned based on max value length of first
    column.
    r   z{{:>{}}}: {{}}r   )r   maxlenr   extend)r  r  r  pairtemplate_lengthtemplates         rN   get_section_column_contentr  J  s     GvK@D3tAw<@AO#**?;;G4.GH N 	K8DQ89N A H 9s   B# B(B-c                     | t         j                  S 	 | j                         } | j	                  d      S # t        $ r Y w xY w)Nz%c %Z)r   STATUS_CONTRACT_EXPIRES_UNKNOWN
astimezone	Exceptionr   )r2   s    rN   format_expiresr  _  sM    777$$& G$$  s   5 	A Ar+   c                 X   | j                  d      sg| j                  d      r| j                  dd      st        j                  S t        j	                  t        j
                  t        j                  t        j                  t        j                  t        j                        g}| j                  dg       D ]&  }|j                  t        j                  d)i |       ( dj                  |      S | j                  dd      st        j                  g}nt        j	                  t        j
                  t        j                  t        j                        g}| j                  dg       D ]  }|j                  d      }|r|n|j                  d	d
      }|j                  d      dk(  rt        j                  nt        j                  }|j                  t        j	                  |j                  dd
      ||              | j                  d      }|r0|j                  t        j                         |j!                  |       | j                  d      rt|j                  dt        j"                  z          t%        | j                  di       j'                               D ]&  \  }}	|j                  dj	                  ||	             ( |s!|j!                  d
t        j(                  g       |j!                  d
t        j*                  j,                  g       t/        j0                         t.        j2                  j4                  k(  r!|j!                  d
t        j6                  g       dj                  |      S g }
d}| j                  dd      st        j                  g}nt8        g}| j                  dg       D ]  }|j                  dd
      }|j                  d      }|r|n|j                  d	d
      }|j                  dd
      t;        |      t;        |j                  dd
            |d}|j                  dd      }|%|j                  dd      }||
j                  |       |j                  d      }|r|sd}dj	                  |d         |d<   |j                  t=        j                  d)i |       |s|s	t?        |j'                               D ]  \  }\  }}|tA        |      dz
  k7  rdnd}|j                  tB        j	                  ||j                  d      t;        |j                  dd
            t;        |j                  dd
            |j                  d	d
                     |r0|j                  d
       |j                  t        jD                         | j                  d      stA        |
      dkD  rs|j                  d
       |j                  t        j                         | j                  d      }|r|j!                  |       tA        |
      dkD  r|j!                  |
       | j                  d      rt|j                  dt        j"                  z          t%        | j                  di       j'                               D ]&  \  }}	|j                  dj	                  ||	             ( |j                  d
       |sA|r |j                  t        jF                         n|j                  t        j(                         |j                  t        jH                  j	                  d              g }| j                  d!i       j                  dd"      }|r!|j                  t        jJ                  |f       | j                  d#i       j                  dd"      }|r!|j                  t        jL                  |f       | j                  d$d      d%k7  r|j                  t        jN                  tQ        | j                  d&            f       | j                  d#i       j                  d'd"      }|j                  t        jR                  t;        |      f       |r,|j                  d
       |j!                  tU        |(             dj                  |      S )*z&Format status dict for tabular output.r0   rB   r4   N)r)   rY   r*   r   r,   r   )r)   rY   r,   rX   r,   r9   rY   rS   r)   r    r7   z{}: {}Fr*   r+   r(   r[   rU   r\   Tz{}*r   u   ├u   └)markerr)   r*   r+   r,   r   zpro enable <service>)commandr?   unknownr8   r3   freer2   r>   )r  r   )+ry   r   STATUS_NO_SERVICES_AVAILABLESTATUS_SIMULATED_TMPLr   STATUS_SERVICESTATUS_AVAILABLESTATUS_ENTITLEDSTATUS_AUTO_ENABLEDSTATUS_DESCRIPTIONr   r	  STATUS_UNATTACHED_TMPLSTANDALONE_YESSTANDALONE_NOSTATUS_NOTICESr  STATUS_FEATURESr   rd   STATUS_ALL_HINTE_UNATTACHEDrK   r   r   r   r   )LIVEPATCH_KERNEL_NOT_SUPPORTED_UNATTACHEDSTATUS_HEADERr   STATUS_TMPL	enumerater  VARIANT_STATUS_TMPLSTATUS_SERVICE_HAS_VARIANTSSTATUS_ALL_HINT_WITH_VARIANTS"STATUS_FOOTER_ENABLE_SERVICES_WITHSTATUS_FOOTER_ACCOUNTSTATUS_FOOTER_SUBSCRIPTIONSTATUS_FOOTER_VALID_UNTILr  STATUS_FOOTER_SUPPORT_LEVELr  )r+   r   r  rM   r   r,   rY   r    r   rg   service_warningshas_variantsrl   r*   fmt_argsr[   warning_messager\   idx_variantr!  pairsaccount_namecontract_namer>   s                             rN   format_tabularrI  i  sb   ::j!::k"::j$/<<< &,,!00&77%55!)!=!= ( ; ; - G "::j"5 H4;;FgFGH 99W%%zz*d+<<=G '--!00&77 ( ; ; . G "::j"5 !(-C!D & # ]B7  {{;/58 ++!// 
 *11$[[4"+$/ 2 ( **Y'NN8223NN7#::j!NN4(":"::;$VZZ
B%?%E%E%GH <
UxsE:;< NNB 8 89:H115567))+))556 NNXGGH yy!!L::j$'889 /$jjR8 *	N%))*b9H+//0FGN " #''r:  '**626/9-"&&x4  +H %((D9G"")++i">".$++O<%))*5H##(<<0@#A NN;--99:H)28>>3C)D %C!W&)S]Q->&>UEFNN+22#)!(V!4%8 'J ;& $7 'Hb 9$ )0M2(F 3 
9*	X rx;;<zz)$4 5 9rx../**Y'NN7# 1$NN+,zz*th6667 J!;!A!A!CD 	8JCNN8??367	8NN2NN8AABNN8334NN33::* 	; 	

 E::i,00CLh44lCDJJz2.2269EMh99=IJzz(D!V+22vzz)45	
 $ZZ
B7;; )
 	44#$67	
 r1eDE99Wr}   c                    t        |       }d}t               }||d<   |D ]3  }|d   |k(  s|j                  d      |k(  s 	 t        | |d         }|} n |t	        j                  |      t        |       j                  r t        i |       }|d   }|d   |d<   ||d<   n?|d   rt        j                  j                  }	nt        j                  j                  }	|	|d<   j                  |d	<   |S # t        j
                  $ r Y w xY w)
zReturn help information from an uaclient service as a dict

    :param name: Name of the service for which to return help data.

    :raises: UbuntuProError when no help is available.
    Nr)   r   r   )r)   r+   r*   rY   help)r   r   ry   r   r   r   NoHelpContentr   r   re   r   r   rg   r`   	help_info)
rV   r)   r   help_resourceresponse_dictr   help_entrl   
status_msgrY   s
             rN   rK  rK  %  s0    (,IM
  MM M& Ft#x||M'Bd'J.3Xf=MN %M &&D11C$$1(BD#H-
$2:$>j!",h %.88>>I.::@@I%.k"$..M&1 66 s    C22DD)F)N)rr   loggingr   r
  collectionsr   r   r   enumr   typingr   r   r	   r
   r   uaclientr   r   r   r   r   r   r   (uaclient.api.u.pro.status.is_attached.v1r   uaclient.configr   r   uaclient.contractr   r   uaclient.defaultsr   r   uaclient.entitlementsr   (uaclient.entitlements.entitlement_statusr   r   r   r   uaclient.filesr   r    r!   r"   uaclient.files.noticesr#   uaclient.messagesr$   get_event_loggerr   	getLoggerreplace_top_level_logger_name__name__r   	ESSENTIALSTANDARDADVANCEDr   rg   OKGREENSTATUS_STATUS_ENABLEDr  r   FAILSTATUS_STATUS_DISABLEDra   r  STATUS_STATUS_INAPPLICABLEr`   STATUS_STATUS_UNAVAILABLErc   WARNINGYELLOWSTATUS_STATUS_WARNINGENTITLEDSTATUS_ENTITLED_ENTITLEDr_   STATUS_ENTITLED_UNENTITLEDSTATUS_SUPPORT_ESSENTIALSTATUS_SUPPORT_STANDARDSTATUS_SUPPORT_ADVANCEDr   r,  r&  r   r'  r)  STATUS_STATUSr+  r4  r5  r7  get_versionr   r   rO   strre   r   r   r   boolr+   r   intr   r   r  r  r  rI  rK  r   r}   rN   <module>rz     s     
  # '  3 3   B : O G 5   * &%%%'g:::8DE 	
 !!8999HMMI##777(--G!!''

-
-	.
--	   &&

,
,	-
--	 ""!?!??(--O!!8<<<x}}L##

-
-	.
--	 x''(mm h&&'mm h&&'mmE% P D N  GMM		 	 %%!!++	 N  EC 
 # u "w""$	
 $   t d  .77== 66  r .;;AA,  "	-8 9@8	#s(^8vD( DtCH~ DN+H +c3h +\,tCH~ ,^ D T#s(^ <GtCH~&G:=G	#s(^G* ',uu#u
4S>3up  T#Y C : AEeCHo&08	#Y*%HX. %3 %y4S> yT yc yx,r}   