abc@s0dZddlmZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl m Z mZddlmZddlmZmZddlmZmZmZdd lmZmZmZmZmZmZmZd d d d dgZ ej!e"Z#dZ$dZ%deddde$dfZ&dZ'de(fdYZ)de(fdYZ*de(fdYZ+de+fdYZ,de,fd YZ-d!e,fd"YZ.e-Z/e.Z0d#e(fd$YZ1d%d&Z2d'Z3d(Z4d)Z5dS(*uPEP 376 implementation.i(tunicode_literalsNi(tDistlibExceptiont resources(tStringIO(t get_schemetUnsupportedVersionError(tMetadatatMETADATA_FILENAMEtWHEEL_METADATA_FILENAME(tparse_requirementtcached_propertytparse_name_and_versiont read_exportst write_exportst CSVReadert CSVWriteru DistributionuBaseInstalledDistributionuInstalledDistributionuEggInfoDistributionuDistributionPathupydist-exports.jsonupydist-commands.jsonu INSTALLERuRECORDu REQUESTEDu RESOURCESuSHAREDu .dist-infot_CachecBs)eZdZdZdZdZRS(uL A simple cache mapping names and .dist-info paths to distributions cCsi|_i|_t|_dS(uZ Initialise an instance. There is normally one for each DistributionPath. N(tnametpathtFalset generated(tself((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt__init__0s  cCs'|jj|jjt|_dS(uC Clear the cache, setting it to its initial state. N(RtclearRRR(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR8s  cCsH|j|jkrD||j|j<|jj|jgj|ndS(u` Add a distribution to the cache. :param dist: The distribution to add. N(RRt setdefaulttkeytappend(Rtdist((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytadd@s(t__name__t __module__t__doc__RRR(((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR,s  tDistributionPathcBseZdZd edZdZdZeeeZ dZ dZ dZ e dZdZd Zd d Zd Zd d ZRS(uU Represents a set of distributions installed on a path (typically sys.path). cCsg|dkrtj}n||_t|_||_t|_t|_t|_ t d|_ dS(u Create an instance from a path, optionally including legacy (distutils/ setuptools/distribute) distributions. :param path: The path to use, as a list of directories. If not specified, sys.path is used. :param include_egg: If True, this instance will look for and return legacy distributions as well as those based on PEP 376. udefaultN( tNonetsysRtTruet _include_distt _include_eggRt_cachet _cache_eggt_cache_enabledRt_scheme(RRt include_egg((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRNs        cCs|jS(N(R((R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_get_cache_enabledbscCs ||_dS(N(R((Rtvalue((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_set_cache_enabledescCs|jj|jjdS(u, Clears the internal cache. N(R&RR'(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt clear_cachejs c cst}x|jD]}tj|}|dkr:qn|jd}| s|j r`qnt|j}x^|D]V}|j|}| sv|j|krqvn|jr}|j t r}t t g}x<|D]1}t j||} |j| } | rPqqWqvtj| j} td| dd} WdQXtjd|j|j|jt|jd| d|Vqv|jrv|j d rvtjd|j|j|jt|j|VqvqvWqWdS( uD Yield .dist-info and/or .egg(-info) distributions. utfileobjtschemeulegacyNuFound %stmetadatatenvu .egg-infou.egg(u .egg-infou.egg(tsetRRtfinder_for_pathR!tfindt is_containertsortedR$tendswitht DISTINFO_EXTRRt posixpathtjoint contextlibtclosingt as_streamRtloggertdebugRtnew_dist_classR%told_dist_class( RtseenRtfindertrtrsettentrytpossible_filenamestmetadata_filenamet metadata_pathtpydisttstreamR1((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_yield_distributionsrs@       cCs|jj }|jo |jj }|s/|rxF|jD]8}t|trd|jj|q<|jj|q<W|rt|j_n|rt|j_qndS(uk Scan the path for distributions and populate the cache with those that are found. N( R&RR%R'RMt isinstancetInstalledDistributionRR#(Rtgen_disttgen_eggR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_generate_caches  cCs)|jdd}dj||gtS(uo The *name* and *version* parameters are converted into their filename-escaped form, i.e. any ``'-'`` characters are replaced with ``'_'`` other than the one in ``'dist-info'`` and the one separating the name from the version number. :parameter name: is converted to a standard distribution name by replacing any runs of non- alphanumeric characters with a single ``'-'``. :type name: string :parameter version: is converted to a standard version string. Spaces become dots, and all other non-alphanumeric characters (except dots) become dashes, with runs of multiple dashes condensed to a single dash. :type version: string :returns: directory name :rtype: stringu-u_(treplaceR;R9(tclsRtversion((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytdistinfo_dirnamesccs|js(xv|jD] }|VqWnZ|jx|jjjD] }|VqEW|jrx"|jjjD] }|VqpWndS(u5 Provides an iterator that looks for distributions and returns :class:`InstalledDistribution` or :class:`EggInfoDistribution` instances for each one of them. :rtype: iterator of :class:`InstalledDistribution` and :class:`EggInfoDistribution` instances N(R(RMRRR&RtvaluesR%R'(RR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytget_distributionss     cCsd}|j}|jsNx|jD]}|j|kr(|}Pq(q(Wne|j||jjkr|jj|d}n2|jr||j jkr|j j|d}n|S(u= Looks for a named distribution on the path. This function only returns the first result found, as no more than one value is expected. If nothing is found, ``None`` is returned. :rtype: :class:`InstalledDistribution`, :class:`EggInfoDistribution` or ``None`` iN( R!tlowerR(RMRRRR&RR%R'(RRtresultR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytget_distributions     c csd}|dk r_y |jjd||f}Wq_tk r[td||fq_Xnx|jD]z}|j}xh|D]`}t|\}}|dkr||kr|VPqq||kr|j|r|VPqqWqlWdS(u Iterates over all distributions to find which distributions provide *name*. If a *version* is provided, it will be used to filter the results. This function only returns the first result found, since no more than one values are expected. If the directory is not found, returns ``None``. :parameter version: a version specifier that indicates the version required, conforming to the format in ``PEP-345`` :type name: string :type version: string u%s (%s)uinvalid name or version: %r, %rN( R!R)tmatchert ValueErrorRRXtprovidesR tmatch( RRRUR\Rtprovidedtptp_nametp_ver((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytprovides_distributions$       cCs;|j|}|dkr.td|n|j|S(u5 Return the path to a resource file. uno distribution named %r foundN(R[R!t LookupErrortget_resource_path(RRt relative_pathR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt get_file_paths ccsxy|jD]k}|j}||kr ||}|dk rY||kru||Vquqxx|jD] }|VqfWq q WdS(u Return all of the exported entries in a particular category. :param category: The category to search for entries. :param name: If specified, only entries with that name are returned. N(RXtexportsR!RW(RtcategoryRRREtdtv((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytget_exported_entries"s     N(RRRR!RRR+R-tpropertyt cache_enabledR.RMRRt classmethodRVRXR[RdRhRm(((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR Js    *    $ t DistributioncBseZdZeZeZdZedZeZ edZ edZ dZ edZ edZedZed Zed Zd Zd Zd ZdZRS(u A base class for distributions, whether installed or from indexes. Either way, it must have some metadata, so that's all that's needed for construction. cCsp||_|j|_|jj|_|j|_d|_d|_d|_d|_ t |_ i|_ dS(u Initialise an instance. :param metadata: The instance of :class:`Metadata` describing this distribution. N( R1RRYRRUR!tlocatortdigesttextrastcontextR3t download_urlstdigests(RR1((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRGs        cCs |jjS(uH The source archive download URL for this distribution. (R1t source_url(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRxXscCsd|j|jfS(uX A utility property which displays the name and version in parentheses. u%s (%s)(RRU(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytname_and_versionascCsB|jj}d|j|jf}||kr>|j|n|S(u A set of distribution names and versions provided by this distribution. :return: A set of "name (version)" strings. u%s (%s)(R1R^RRUR(Rtplistts((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR^hs   cCsS|j}tjd|jt||}t|j|d|jd|jS(Nu%Getting requirements from metadata %rRtR2( R1R?R@ttodicttgetattrR3tget_requirementsRtRu(Rtreq_attrtmdtreqts((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_get_requirementsts  cCs |jdS(Nu run_requires(R(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt run_requires{scCs |jdS(Nu meta_requires(R(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt meta_requiresscCs |jdS(Nubuild_requires(R(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytbuild_requiresscCs |jdS(Nu test_requires(R(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt test_requiresscCs |jdS(Nu dev_requires(R(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt dev_requiressc Cst|}t|jj}y|j|j}Wn@tk rvtjd||j d}|j|}nX|j }t }x]|j D]R}t |\}} ||krqny|j| }PWqtk rqXqW|S(u Say if this instance matches (fulfills) a requirement. :param req: The requirement to match. :rtype req: str :return: True if it matches, else False. u+could not read version %r - using name onlyi(R RR1R0R\t requirementRR?twarningtsplitRRR^R R_( RtreqRER0R\RRZRaRbRc((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytmatches_requirements*      cCs6|jrd|j}nd}d|j|j|fS(uC Return a textual representation of this instance, u [%s]uu(RxRRU(Rtsuffix((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt__repr__s cCs[t|t|k r!t}n6|j|jkoT|j|jkoT|j|jk}|S(u< See if this distribution is the same as another. :param other: The distribution to compare with. To be equal to one another. distributions must have the same type, name, version and source_url. :return: True if it is the same, else False. (ttypeRRRURx(RtotherRZ((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt__eq__s  cCs't|jt|jt|jS(uH Compute hash in a way which matches the equality test. (thashRRURx(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt__hash__s(RRRRtbuild_time_dependencyt requestedRRnRxt download_urlRyR^RRRRRRRRRR(((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRq5s$   " tBaseInstalledDistributioncBs,eZdZdZddZddZRS(u] This is the base class for installed distributions (whether PEP 376 or legacy). cCs,tt|j|||_||_dS(u Initialise an instance. :param metadata: An instance of :class:`Metadata` which describes the distribution. This will normally have been initialised from a metadata file in the ``path``. :param path: The path of the ``.dist-info`` or ``.egg-info`` directory for the distribution. :param env: This is normally the :class:`DistributionPath` instance where this distribution was found. N(tsuperRRRt dist_path(RR1RR2((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs  cCs|dkr|j}n|dkr6tj}d}ntt|}d|j}||j}tj|jdj d}d||fS(u Get the hash of some data, using a particular hash algorithm, if specified. :param data: The data to be hashed. :type data: bytes :param hasher: The name of a hash implementation, supported by hashlib, or ``None``. Examples of valid values are ``'sha1'``, ``'sha224'``, ``'sha384'``, '``sha256'``, ``'md5'`` and ``'sha512'``. If no hasher is specified, the ``hasher`` attribute of the :class:`InstalledDistribution` instance is used. If the hasher is determined to be ``None``, MD5 is used as the hashing algorithm. :returns: The hash of the data. If a hasher was explicitly specified, the returned hash will be prefixed with the specified hasher followed by '='. :rtype: str uu%s=t=uasciiu%s%sN( R!thasherthashlibtmd5R}Rstbase64turlsafe_b64encodetrstriptdecode(RtdataRtprefixRs((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytget_hashs      !N(RRRR!RRR(((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs ROcBseZdZdZdddZdZdZdZe dZ dZ dZ d Z d Zed Zd Ze d ZedZdZdZdZdZejZRS(u  Created with the *path* of the ``.dist-info`` directory provided to the constructor. It reads the metadata contained in ``pydist.json`` when it is instantiated., or uses a passed in Metadata instance (useful for when dry-run mode is being used). usha256c Cstj||_}|dkr;ddl}|jn|rr|jrr||jjkrr|jj|j }n|dkr$|j t }|dkr|j t }n|dkr|j d}n|dkrt dt |fntj|j}td|dd}WdQXntt|j||||rb|jrb|jj|ny|j d}Wn'tk rddl}|jnX|dk |_dS(NiuMETADATAuno %s found in %sR/R0ulegacyu REQUESTED(RR4RDR!tpdbt set_traceR(R&RR1R5RRR]R<R=R>RRRORRtAttributeErrorR(RRR1R2RDRRERL((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs4  !       cCsd|j|j|jfS(Nu#(RRUR(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR2scCsd|j|jfS(Nu%s %s(RRU(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt__str__6sc Csg}|jd}tj|j}td|i}x_|D]W}gtt|dD] }d^qb}||\}} } |j|| | fqFWWdQXWdQX|S(u" Get the list of installed files for the distribution :return: A list of tuples of path, hash and size. Note that hash and size might be ``None`` for some entries. The path is exactly as stored in the file (which is as in PEP 376). uRECORDRLiN( tget_distinfo_resourceR<R=R>RtrangetlenR!R( RtresultsRERLt record_readertrowtitmissingRtchecksumtsize((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt _get_records9s (&cCs.i}|jt}|r*|j}n|S(u Return the information exported by this distribution. :return: A dictionary of exports, mapping an export category to a dict of :class:`ExportEntry` instances describing the individual export entries, and keyed by name. (RtEXPORTS_FILENAMER (RRZRE((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRiPs cCsLi}|jt}|rHtj|j}t|}WdQXn|S(u Read exports data from a file in .ini format. :return: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. N(RRR<R=R>R (RRZRERL((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR ^s cCs8|jt}t|d}t||WdQXdS(u Write a dictionary of exports to a file in .ini format. :param exports: A dictionary of exports, mapping an export category to a list of :class:`ExportEntry` instances describing the individual export entries. uwN(tget_distinfo_fileRtopenR (RRitrftf((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR msc Cs|jd}tj|jF}td|.}x$|D]\}}||kr@|Sq@WWdQXWdQXtd|dS(uW NOTE: This API may change in the future. Return the absolute path to a resource file with the given relative path. :param relative_path: The path, relative to .dist-info, of the resource of interest. :return: The absolute path where the resource is to be found. u RESOURCESRLNu3no resource file with relative path %r is installed(RR<R=R>RtKeyError(RRgRERLtresources_readertrelativet destination((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRfxs  ccs x|jD] }|Vq WdS(u Iterates over the ``RECORD`` entries and returns a tuple ``(path, hash, size)`` for each line. :returns: iterator of (path, hash, size) N(R(RRZ((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytlist_installed_filessc Cstjj|d}tjj|j}|j|}tjj|d}|jd}tjd||rwdSt |}x|D]}tjj |s|j d rd} } nCdtjj |} t |d} |j| j} WdQX|j|s(|r@|j|r@tjj||}n|j|| | fqW|j|rtjj||}n|j|ddfWdQX|S( u Writes the ``RECORD`` file, using the ``paths`` iterable passed in. Any existing ``RECORD`` file is silently overwritten. prefix is used to determine when to write absolute paths. uuRECORDu creating %su.pycu.pyou%durbN(u.pycu.pyo(tosRR;tdirnamet startswithRR?tinfoR!RtisdirR8tgetsizeRRtreadtrelpathtwriterow( RtpathsRtdry_runtbasetbase_under_prefixt record_pathtwriterRt hash_valueRtfp((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytwrite_installed_filess. ! c Csg}tjj|j}|jd}xn|jD]`\}}}tjj|sptjj||}n||krq7ntjj|s|j|dt t fq7tjj |r7t tjj |}|r||kr|j|d||fq|rd|kr3|jddd}nd }t|dG} |j| j|} | |kr|j|d|| fnWd QXqq7q7W|S( u Checks that the hashes and sizes of the files in ``RECORD`` are matched by the files themselves. Returns a (possibly empty) list of mismatches. Each entry in the mismatch list will be a tuple consisting of the path, 'exists', 'size' or 'hash' according to what didn't match (existence is checked first, then size, then hash), the expected value and the actual value. uRECORDuexistsusizeu=iiurbuhashN(RRRRRtisabsR;texistsRR#RtisfiletstrRRR!RRR( Rt mismatchesRRRRRt actual_sizeRRt actual_hash((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytcheck_installed_filess.    ,cCsi}tjj|jd}tjj|rtj|ddd}|jj}WdQXx[|D]P}|jdd\}}|dkr|j |gj |qj|||su%s (%s)( RtstripRR?RR Rtt constraintsRRR;(RtreqsRRREtcons((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytparse_requires_dataos&       csRg}y4tj|dd}|j}WdQXWntk rMnX|S(uCreate a list of dependencies from a requires.txt file. *req_path*: the path to a setuptools-produced requires.txt file. uruutf-8N(RRRtIOError(treq_pathRR(R(s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytparse_requires_paths u.egguEGG-INFOuPKG-INFORR0ulegacyu requires.txtuEGG-INFO/PKG-INFOuutf8R/uEGG-INFO/requires.txtuutf-8u .egg-infou,path must end with .egg-info or .egg, got %r(R!R8RRRR;Rt zipimportt zipimporterRtget_dataRRRtadd_requirements( RRtrequiresRt meta_pathR1RtzipfR/R((Rs@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRls:     cCsd|j|j|jfS(Nu!(RRUR(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRscCsd|j|jfS(Nu%s %s(RRU(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRscCsg}tjj|jd}tjj|rx`|jD]O\}}}||kr^q=ntjj|s=|j|dttfq=q=Wn|S(u Checks that the hashes and sizes of the files in ``RECORD`` are matched by the files themselves. Returns a (possibly empty) list of mismatches. Each entry in the mismatch list will be a tuple consisting of the path, 'exists', 'size' or 'hash' according to what didn't match (existence is checked first, then size, then hash), the expected value and the actual value. uinstalled-files.txtuexists(RRR;RRRR#R(RRRRt_((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs  #c Cs2d}d}tjj|jd}g}tjj|r.tj|ddd}x|D]}|j}tjjtjj|j|}tjj|stj d||j d rqdqntjj |sd|j |||||fqdqdWWd QX|j |d d fn|S( u Iterates over the ``installed-files.txt`` entries and returns a tuple ``(path, hash, size)`` for each line. :returns: a list of (path, hash, size) cSs@t|d}z|j}Wd|jXtj|jS(Nurb(RRtcloseRRt hexdigest(RRtcontent((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_md5s  cSstj|jS(N(Rtstattst_size(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyt_sizesuinstalled-files.txturRuutf-8uNon-existent file: %su.pycu.pyoN(u.pycu.pyo(RRR;RRRRtnormpathR?RR8RRR!(RRRRRZRRRa((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs"    $ /c cstjj|jd}t}tj|ddd}x|D]}|j}|dkrjt}q@n|s@tjjtjj|j|}|j |jr|r|Vq|Vqq@q@WWdQXdS(u  Iterates over the ``installed-files.txt`` entries and returns paths for each line if the path is pointing to a file located in the ``.egg-info`` directory or one of its subdirectories. :parameter absolute: If *absolute* is ``True``, each returned path is transformed into a local absolute path. Otherwise the raw value from ``installed-files.txt`` is returned. :type absolute: boolean :returns: iterator of paths uinstalled-files.txturRuutf-8u./N( RRR;R#RRRRRR(RtabsoluteRtskipRRRa((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRs    $cCst|to|j|jkS(N(RNRR(RR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRsN(RRRR#RRR!RRRRRRRRRRR(((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyRNs  K    &  tDependencyGraphcBsheZdZdZdZd dZdZdZddZ e dZ d Z d Z RS( u Represents a dependency graph between distributions. The dependency relationships are stored in an ``adjacency_list`` that maps distributions to a list of ``(other, label)`` tuples where ``other`` is a distribution and the edge is labeled with ``label`` (i.e. the version specifier, if such was provided). Also, for more efficient traversal, for every distribution ``x``, a list of predecessors is kept in ``reverse_list[x]``. An edge from distribution ``a`` to distribution ``b`` means that ``a`` depends on ``b``. If any missing dependencies are found, they are stored in ``missing``, which is a dictionary that maps distributions to a list of requirements that were not provided by any other distributions. cCsi|_i|_i|_dS(N(tadjacency_listt reverse_listR(R((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pyR.s  cCsg|j| "%s" [label="%s"] u "%s" -> "%s" usubgraph disconnected { ulabel = "Disconnected" ubgcolor = red u"%s"u u} N(RRtitemsRRR!R(RRtskip_disconnectedt disconnectedRtadjsRR((s@/usr/lib/python2.7/site-packages/pip/_vendor/distlib/database.pytto_dotgs&    %    cCs=g}i}x(|jjD]\}}|||t|jD])\}}|sZ|j|||=qZqZW|sPnxO|jD]A\}}g|D]$\}}||kr||f^q||sL         4  7F 6