o )aΛ@sdZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl ZddlZddlZddlZddlmZddlZddlmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#ddl$m%Z%ddl&m'Z'ddl(m)Z)ddl*m+Z+dd l,m-Z-e.d Z/e.d ej0Z1e.d Z2e.d ej0j3Z4d5Z6gdZ7dZ8dZ9e9j:dj:ej;edZddZ?dBddZ@dBddZAdBddZBdedfd d!ZCd"d#ZDe.d$ej0ZEeDd%d&ZFGd'd(d(ZGGd)d*d*eGZHGd+d,d,eZIe.d-jJZKd.d/ZLd0d1ZMdCd2d3ZNd4d5ZOGd6d7d7ZPGd8d9d9e jQZRejSjTfd:d;ZUdd?ZWd@dAZXdS)Dz#PyPI and direct package downloadingNwraps) CHECKOUT_DIST Distribution BINARY_DISTnormalize_path SOURCE_DIST Environmentfind_distributions safe_name safe_version to_filename Requirement DEVELOP_DISTEGG_DIST)log)DistutilsError) translate)Wheelunique_everseenz^egg=([-A-Za-z0-9_.+!]+)$zhref\s*=\s*['"]?([^'"> ]+)z([^<]+)\n\s+\(md5\)z([-+.a-z0-9]{2,}):z.tar.gz .tar.bz2 .tar .zip .tgz) PackageIndexdistros_for_urlparse_bdist_wininstinterpret_distro_namezr$) r'rZ from_locationrZ is_compatiblerHrIrrrr EXTENSIONSlen)rGbasenamerCZwheelZwin_baser+platformZextr!r!r"r?ps4     r?cCstt|tj||S)zEYield possible egg or source distribution objects based on a filename)r?rosr:rL)filenamerCr!r!r"distros_for_filenamesrPc cs~|d}|stdd|ddDrdStdt|dD]}t||d|d|d||d|||dVq dS)zGenerate alternative interpretations of a source distro name Note: if `location` is a filesystem filename, you should call ``pkg_resources.normalize_path()`` on it before passing it to this routine! rFcss|] }td|VqdS)z py\d\.\d$N)rerA).0pr!r!r" sz(interpret_distro_name..Nr1) py_versionr>rM)r5anyrangerKrjoin)rGrLrCrVr>rMr7rSr!r!r"rs $ rcstfdd}|S)zs Wrap a function returning an iterable such that the resulting iterable only ever yields unique items. cst|i|SNr)argskwargsfuncr!r"wrapperszunique_values..wrapperr)r^r_r!r]r" unique_valuessr`z(<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>c cst|D]2}|\}}tttj|d}d|vs#d|vr8t |D]}t j |t |dVq(qdD] }||}|dkr[t ||}|r[t j |t |dVq;dS)zEFind rel="homepage" and rel="download" links in `page`, yielding URLs,Zhomepager.r1)z Home PagezDownload URLr-N)RELfinditergroupssetmapstrstripr&r5HREFr2rurljoin htmldecoderBfindsearch)r6pagerAtagrelZrelsposr!r!r"find_external_linkss    rrc@(eZdZdZddZddZddZdS) ContentCheckerzP A null content checker that defines the interface for checking content cCdS)z3 Feed a block of data to the hash. Nr!selfblockr!r!r"feedzContentChecker.feedcCru)zC Check the hash. Return False if validation fails. Tr!rwr!r!r"is_validrzzContentChecker.is_validcCru)zu Call reporter with information about the checker (hash name) substituted into the template. Nr!)rwreportertemplater!r!r"reportszContentChecker.reportN)__name__ __module__ __qualname____doc__ryr|rr!r!r!r"rts  rtc@sBeZdZedZddZeddZddZ dd Z d d Z d S) HashCheckerzK(?Psha1|sha224|sha384|sha256|sha512|md5)=(?P[a-f0-9]+)cCs||_t||_||_dSrZ) hash_namehashlibnewhashexpected)rwrrr!r!r"__init__s  zHashChecker.__init__cCsBtj|d}|s tS|j|}|stS|di|S)z5Construct a (possibly null) ContentChecker from a URLr-Nr!)r2rr3rtpatternrm groupdict)clsr6r<rAr!r!r"from_urls zHashChecker.from_urlcCs|j|dSrZ)rupdatervr!r!r"ryzHashChecker.feedcCs|j|jkSrZ)rZ hexdigestrr{r!r!r"r|rzHashChecker.is_validcCs||j}||SrZ)r)rwr}r~msgr!r!r"rs zHashChecker.reportN) rrrrQcompilerr classmethodrryr|rr!r!r!r"rs   rcsLeZdZdZ  dLddZdMd d ZdMd d ZdMd dZddZddZ ddZ ddZ ddZ dNddZ ddZdNfdd Zdd Zd!d"Zd#d$Zd%d&Zd'd(Z  dOd)d*ZdPd+d,Zd-d.Zd/Zd0d1Zd2d3ZdNd4d5Zd6d7Zd8d9Zd:d;Zdd?Z e!dMd@dAZ"dBdCZ#dDdEZ$dFdGZ%dHdIZ&dJdKZ'Z(S)Qrz;A distribution index that scans web pages for download URLshttps://pypi.org/simple/*NTcOsrtj|g|Ri||dd|d |_i|_i|_i|_td t t |j |_ g|_tjj|_dS)Nr,|)r rr' index_url scanned_urls fetched_urls package_pagesrQrrYrfrrAallowsto_scanr2requesturlopenopener)rwrZhostsZ ca_bundleZ verify_sslr[kwr!r!r"rszPackageIndex.__init__Fc Cs||jvr |s dSd|j|<t|s||dStt|}|r.||s(dS|d||s7|r7||jvrAtt|j |dS||sMd|j|<dS| d|d|j|<d}| |||}|durhdSt |t jjr||jdkr|| d|jd|j|j<d|jd d vr|dS|j}|}t |tst |t jjrd }n|jd pd }||d }|t|D]} t j|t| d} |!| q|"|j#rt$|dddkr|%||}dSdSdS)z.)filterrNr:rr itertoolsstarmap scan_egg_link)rwZ search_pathdirsZ egg_linksr!r!r"scan_egg_links|s zPackageIndex.scan_egg_linkscCsttj||}ttdttj|}Wdn1swYt |dkr,dS|\}}t tj||D]}tjj|g|R|_ t |_ ||q9dS)NrU)openrNr:rYrrrfrgrhrKr rGrr>r)rwr:rZ raw_lineslinesZegg_pathZ setup_pathrDr!r!r"rs  zPackageIndex.scan_egg_linkcCsd}||js |Stttjj|t|jdd}t|dks)d|dvr+|St |d}t |d}d|j | i|<t|t|fS)N)NNr,rUr0r1rT)r(rrrfr2rr4rKr5r r r setdefaultr&r )rwrZNO_MATCH_SENTINELr7pkgverr!r!r"_scans   zPackageIndex._scanc Cst|D]}z|tj|t|dWqty!Yqw||\}}|s-dSt ||D]$}t |\}}| drQ|sQ|rL|d||f7}n| || |q2tdd|S)z#Process the contents of a PyPI pager1r.pyz #egg=%s-%scSsd|dddS)Nz%sr1rU)rB)mr!r!r"sz,PackageIndex.process_index..)rircrr2rrjrkrBrrrr=r'need_version_infoscan_urlPYPI_MD5sub) rwr6rnrArrnew_urlr*fragr!r!r"rs&"    zPackageIndex.process_indexcCs|d|dS)NzPPage at %s links to .py file(s) without version info; an index scan is required.)scan_allrwr6r!r!r"rszPackageIndex.need_version_infocGs<|j|jvr|r|j|g|R|d||jdS)Nz6Scanning index of all packages (this may take a while))rrrrrrwrr[r!r!r"rs zPackageIndex.scan_allcCsz||j|jd|j|js||j|jd|j|js)||t|j|jdD]}||q3dS)Nr,r!) rr unsafe_namerrkeyrHnot_found_in_indexr)rw requirementr6r!r!r" find_packagess  zPackageIndex.find_packagescsR|||||jD]}||vr|S|d||qtt|||S)Nz%s does not match %s)prescanrrrsuperrobtain)rwrZ installerrD __class__r!r"rs zPackageIndex.obtaincCsL||jd||s$|t|td|jjtj |fdS)z- checker is a ContentChecker zValidating %%s checksum for %sz7%s validation failed for %s; possible download problem?N) rrr|rrNunlinkrrr)r:rL)rwcheckerrOtfpr!r!r" check_hashs zPackageIndex.check_hashcCsN|D]"}|jdust|r|dstt|r||q|j|qdS)z;Add `urls` to the list that will be prescanned for searchesNfile:)rrr(rrrappend)rwZurlsr6r!r!r"add_find_linkss  zPackageIndex.add_find_linkscCs"|jr tt|j|jd|_dS)z7Scan urls scheduled for prescanning (e.g. --find-links)N)rrrfrr{r!r!r"r s zPackageIndex.prescancCs<||jr |jd}}n|jd}}|||j|dS)Nz#Couldn't retrieve index page for %rz3Couldn't find index page for %r (maybe misspelled?))rrrrr)rwrZmethrr!r!r"rs   zPackageIndex.not_found_in_indexcCs~t|ts5t|}|r)||d||}t|\}}|dr'||||}|Stj |r1|St |}t | ||ddS)aLocate and/or download `spec` to `tmpdir`, returning a local path `spec` may be a ``Requirement`` object, or a string containing a URL, an existing local filename, or a project/version requirement spec (i.e. the string form of a ``Requirement`` object). If it is the URL of a .py file with an unambiguous ``#egg=name-version`` tag (i.e., one that escapes ``-`` as ``_`` throughout), a trivial ``setup.py`` is automatically created alongside the downloaded file. If `spec` is a ``Requirement`` object or a string containing a project/version requirement spec, this method returns the location of a matching distribution (possibly after downloading it to `tmpdir`). If `spec` is a locally existing file or directory name, it is simply returned unchanged. If `spec` is a URL, it is downloaded to a subpath of `tmpdir`, and the local filename is returned. Various errors may be raised if a problem occurs during downloading. r1rrGN)rrr _download_urlrBr=r' gen_setuprNr:rr#rfetch_distribution)rwrtmpdirr8foundr*r<r!r!r"r.s    zPackageIndex.downloadc sd|id}d fdd }|r$|||}|s/|dur/|||}|dur@jdur<||}|durO|sO|||}|dur`drZdp[d|dSd||j|jd S) a|Obtain a distribution suitable for fulfilling `requirement` `requirement` must be a ``pkg_resources.Requirement`` instance. If necessary, or if the `force_scan` flag is set, the requirement is searched for in the (online) package index as well as the locally installed packages. If a distribution matching `requirement` is found, the returned distribution's ``location`` is the value you would have gotten from calling the ``download()`` method with the matching distribution's URL or filename. If no matching distribution is found, ``None`` is returned. If the `source` flag is set, only source distributions and source checkout links will be considered. Unless the `develop_ok` flag is set, development and system eggs (i.e., those using the ``.egg-info`` format) will be ignored. zSearching for %sNcs|dur}||jD];}|jtkr#s#|vr"d|d|<q ||vo.|jtkp. }|rF|j}||_tj |jrF|Sq dS)Nz&Skipping development or system egg: %sr1) rr>rrrr.rGdownload_locationrNr:r)ZreqenvrDtestZloc develop_okrwZskippedsourcerr!r"rlUs(z-PackageIndex.fetch_distribution..findz:No local packages or working download links found for %s%sza source distribution of rzBest match: %s)rGrZ)rrrrrZcloner) rwrr force_scanrrZ local_indexrDrlr!rr"r=s2         zPackageIndex.fetch_distributioncCs"|||||}|dur|jSdS)a3Obtain a file suitable for fulfilling `requirement` DEPRECATED; use the ``fetch_distribution()`` method now instead. For backward compatibility, this routine is identical but returns the ``location`` of the downloaded distribution instead of a distribution object. N)rrG)rwrrrrrDr!r!r"fetchszPackageIndex.fetchc Cs t|}|rddt||ddDpg}t|dkrxtj|}tj||krEtj ||}ddl m }|||sEt |||}ttj |dd} | d|dj|djtj|dfWd|S1sqwY|S|rtd ||ftd ) NcSsg|]}|jr|qSr!)rI)rRdr!r!r" s z*PackageIndex.gen_setup..r1r)samefilezsetup.pywzIfrom setuptools import setup setup(name=%r, version=%r, py_modules=[%r]) zCan't unambiguously interpret project/version identifier %r; any dashes in the name or version should be escaped using underscores. %rzpCan't process plain .py files without an '#egg=name-version' suffix to enable automatic setup script generation.)r@rArrBrKrNr:rLdirnamerYZsetuptools.command.easy_installrshutilZcopy2rwriterHrIsplitextr) rwrOr<rrArrLZdstrrr!r!r"rsF          zPackageIndex.gen_setupi c Cs2|d|d}zt|}||}t|tjjr%td||j |j f|}d}|j }d}d|vrI| d} t tt| }||||||t|d1} ||} | ro|| | | |d 7}||||||nqqqP|||| Wdn1swY|W|r|SS|r|ww) NzDownloading %szCan't download %s: %s %srr-zcontent-lengthzContent-LengthwbTr1)rrrrrr2rrrrr dl_blocksizeZget_allmaxrfint reporthookrrryr rr) rwr6rOfprrblocknumbssizeZsizesrrxr!r!r" _download_tosF            zPackageIndex._download_tocCsdSrZr!)rwr6rOrZblksizerr!r!r"rzPackageIndex.reporthookc Cs|dr t|Szt||jWSttjjfyD}z$ddd|j D}|r0| ||n t d||f|WYd}~dSd}~wt j jyY}z|WYd}~Sd}~wt j jy}z|rl| ||jn t d||jf|WYd}~dSd}~wtjjy}z|r| ||jn t d||jf|WYd}~dSd}~wtjjtj fy}z|r| ||n t d||f|WYd}~dSd}~ww)Nr cSsg|]}t|qSr!)rg)rRargr!r!r"rsz)PackageIndex.open_url..z%s %szDownload error for %s: %sz;%s returned a bad status line. The server might be down, %s)r( local_openopen_with_authrrhttpclient InvalidURLrYr[rrr2rrZURLErrorreasonZ BadStatusLinelineZ HTTPExceptionsocket)rwr6Zwarningvrr!r!r"rs^ zPackageIndex.open_urlcCst|\}}|rd|vr|dddd}d|vs nd}|dr(|dd}tj||}|dks8|d r>|||S|d ksG|d rM|||S|d rX| ||S|d krht j t j |dS||d|||S)Nz...\_Z__downloaded__rEr%svnzsvn+gitzgit+zhg+rrUT)r=replacer'rNr:rYr( _download_svn _download_git _download_hgr2r url2pathnamerr3r_attempt_download)rwr8r6rr)r<rOr!r!r"r s(         zPackageIndex._download_urlcCs||ddS)NT)rrr!r!r"r)rzPackageIndex.scan_urlcCs2|||}d|ddvr||||S|S)Nrrr)rrr&_download_html)rwr6rOrr!r!r"r+,s zPackageIndex._attempt_downloadcCsjt|}|D]}|r%td|r#|t||||Sq&q|t|td|)Nz ([^- ]+ - )?Revision \d+:zUnexpected HTML page found at ) r���rh���rQ���rm���r���rN���r���r'��r���)rw���r6���r���rO���r���r��r!���r!���r"���r,��3��s���    zPackageIndex._download_htmlc�����������������C���s��t�dt�|ddd�}d}|�drqd|v�rqtj|\}}}}}} |sq|drqd |d d��v�rq|d d��d d\}}t |\} } | rqd | v�r]| d d\} } d | | f�}nd | �}| }|||||| f}tj |}|� d||�t d|||f��|S�)Nz"SVN download support is deprecatedr0���r1���r���r���zsvn:@z//r,���rU���:z --username=%s --password=%sz --username=z'Doing subversion checkout from %s to %szsvn checkout%s -q %s %s)warningsr��� UserWarningr5���r&���r(���r2���r���r3��� _splituser urlunparser���rN���system)rw���r6���rO���Zcredsr8���netlocr:���rS���qr���authhostuserZpwr7���r!���r!���r"���r'��B��s&���   zPackageIndex._download_svnc�����������������C���sp���t�j|�\}}}}}|ddd�}|ddd�}d�}d|v�r)|dd\}}t�j||||df}�|�|fS�)N+r1���r-���r0���r���r-��r���)r2���r���urlsplitr5���rsplit urlunsplit)r6��� pop_prefixr8���r4��r:���r;���r���revr!���r!���r"���_vcs_split_rev_from_urlX��s���z$PackageIndex._vcs_split_rev_from_urlc�����������������C���l���|�ddd�}|�j|dd\}}|�d||�td||f��|d�ur4|�d|�td ||f��|S�) Nr0���r1���r���Tr=��zDoing git clone from %s to %szgit clone --quiet %s %szChecking out %szgit -C %s checkout --quiet %sr5���r?��r���rN���r3��rw���r6���rO���r>��r!���r!���r"���r(��j����� zPackageIndex._download_gitc�����������������C���r@��) Nr0���r1���r���TrA��zDoing hg clone from %s to %szhg clone --quiet %s %szUpdating to %szhg --cwd %s up -C -r %s -qrB��rC��r!���r!���r"���r)��z��rD��zPackageIndex._download_hgc�����������������G������t�j|g|R���d�S�rZ���)r���r���r���r!���r!���r"���r��������zPackageIndex.debugc�����������������G���rE��rZ���)r���r���r���r!���r!���r"���r�����rF��zPackageIndex.infoc�����������������G���rE��rZ���)r���r���r���r!���r!���r"���r�����rF��zPackageIndex.warn)r���r���NT)FrZ���)FFFN)FF))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���r���r���r+��r,��r'�� staticmethodr?��r(��r)��r���r���r��� __classcell__r!���r!���r���r"���r�����sT����  5       # L )$ # r���z!&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?c�����������������C���s���|��d}t|S�)Nr���)rB���r���Zunescape)rA���Zwhatr!���r!���r"��� decode_entity��s���  rI��c�����������������C���s ���t�t|�S�)a�� Decode HTML entities in the given text. >>> htmldecode( ... 'https://../package_name-0.1.2.tar.gz' ... '?tokena=A&tokenb=B">package_name-0.1.2.tar.gz') 'https://../package_name-0.1.2.tar.gz?tokena=A&tokenb=B">package_name-0.1.2.tar.gz' ) entity_subrI��)textr!���r!���r"���rk�����s��� rk���c��������������������s����fdd}|S�)Nc��������������������s����fdd}|S�)Nc��������������� ������s:���t��}t��z �|�i�|W�t�|�S�t�|�w�rZ���)r��ZgetdefaulttimeoutZsetdefaulttimeout)r[���r\���Z old_timeout)r^���timeoutr!���r"���_socket_timeout��s ��� z@socket_timeout.<locals>._socket_timeout.<locals>._socket_timeoutr!���)r^���rM��rL��r]���r"���rM����s���z'socket_timeout.<locals>._socket_timeoutr!���)rL��rM��r!���rN��r"���socket_timeout��s���  rO��c�����������������C���s2���t�j|�}|�}t|}|�}|ddS�)a9�� Encode auth from a URL suitable for an HTTP header. >>> str(_encode_auth('username%3Apassword')) 'dXNlcm5hbWU6cGFzc3dvcmQ=' Long auth strings should not cause a newline to be inserted. >>> long_auth = 'username:' + 'password'*10 >>> chr(10) in str(_encode_auth(long_auth)) False  r���)r2���r���r4���encodebase64Z b64encoder���r&��)r6��Zauth_sZ auth_bytesZ encoded_bytesZencodedr!���r!���r"��� _encode_auth��s ���   rS��c�������������������@���rs���) Credentialz: A username/password pair. Use like a namedtuple. c�����������������C���s���||�_�||�_d�S�rZ���usernamepassword)rw���rV��rW��r!���r!���r"���r�����s��� zCredential.__init__c�����������������c���s����|�j�V��|�jV��d�S�rZ���rU��r{���r!���r!���r"���__iter__��s��� zCredential.__iter__c�����������������C���s ���dt�|��S�)Nz%(username)s:%(password)s)varsr{���r!���r!���r"���__str__��s��� zCredential.__str__N)r���r���r���r���r���rX��rZ��r!���r!���r!���r"���rT����s ���� rT��c�������������������@���s0���e�Zd�Zdd�Zedd�Zdd�Zdd�Zd S�) PyPIConfigc�����������������C���sR���t�g�dd}tj|�|�tjtjdd}tj |r'|� |�dS�dS�)z% Load from ~/.pypirc )rV��rW�� repositoryr���~z.pypircN) dictfromkeys configparserRawConfigParserr���rN���r:���rY��� expanduserr���r���)rw���defaultsZrcr!���r!���r"���r�����s ��� zPyPIConfig.__init__c��������������������s&����fdd���D�}tt�j|S�)Nc��������������������s ���g�|�] }��|d��r|qS�)r\��)r���rh���)rR���sectionr{���r!���r"���r����s ����z2PyPIConfig.creds_by_repository.<locals>.<listcomp>)Zsectionsr^��rf���_get_repo_cred)rw���Zsections_with_repositoriesr!���r{���r"���creds_by_repository��s��� zPyPIConfig.creds_by_repositoryc�����������������C���s6���|��|d�}|t|��|d�|��|d�fS�)Nr\��rV��rW��)r���rh���rT��)rw���rd��Zrepor!���r!���r"���re����s ���zPyPIConfig._get_repo_credc�����������������C���s*���|�j��D�] \}}||r|��S�qdS�)z If the URL indicated appears to be a repository defined in this config, return the credential for that repository. N)rf��itemsr(���)rw���r6���r\��credr!���r!���r"���find_credential��s ��� zPyPIConfig.find_credentialN)r���r���r���r���propertyrf��re��ri��r!���r!���r!���r"���r[����s ����  r[��c�����������������C���s:��t�j|�}|\}}}}}}|drtjd|dv�r$t|\} } nd} | sBt� |�} | rBt | } | j |�f} t j dg| R���| redt| �} || ||||f} t�j| }t�j|}|d| �nt�j|�}|dt�||}| rt�j|j\}}}}}}||kr|| kr||||||f} t�j| |_|S�) z4Open a urllib2 request, handling HTTP authenticationr.��znonnumeric port: '')r��httpsNz*Authenticating as %s for %s (from .pypirc)zBasic Z Authorizationz User-Agent)r2���r���r3���r'���r��r��r��r1��r[��ri��rg���rV��r���r���rS��r2��r���ZRequestZ add_header user_agentr6���)r6���r���parsedr8���r4��r:���paramsr;���r���r6��Zaddressrh��r���r7���r���r���r��s2Zh2Zpath2Zparam2Zquery2Zfrag2r!���r!���r"���r����s8���          r��c�����������������C���s$���|��d\}}}�|r||�fS�d|�fS�)zNsplituser('user[:passwd]@host[:port]') --> 'user[:passwd]', 'host[:port]'.r-��N) rpartition)r7��r8��delimr!���r!���r"���r1��4��s���r1��c�����������������C���s���|�S�rZ���r!���)r6���r!���r!���r"��� fix_sf_url?��r��rr��c�������������� ���C���s*��t�j|�\}}}}}}t�j|}tj|rt�j|�S�| dr}tj |r}g�}t |D�];} tj || } | dkrXt | d } | �} W�d���n1�sQw���Y���qxtj | rb| d7�} |dj| d�q0d} | j|�d |d } d \}}nd \}}} d d i}t| }t�j|�||||S�)z7Read a local path, with special support for directoriesr,���z index.htmlrNz<a href="{name}">{name}</a>)r)���zB<html><head><title>{url}{files}rP)r6files)ZOK)rzPath not foundz Not foundrz text/html)r2rr3rr*rNr:isfilerr'rrrYrrrformatioStringIOrr)r6r8r9r:Zparamr;rrOrtrfilepathrbodyrZstatusmessagerZ body_streamr!r!r"rCs0         rrZ)r)YrsysrNrQrxrrrRrrr/r`rZ http.clientr urllib.parser2Zurllib.requestZ urllib.error functoolsrrZ pkg_resourcesrrrrrr r r r r rrrZ distutilsrZdistutils.errorsrfnmatchrZsetuptools.wheelrZ setuptools.extern.more_itertoolsrrr@IrirrArr5rJ__all__Z_SOCKET_TIMEOUTZ_tmplrw version_inforlr#rr=rr?rPrr`rbrrrtrrrrJrIrkrOrSrTrar[rrrr1rrrr!r!r!r"s <          ! #  !  &/