U ÀÒ.eõã@sŽddlmZddlZddlZddlZddlZddlmZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlmZmZddlmZmZmZmZmZddlmZddlm Z m!Z!m"Z"dd l#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,dd l-m.Z.m/Z/e  0e1¡Z2da3e4ed ƒr8d Z5n*ej6 7d ¡rLdZ5nej6dkr^dZ5ndZ5e 8d¡Z9e9s„dej:dd…Z9de9Z;e5e9Zdd¡ >dd¡Z?e 8d¡Z@e@rØe@ 7d¡rØe@ >dd¡Z@ndd„ZAeAƒZ@[Ae BdejCejDB¡ZEe BdejCejDB¡ZFe Bd¡ZGe Bd ¡ZHd!ZId"ZJe jKd#krBd$d%„ZLnd&d%„ZLGd'd(„d(eMƒZNeNƒZOGd)d*„d*eMƒZPd+d,„ZQeQƒZR[Qd/d-d.„ZSdS)0é)Úunicode_literalsN)Úmessage_from_fileé)Ú __version__ÚDistlibException)Ú sysconfigÚZipFileÚfsdecodeÚ text_typeÚfilter)ÚInstalledDistribution)ÚMetadataÚMETADATA_FILENAMEÚWHEEL_METADATA_FILENAME) Ú FileOperatorÚ convert_pathÚ CSVReaderÚ CSVWriterÚCacheÚcached_propertyÚget_cache_baseÚ read_exportsÚtempdir)ÚNormalizedVersionÚUnsupportedVersionErrorZpypy_version_infoZppÚjavaZjyZcliZipÚcpZpy_version_nodotz%s%séÚpyú-Ú_Ú.ZSOABIzcpython-cCsRdtg}t d¡r| d¡t d¡r0| d¡t d¡dkrH| d¡d  |¡S) NrZPy_DEBUGÚdZ WITH_PYMALLOCÚmZPy_UNICODE_SIZEéÚuÚ)Ú VER_SUFFIXrÚget_config_varÚappendÚjoin)Úparts©r,ú=/usr/lib/python3.8/site-packages/pip/_vendor/distlib/wheel.pyÚ _derive_abi;s     r.zz (?P[^-]+) -(?P\d+[^-]*) (-(?P\d+[^-]*))? -(?P\w+\d+(\.\w+\d+)*) -(?P\w+) -(?P\w+(\.\w+)*) \.whl$ z7 (?P[^-]+) -(?P\d+[^-]*) (-(?P\d+[^-]*))?$ s \s*#![^\r\n]*s^(\s*#!("[^"]+"|\S+))\s+(.*)$s#!pythons #!pythonwú/cCs|S©Nr,©Úor,r,r-Ú]ór3cCs| tjd¡S)Nr/)ÚreplaceÚosÚsepr1r,r,r-r3_r4c@s6eZdZdd„Zdd„Zdd„Zd dd „Zd d „ZdS) ÚMountercCsi|_i|_dSr0)Ú impure_wheelsÚlibs©Úselfr,r,r-Ú__init__cszMounter.__init__cCs||j|<|j |¡dSr0)r9r:Úupdate)r<ÚpathnameÚ extensionsr,r,r-Úaddgs z Mounter.addcCs0|j |¡}|D]\}}||jkr|j|=qdSr0)r9Úpopr:)r<r?r@ÚkÚvr,r,r-Úremoveks   zMounter.removeNcCs||jkr|}nd}|Sr0)r:)r<ÚfullnameÚpathÚresultr,r,r-Ú find_moduleqs zMounter.find_modulecCsj|tjkrtj|}nP||jkr,td|ƒ‚t ||j|¡}||_| dd¡}t|ƒdkrf|d|_ |S)Nzunable to find extension for %sr!rr) ÚsysÚmodulesr:Ú ImportErrorÚimpZ load_dynamicÚ __loader__ÚrsplitÚlenÚ __package__)r<rFrHr+r,r,r-Ú load_modulexs       zMounter.load_module)N)Ú__name__Ú __module__Ú __qualname__r=rArErIrRr,r,r,r-r8bs  r8c@sîeZdZdZdZdZd4dd„Zedd „ƒZed d „ƒZ ed d „ƒZ e dd„ƒZ dd„Z e dd„ƒZdd„Zd5dd„Zdd„Zdd„Zdd„Zd6dd„Zd d!„Zd"d#„Zd$d%„Zd&d'„Zd(d)„Zd*d+„Zd7d,d-„Zd.d/„Zd0d1„Zd8d2d3„ZdS)9ÚWheelz@ Class to build and install from Wheel files (PEP 427). ©rrZsha256NFcCs8||_||_d|_tg|_dg|_dg|_t ¡|_ |dkrRd|_ d|_ |j |_ nât |¡}|rš| d¡}|d|_ |d d d ¡|_ |d |_|j |_ nštj |¡\}}t |¡}|sÄtd |ƒ‚|rÖtj |¡|_ ||_ | d¡}|d|_ |d|_ |d |_|d  d¡|_|d d¡|_|d d¡|_dS)zB Initialise an instance using a (valid) filename. r&ÚnoneÚanyNZdummyz0.1ZnmZvnr rZbnzInvalid name or filename: %rrr!ZbiZar)ÚsignZ should_verifyÚbuildverÚPYVERÚpyverÚabiÚarchr6ÚgetcwdÚdirnameÚnameÚversionÚfilenameZ _filenameÚNAME_VERSION_REÚmatchÚ groupdictr5rGÚsplitÚ FILENAME_RErÚabspath)r<rdrZÚverifyr#Úinforar,r,r-r=sD        ÿ    zWheel.__init__cCs^|jrd|j}nd}d |j¡}d |j¡}d |j¡}|j dd¡}d|j|||||fS)zJ Build and return a filename from the various components. rr&r!r z%s-%s%s-%s-%s-%s.whl)r[r*r]r^r_rcr5rb)r<r[r]r^r_rcr,r,r-rd¹s     ÿzWheel.filenamecCstj |j|j¡}tj |¡Sr0)r6rGr*rardÚisfile)r<rGr,r,r-ÚexistsÊsz Wheel.existsccs4|jD](}|jD]}|jD]}|||fVqqqdSr0)r]r^r_)r<r]r^r_r,r,r-ÚtagsÏs   z Wheel.tagsc Cstj |j|j¡}d|j|jf}d|}t d¡}t |dƒÖ}|  |¡}|d  dd¡}t dd „|Dƒƒ}|d kr€t td g} nt tg} d} | D]f} zLt || ¡} | | ¡,} || ƒ}t|d } | rÔW5QR£WqøW5QRXWqtk rôYqXq| std d | ¡ƒ‚W5QRX| S)Nú%s-%sú %s.dist-infoúutf-8Úrú Wheel-Versionr!rcSsg|] }t|ƒ‘qSr,©Úint©Ú.0Úir,r,r-Ú ßsz"Wheel.metadata..rWZMETADATA)Zfileobjz8Invalid wheel, because metadata is missing: looked in %sz, )r6rGr*rardrbrcÚcodecsÚ getreaderrÚget_wheel_metadatarhÚtuplerrÚ posixpathÚopenr ÚKeyErrorÚ ValueError)r<r?Úname_verÚinfo_dirÚwrapperÚzfÚwheel_metadataÚwvÚ file_versionZfnsrHÚfnÚmetadata_filenameÚbfÚwfr,r,r-ÚmetadataÖs6       ÿzWheel.metadatac CsXd|j|jf}d|}t |d¡}| |¡}t d¡|ƒ}t|ƒ}W5QRXt|ƒS)NrprqÚWHEELrr) rbrcrr*r€r{r|rÚdict)r<r†rƒr„r‹rŒrÚmessager,r,r-r}ôs  zWheel.get_wheel_metadatac Cs6tj |j|j¡}t|dƒ}| |¡}W5QRX|S)Nrs)r6rGr*rardrr})r<r?r†rHr,r,r-rlýs z Wheel.infoc CsÔt |¡}|r|| ¡}|d|…||d…}}d| ¡krBt}nt}t |¡}|rfd| ¡d}nd}||}||}nT| d¡}| d¡} |dks || kr¦d} n|||d…d krÀd } nd} t| |}|S) Nspythonwó éÿÿÿÿr4ó ó rrs ) Ú SHEBANG_RErfÚendÚlowerÚSHEBANG_PYTHONWÚSHEBANG_PYTHONÚSHEBANG_DETAIL_REÚgroupsÚfind) r<Údatar#r—ZshebangZdata_after_shebangZshebang_pythonÚargsZcrZlfZtermr,r,r-Úprocess_shebangs,       zWheel.process_shebangcCsh|dkr|j}ztt|ƒ}Wn tk r<td|ƒ‚YnX||ƒ ¡}t |¡ d¡  d¡}||fS)NzUnsupported hash algorithm: %ró=Úascii) Ú hash_kindÚgetattrÚhashlibÚAttributeErrorrÚdigestÚbase64Zurlsafe_b64encodeÚrstripÚdecode)r<ržr£ÚhasherrHr,r,r-Úget_hash"s zWheel.get_hashc Cs^t|ƒ}ttj ||¡ƒ}| |ddf¡| ¡t|ƒ}|D]}| |¡q@W5QRXdS)Nr&) ÚlistÚto_posixr6rGÚrelpathr)ÚsortrZwriterow)r<ÚrecordsZ record_pathÚbaseÚpÚwriterÚrowr,r,r-Ú write_record-s zWheel.write_recordc Cs®g}|\}}tt|jƒ}|D]P\}} t| dƒ} |  ¡} W5QRXd| | ¡} tj | ¡} |  || | f¡qtj  |d¡} |  || |¡t tj  |d¡ƒ}|  || f¡dS)NÚrbz%s=%sÚRECORD) r¤r¥r£r€Úreadr¬r6rGÚgetsizer)r*r¶r®)r<rlÚlibdirÚ archive_pathsr±Údistinfor„r«Úapr³Úfržr§Úsizer,r,r-Ú write_records6s    zWheel.write_recordsc CsFt|dtjƒ.}|D]"\}}t d||¡| ||¡qW5QRXdS)NÚwzWrote %s to %s in wheel)rÚzipfileZ ZIP_DEFLATEDÚloggerÚdebugÚwrite)r<r?r¼r†r¾r³r,r,r-Ú build_zipFs zWheel.build_zipc! sp|dkr i}tt‡fdd„dƒƒd}|dkrFd}tg}tg}tg}nd}tg}d g}d g}| d |¡|_| d |¡|_| d |¡|_ ˆ|} d|j |j f} d| } d| } g} dD]Þ}|ˆkrÄq¶ˆ|}t j  |¡r¶t  |¡D]°\}}}|D] }tt j  ||¡ƒ}t j  ||¡}tt j  | ||¡ƒ}|  ||f¡|dkrð| d¡sðt|dƒ}| ¡}W5QRX| |¡}t|dƒ}| |¡W5QRXqðqâq¶| }d}t  |¡D]¦\}}}||krþt|ƒD]8\}}t|ƒ}| d¡rÄt j  ||¡}||=qþqÄ|D]H}t|ƒ d¡rqt j  ||¡}tt j  ||¡ƒ}|  ||f¡qq¨t  |¡}|D]B}|dkr^tt j  ||¡ƒ}tt j  | |¡ƒ}|  ||f¡q^d|p®|jdtd|g}|jD] \}}}| d|||f¡qÆt j  |d¡}t|dƒ}| d |¡¡W5QRXtt j  | d¡ƒ}|  ||f¡| || f| | ¡t j  |j |j!¡} | "| | ¡| S) z‰ Build a wheel from files in specified paths, and use any specified tags when determining the name of the wheel. Ncs|ˆkSr0r,r1©Úpathsr,r-r3Tr4zWheel.build..)ÚpurelibÚplatlibrrËZfalseÚtruerXrYr]r^r_rpú%s.datarq)ržZheadersÚscriptsrÎú.exer·Úwbz .dist-info)z.pycz.pyo)r¸Z INSTALLERZSHAREDrzWheel-Version: %d.%dzGenerator: distlib %szRoot-Is-Purelib: %sz Tag: %s-%s-%srrÂÚ )#r­r ÚIMPVERÚABIÚARCHr\Úgetr]r^r_rbrcr6rGÚisdirÚwalkr r*r¯r®r)Úendswithr€r¹r rÆÚ enumerateÚlistdirÚ wheel_versionrrorÁrardrÇ)!r<rÉrorÛZlibkeyZis_pureZ default_pyverZ default_abiZ default_archr»rƒÚdata_dirr„r¼ÚkeyrGÚrootÚdirsÚfilesrŠr³Úrpr¾r¿ržr½ryÚdnr‡r]r^r_r?r,rÈr-ÚbuildLs”         ý  z Wheel.buildcCs | d¡S)zl Determine whether an archive entry should be skipped when verifying or installing. )r/z /RECORD.jws)rØ)r<Úarcnamer,r,r-Ú skip_entry´szWheel.skip_entrycC Ksf|j}| d¡}| dd¡}| dd¡}tj |j|j¡}d|j|jf} d| } d| } t  | t ¡} t  | d¡} t  | d ¡}t   d ¡}t |d ƒÈ}| | ¡}||ƒ}t|ƒ}W5QRX|d  d d¡}tdd„|Dƒƒ}||jkrø|rø||j|ƒ|ddkr|d}n|d}i}| |¡8}t|d"}|D]}|d}|||<q8W5QRXW5QRXt  | d¡}t  | d¡}t  | dd¡}t|d}d|_tj } g}!t ¡}"|"|_d|_zŽz\| ¡D]´}#|#j}$t|$t ƒrè|$}%n |$ !d ¡}%| "|%¡rqÊ||%}|dr4t#|#j$ƒ|dkr4t%d|%ƒ‚|dr–|d dd¡\}&}'| |$¡}| &¡}(W5QRX| '|(|&¡\})}*|*|'kr–t%d|$ƒ‚|r¼|% (||f¡r¼t) *d |%¡qÊ|% (|¡oÒ|% +d!¡ }+|% (|¡r |% d"d¡\})},}-tj ||,t,|-ƒ¡}.n$|%| |fkrqÊtj |t,|%ƒ¡}.|+s | |$¡}| -||.¡W5QRX|! .|.¡|s´|dr´t|.d#ƒ4}| &¡}(| '|(|&¡\})}/|/|*krªt%d$|.ƒ‚W5QRX| r~|. +d%¡r~z|j/|.|d&}0|! .|0¡Wn$t0k rt)j1d'dd(YnXnttj 2t,|$ƒ¡}1tj |"|1¡}2| |$¡}| -||2¡W5QRXtj |.¡\}3}1|3|_| 3|1¡}4| 4|4¡|! 5|4¡qÊ|ršt) *d)¡d}5nnd}6|j6d }|d*krzt  | d+¡}7z˜| |7¡}t7|ƒ}8W5QRXi}6d,D]l}9d-|9}:|:|8kræi|6d.|9<};|8|: 8¡D]6}|6 d6i¡}?|>s|?r¨| dd¡}@tj >|@¡s*t?d7ƒ‚|@|_|> @¡D]*\}:}.zRoot-Is-PurelibrÌrÊrË©Ústreamrr&rÎ)Údry_runTNrúsize mismatch for %sú=údigest mismatch for %szlib_only: skipping %srÏr/r·zdigest mismatch on write for %sz.py)Zhashed_invalidationzByte-compilation failed)Úexc_infozlib_only: returning Nonez1.0zentry_points.txt)ZconsoleÚguiz %s_scriptszwrap_%sz%s:%sz %szAUnable to read legacy script metadata, so cannot generate scriptsr@zpython.commandsz8Unable to read JSON metadata, so cannot generate scriptsZ wrap_consoleZwrap_guizValid script path not specifiedz%s = %srïÚlibÚprefixzinstallation failed.)GrêrÕr6rGr*rardrbrcrrr{r|rr€rrhr~rÛrrÚrecordrJÚdont_write_bytecodeÚtempfileZmkdtempZ source_dirZ target_dirÚshutilZrmtreeÚinfolistÚ isinstancer rªråÚstrÚ file_sizerr¹r¬Ú startswithrÄrÅrØrZ copy_streamr)Z byte_compileÚ ExceptionZwarningÚbasenameZmakeZset_executable_modeÚextendrlrÚvaluesrñÚsuffixÚflagsÚjsonÚloadrÖr‚Úitemsr rZwrite_shared_locationsZwrite_installed_filesZ exceptionZrollback)Cr<rÉZmakerÚkwargsrêrærçZbc_hashed_invalidationr?rƒrÜr„Ú metadata_nameÚwheel_metadata_nameÚ record_namer…r†Úbwfrr‘rˆr‰r»r±rŒÚreaderrµr³Zdata_pfxZinfo_pfxZ script_pfxZfileopZbcZoutfilesÚworkdirÚzinforäÚ u_arcnameÚkindÚvalueržr r§Z is_scriptÚwhereráZoutfileZ newdigestZpycrŠZworknamerâÚ filenamesZdistZcommandsZepZepdatarÝrCr"rDÚsZconsole_scriptsZ gui_scriptsZ script_dirZscriptZoptionsr,r,r-ÚinstallÄsT                   ÿ   ÿ   ÿ     þÿÿ                     ÿ  z Wheel.installcCs4tdkr0tj tƒtdƒtjdd…¡}t|ƒatS)Nz dylib-cacheé) Úcacher6rGr*rrørJrcr)r<r²r,r,r-Ú_get_dylib_cacheªs  ÿzWheel._get_dylib_cachec Cshtj |j|j¡}d|j|jf}d|}t |d¡}t  d¡}g}t |dƒ}zð|  |¡Ü}||ƒ} t   | ¡} | ¡} |  |¡} tj | j| ¡} tj | ¡sªt | ¡|  ¡D]‚\}}tj | t|ƒ¡}tj |¡sÞd}n6t |¡j}tj |¡}| |¡}tj|jŽ}||k}|r&| || ¡| ||f¡q²W5QRXWntk rXYnXW5QRX|S)NrprqZ EXTENSIONSrrrsT)r6rGr*rardrbrcrr{r|rr€rrrZ prefix_to_dirr²rÖÚmakedirsrrrnÚstatÚst_mtimeÚdatetimeZ fromtimestampZgetinfoZ date_timeÚextractr)r)r<r?rƒr„rär…rHr†rŒrr@rrñZ cache_baserbr¯ÚdestrZ file_timerlZ wheel_timer,r,r-Ú_get_extensions³s>             zWheel._get_extensionscCst|ƒS)zM Determine if a wheel is compatible with the running system. )Ú is_compatibler;r,r,r-rÕszWheel.is_compatiblecCsdS)zP Determine if a wheel is asserted as mountable by its metadata. Tr,r;r,r,r-Ú is_mountableÛszWheel.is_mountablecCs´tj tj |j|j¡¡}| ¡s2d|}t|ƒ‚| ¡sJd|}t|ƒ‚|t jkrbt   d|¡nN|rtt j  |¡nt j  d|¡| ¡}|r°tt jkr¤t j  t¡t ||¡dS)Nz)Wheel %s not compatible with this Python.z$Wheel %s is marked as not mountable.z%s already in pathr)r6rGrjr*rardrrrrJrÄrÅr)ÚinsertrÚ_hookÚ meta_pathrA)r<r)r?Úmsgr@r,r,r-Úmountás"   z Wheel.mountcCsrtj tj |j|j¡¡}|tjkr2t d|¡n.rèrr/ú..úinvalid entry in wheel: %rrrërìrí)r6rGr*rardrbrcrrr{r|rr€rrhr~rrör÷r rªrrårørùr¹r¬)r<r?rƒrÜr„rrrr…r†rrr‘rˆr‰r±rŒr rµr³r rär r rržr r§r,r,r-rks\            ÿ ÿ   ÿz Wheel.verifyc KsØdd„}dd„}tj |j|j¡}d|j|jf}d|}t |d¡} tƒ€} t |dƒ|} i} |   ¡D]h} | j}t |t ƒr‚|}n |  d ¡}|| kr–qhd |krªtd |ƒ‚|  | | ¡tj | t|ƒ¡}|| |<qhW5QRX|| |ƒ\}}|| f|Ž}|rÊ|| |ƒ\}}|r$||kr$|||ƒ|d krNtjd d| d\}}t |¡n*tj |¡shtd|ƒ‚tj ||j¡}t|  ¡ƒ}tj | |¡}||f}| || |¡| ||¡|d krÊt ||¡W5QRX|S)a‘ Update the contents of a wheel in a generic way. The modifier should be a callable which expects a dictionary argument: its keys are archive-entry paths, and its values are absolute filesystem paths where the contents the corresponding archive entries can be found. The modifier is free to change the contents of the files pointed to, add new entries and remove entries, before returning. This method will extract the entire contents of the wheel to a temporary location, call the modifier, and then use the passed (and possibly updated) dictionary to write a new wheel. If ``dest_dir`` is specified, the new wheel is written there -- otherwise, the original wheel is overwritten. The modifier should return True if it updated the wheel, else False. This method returns the same value the modifier returns. cSsHd}}d|tf}||kr$d|}||kr@||}t|dj}||fS)Nz%s/%sz %s/PKG-INFO©rG)rr rc)Úpath_mapr„rcrGrÝr,r,r-Ú get_versionKs  z!Wheel.update..get_versioncSsâd}z|t|ƒ}| d¡}|dkr*d|}nTdd„||dd… d¡Dƒ}|dd7<d |d|…d d d „|Dƒ¡f}Wn tk r t d |¡YnX|rÞt|d }||_|  t ¡ }|j ||dt d||¡dS)Nrrz%s+1cSsg|] }t|ƒ‘qSr,ru)rxrr,r,r-rz]sz8Wheel.update..update_version..rr!r“z%s+%scss|]}t|ƒVqdSr0)rørwr,r,r-Ú `sz7Wheel.update..update_version..z0Cannot update non-compliant (PEP-440) version %rr')rGÚlegacyzVersion updated from %r to %r) rrrhr*rrÄrÅr rcrØrrÆ)rcrGÚupdatedrDryr+Zmdr+r,r,r-Úupdate_versionUs.    ÿ ÿ   ÿz$Wheel.update..update_versionrprqr¸rsrrr%r&Nz.whlz wheel-update-)rÿrñÚdirzNot a directory: %r)r6rGr*rardrbrcrrrrör÷r rªrrrrôZmkstempÚcloserÖr­rrÁrÇrõZcopyfile)r<ZmodifierZdest_dirrr)r-r?rƒr„rr r†r(r rär rGZoriginal_versionr ZmodifiedZcurrent_versionÚfdÚnewpathr¼r½rlr,r,r-r>:s\       ÿ    þ      z Wheel.update)NFF)N)NN)F)N)rSrTrUÚ__doc__rÛr£r=ÚpropertyrdrnrorrŽr}rlr r¬r¶rÁrÇrãrårrrrrr#r$rkr>r,r,r,r-rVˆs@ )         hg "  8rVc Csxtg}td}ttjddddƒD]}| d |t|ƒg¡¡q$g}t ¡D]*\}}}|  d¡rN| |  dd¡d¡qN|  ¡t dkr–|  dt ¡| d¡g}tg}tjd krŽt d t¡}|rŽ| ¡\} }}} t|ƒ}| g} | d krø|  d ¡| d kr |  d¡| dkr |  d¡| dkr4|  d¡| dkrH|  d¡|dkrŽ| D]*} d| ||| f} | tkrV| | ¡qV|d8}qH|D]0}|D]$} | d t|df¡|| f¡qšq’t|ƒD]L\}}| d t|f¡ddf¡|dkrÌ| d t|df¡ddf¡qÌt|ƒD]L\}}| d d|f¡ddf¡|dkr"| d d|df¡ddf¡q"t|ƒS)zG Return (pyver, abi, arch) tuples compatible with this Python. rrr“r&z.abir!rrXÚdarwinz(\w+)_(\d+)_(\d+)_(\w+)$)Úi386ÚppcZfat)r5r6Úx86_64Zfat3)Úppc64r7Zfat64)r5r7Úintel)r5r7r9r6r8Z universalz %s_%s_%s_%srYr)r'ÚrangerJÚ version_infor)r*rørMZ get_suffixesrúrhr°rÓrrÔÚplatformÚrerfrœrvÚ IMP_PREFIXrÙÚset)ZversionsÚmajorÚminorZabisrÿr rHZarchesr#rbr_Zmatchesrfrr^ryrcr,r,r-Úcompatible_tagsŸs`                 & " "rBcCs\t|tƒst|ƒ}d}|dkr"t}|D]0\}}}||jkr&||jkr&||jkr&d}qXq&|S)NFT)r÷rVÚCOMPATIBLE_TAGSr]r^r_)ZwheelrorHZverr^r_r,r,r-râs r)N)TZ __future__rr¨r{rZdistutils.utilZ distutilsZemailrr¥rMrZloggingr6rr=rõrJrôrÃr&rrÚcompatrrr r r Zdatabaser rŽr rrÚutilrrrrrrrrrrcrrZ getLoggerrSrÄrÚhasattrr>r<rúr(r'r;r\rÒZ get_platformr5rÔrÓr.ÚcompileÚ IGNORECASEÚVERBOSErirer–r›ršr™r7r®Úobjectr8r rVrBrCrr,r,r,r-ÚsŠ   ,       ø  ü    #>